Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: STM32F3-Discovery
Diff: space_invaders.c
- Revision:
- 0:404dae88af71
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/space_invaders.c Tue Mar 01 02:40:19 2016 +0000
@@ -0,0 +1,1093 @@
+/***************************************************************************
+ * STM32 VGA demo
+ * Copyright (C) 2012 Artekit Italy
+ * http://www.artekit.eu
+ * Written by Ruben H. Meleca
+
+### space_invaders.c
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+***************************************************************************/
+
+#include "stm32f30x.h"
+#include "sys.h"
+#include "video.h"
+#include "gdi.h"
+#include "space_invaders.h"
+//#include <string.h>
+//#include <stdio.h>
+//#include <stdlib.h>
+
+extern volatile u32 sysTicks;
+
+
+
+
+extern u8 siLogo[VID_VSIZE][VID_HSIZE];
+
+//extern volatile u32 sysTicks;
+
+const u8 siBadBoys99[] = { 0x00, 0x00,
+ 0x00, 0x00,
+ 0x21, 0x08,
+ 0x11, 0x10,
+ 0x09, 0x20,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x09, 0x20,
+ 0x11, 0x10,
+ 0x21, 0x08,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+
+const u8 siBadBoys00[] = { 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+
+const u8 siBadBoys01[] = { 0x00, 0x00,
+ 0x00, 0x00,
+ 0x03, 0x80,
+ 0x07, 0xc0,
+ 0x0f, 0xe0,
+ 0x1b, 0xb0,
+ 0x1f, 0xf0,
+ 0x04, 0x40,
+ 0x0b, 0xa0,
+ 0x14, 0x50,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+
+const u8 siBadBoys02[] = { 0x00, 0x00,
+ 0x00, 0x00,
+ 0x03, 0x80,
+ 0x07, 0xc0,
+ 0x0f, 0xe0,
+ 0x1b, 0xb0,
+ 0x1f, 0xf0,
+ 0x04, 0x40,
+ 0x0b, 0xa0,
+ 0x08, 0x20,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+
+
+const u8 siBadBoys11[] = { 0x00, 0x00,
+ 0x00, 0x00,
+ 0x08, 0x20,
+ 0x04, 0x40,
+ 0x0f, 0xe0,
+ 0x1b, 0xb0,
+ 0x3f, 0xf8,
+ 0x2f, 0xe8,
+ 0x28, 0x28,
+ 0x06, 0xc0,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+
+const u8 siBadBoys12[] = { 0x00, 0x00,
+ 0x00, 0x00,
+ 0x08, 0x20,
+ 0x24, 0x48,
+ 0x2f, 0xe8,
+ 0x3b, 0xb8,
+ 0x3f, 0xf8,
+ 0x1f, 0xf0,
+ 0x08, 0x20,
+ 0x10, 0x10,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+
+const u8 siBadBoys21[] = { 0x00, 0x00,
+ 0x00, 0x00,
+ 0x07, 0xc0,
+ 0x1f, 0xf0,
+ 0x3f, 0xf8,
+ 0x33, 0x98,
+ 0x3f, 0xf8,
+ 0x0c, 0x60,
+ 0x1b, 0xb0,
+ 0x30, 0x18,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+
+const u8 siBadBoys22[] = { 0x00, 0x00,
+ 0x00, 0x00,
+ 0x07, 0xc0,
+ 0x1f, 0xf0,
+ 0x3f, 0xf8,
+ 0x33, 0x98,
+ 0x3f, 0xf8,
+ 0x0c, 0x60,
+ 0x1b, 0xb0,
+ 0x0c, 0x60,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+
+const u8 siGoodBoys[] = { 0x00, 0x18, 0x00,
+ 0x00, 0x18, 0x00,
+ 0x00, 0x3c, 0x00,
+ 0x00, 0xff, 0x00,
+ 0x0f, 0xff, 0xf0,
+ 0x3f, 0xff, 0xfc,
+ 0x3f, 0xff, 0xfc,
+ 0x3f, 0xff, 0xfc,
+ 0x3c, 0x00, 0x3c };
+
+const u8 siGoodBoysBlk[] = { 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00 };
+
+const u8 siBadBomb00[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+const u8 siBadBomb01[] = { 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x40,
+ 0x80, 0x40, 0x20, 0x40, 0x80, 0x40, 0x20 };
+const u8 siBadBomb02[] = { 0x00, 0x00, 0x00, 0x20, 0x40, 0x80, 0x40,
+ 0x20, 0x40, 0x80, 0x40, 0x20, 0x40, 0x80 };
+
+const u8 siGoodBomb1[] = { 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00 };
+const u8 siGoodBomb2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+
+const u8 siDefs1[] = { 0xe0, 0xe0, 0xe0, 0xe0, 0xe0 };
+const u8 siDefs2[] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+void numtostr(char *buffer,int n);
+
+const pu8 siVesselPoints[] = {
+ "= 30 POINTS",
+ "= 20 POINTS",
+ "= 10 POINTS" };
+
+const pu8 siPressKey = "PRESS ANY BUTTON TO START GAME";
+
+#define CCM __attribute__ ((section (".ccmram"))) static
+
+static SI_BADBOY sibb[SI_MAXBADBOYS_ROWS][SI_MAXBADBOYS_COLS];
+static SI_BOMB siBomb[SI_MAXBADBOYSBOMB];
+
+static SI_DEFENSE sidef1[SI_MAXDEFENSES_ROWS][SI_MAXDEFENSES_COLS];
+static SI_DEFENSE sidef2[SI_MAXDEFENSES_ROWS][SI_MAXDEFENSES_COLS];
+static SI_DEFENSE sidef3[SI_MAXDEFENSES_ROWS][SI_MAXDEFENSES_COLS];
+static SI_DEFENSE sidef4[SI_MAXDEFENSES_ROWS][SI_MAXDEFENSES_COLS];
+
+static i16 siXGoodBoy = SI_GOODBOYSTART_X;
+static i16 siYGoodBoy = SI_GOODBOYSTART_Y;
+
+static i16 siGoodBoyCount;
+static i16 siGoodBoyCountOld;
+
+static i16 siGoodBoysKeyDelay;
+static i16 siGoodBombDelay;
+static i16 siGoodBombActive;
+static i16 siGoodBombX;
+static i16 siGoodBombY;
+static i16 siGoodBombKeyState;
+
+static i16 siCurrentScore;
+static i16 siBakScore;
+static i16 siBestScore;
+
+static i16 siBadBoysDelay;
+static i16 siBadBoysShiftX;
+static i16 siBadBoysShiftY;
+static i16 siBadBoysMode;
+static i16 siBadBoysFlip;
+static i16 siBadBoysYCount;
+static i16 siBadBoysBombDelay;
+static i16 siBadBombMoveDelay;
+static i16 siBadBoysCount; // Count Bad Boys. If 0, you win
+static i16 siBadBoyBombOK = 1; // 1 = fire bombs, 0 = No
+
+static u8 siScore[24];
+static float AccBuffer[3] = {0.0f};
+
+
+//#undef static
+
+u8 siAnyButtonPressed(void) {
+
+u32 b;
+
+ b = GPIOA->IDR;
+ return (b&SI_FIRE_BUTTON);
+ if ((b & 0x00000001) != (SI_FIRE_BUTTON/* | SI_LEFT_BUTTON | SI_RIGHT_BUTTON*/)) return(1);
+ return(0);
+}
+
+void siYouWin(void) {
+
+ vidClearScreen();
+ gdiRectangle(0,0,(VID_PIXELS_X - 1),VID_VSIZE - 1,0);
+
+ gdiDrawTextEx(167,80,"* YOU WIN *",GDI_ROP_XOR);
+ while(1) {
+ if (siAnyButtonPressed()) return;
+ gdiDrawTextEx(108,170,siPressKey,GDI_ROP_XOR);
+ sysDelayMs(400);
+ if (siAnyButtonPressed()) return;
+ gdiDrawTextEx(108,170,siPressKey,GDI_ROP_XOR);
+ if (siAnyButtonPressed()) return;
+ sysDelayMs(200);
+ };
+}
+
+void siYouLose(void) {
+
+ vidClearScreen();
+ gdiRectangle(0,0,(VID_PIXELS_X - 1),VID_VSIZE - 1,0);
+
+ gdiDrawTextEx(164,80,"* YOU LOSE *",GDI_ROP_XOR);
+ while(1) {
+ if (siAnyButtonPressed()) return;
+ gdiDrawTextEx(108,170,siPressKey,GDI_ROP_XOR);
+ sysDelayMs(400);
+ if (siAnyButtonPressed()) return;
+ gdiDrawTextEx(108,170,siPressKey,GDI_ROP_XOR);
+ if (siAnyButtonPressed()) return;
+ sysDelayMs(200);
+ };
+
+}
+
+char * strcpy(char *dest, char *src) {
+ while(*dest++=*src++);
+ return dest;
+}
+
+int strlen(const char *str)
+{
+ const char *s;
+ for (s = str; *s; ++s)
+ ;
+ return (s - str);
+}
+
+void siInitialScreen(void) {
+
+u16 i, x, y, l, j;
+pu8 ptr = NULL;
+u8 buf[] = " ";
+
+ vidClearScreen();
+
+ gdiRectangle(0,0,(VID_PIXELS_X - 1),VID_VSIZE - 1,0);
+
+ gdiDrawTextEx(180, 40, "ARTEKIT", GDI_ROP_COPY);
+ gdiDrawTextEx(156, 55, "SPACE INVADERS", GDI_ROP_COPY);
+ gdiDrawTextEx(180, 70, "LEVEL I", GDI_ROP_COPY);
+
+ sysDelayMs(1000);
+
+ gdiDrawTextEx(130,110,"* SCORE ADVANCE TABLE *",GDI_ROP_XOR);
+ sysDelayMs(400);
+ y = 125;
+ for (i = 0; i < 3; i++) {
+ x = 155;
+ switch(i) {
+ case 0: ptr = (pu8) siBadBoys01;
+ break;
+ case 1: ptr = (pu8) siBadBoys11;
+ break;
+ case 2: ptr = (pu8) siBadBoys21;
+ break;
+ }
+ gdiBitBlt(NULL,x,y,15,12,ptr,GDI_ROP_COPY);
+ x += 20;
+ l = strlen((const char*)siVesselPoints[i]);
+ ptr = siVesselPoints[i];
+ for (j = 0; j < l; j++) {
+ sysDelayMs(25);
+ buf[0] = *ptr++;
+ gdiDrawTextEx(x,y + 2,buf,GDI_ROP_COPY);
+ x += 6;
+ }
+ y += 12;
+ sysDelayMs(300);
+ }
+ while(1) {
+ if (siAnyButtonPressed()) return;
+ gdiDrawTextEx(108,170,siPressKey,GDI_ROP_XOR);
+ sysDelayMs(400);
+ if (siAnyButtonPressed()) return;
+ gdiDrawTextEx(108,170,siPressKey,GDI_ROP_XOR);
+ if (siAnyButtonPressed()) return;
+ sysDelayMs(200);
+
+ };
+
+}
+int leftcol, rtcol, count, shiftdown=0;
+
+CCM void siShiftBadboys(void) {
+
+ if(shiftdown>0) {
+ siBadBoysShiftY += 2;
+ shiftdown--;
+ } else {
+ if (!siBadBoysMode) {
+ if (++siBadBoysShiftX+rtcol*20 >= 288) {
+ siBadBoysMode = 1;
+ siBadBoysShiftX -= 2;
+ siBadBoysShiftY += 2;
+ shiftdown=8;
+ if (siBadBoysYCount < 459) siBadBoysYCount += SI_BADBOYSSPEEDCOUNT;
+ } else {
+ siBadBoysShiftX += 1;
+ }
+ } else {
+ if ( --siBadBoysShiftX+leftcol*20 < -10) {
+ siBadBoysMode = 0;
+ siBadBoysShiftX += 2;
+ siBadBoysShiftY += 2;
+ shiftdown=8;
+ if (siBadBoysYCount < 459) siBadBoysYCount += SI_BADBOYSSPEEDCOUNT;
+ } else {
+ siBadBoysShiftX -= 1;
+ }
+ }
+ }
+
+ (siBadBoysFlip == 0) ? (siBadBoysFlip = 1) : (siBadBoysFlip = 0);
+}
+
+
+CCM void siDrawBadboys(void) {
+
+u16 i, n;
+
+ if (--siBadBoysDelay > 0) return;
+ siBadBoysDelay = SI_BADBOYSSTARTDELAY - siBadBoysYCount;
+ leftcol=110;rtcol=0;count=0;
+ for (i = 0; i < SI_MAXBADBOYS_ROWS; i++) {
+ for (n = 0; n < SI_MAXBADBOYS_COLS; n++) {
+ if (sibb[i][n].mode == SI_ALIVE) {
+ count++;
+ if(n<leftcol)
+ leftcol=n;
+ if(n>rtcol)
+ rtcol=n;
+ if (!siBadBoysFlip) {
+ gdiBitBlt(NULL,sibb[i][n].x + siBadBoysShiftX,sibb[i][n].y + siBadBoysShiftY,15,12,sibb[i][n].b1,GDI_ROP_COPY);
+ } else {
+ gdiBitBlt(NULL,sibb[i][n].x + siBadBoysShiftX,sibb[i][n].y + siBadBoysShiftY,15,12,sibb[i][n].b2,GDI_ROP_COPY);
+ }
+ } else {
+ if (sibb[i][n].mode == SI_DESTROYED) {
+ sibb[i][n].mode = SI_CANCEL;
+ gdiBitBlt(NULL,sibb[i][n].x + siBadBoysShiftX,sibb[i][n].y + siBadBoysShiftY,15,12,(pu8) siBadBoys99,GDI_ROP_COPY);
+ } else {
+ if (sibb[i][n].mode == SI_CANCEL) {
+ sibb[i][n].mode = SI_DEAD;
+ gdiBitBlt(NULL,sibb[i][n].x + siBadBoysShiftX,sibb[i][n].y + siBadBoysShiftY,15,12,(pu8) siBadBoys00,GDI_ROP_COPY);
+ }
+ }
+ }
+ }
+ }
+ siShiftBadboys();
+ siBadBoysDelay = count*10;
+}
+
+CCM void siShowDefenses(void) {
+
+u16 i, j, n;
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < SI_MAXDEFENSES_ROWS; j++) {
+ for (n = 0; n < SI_MAXDEFENSES_COLS; n++) {
+ switch(i) {
+ case 0: if (sidef1[j][n].mode == SI_ALIVE) {
+ gdiBitBlt(NULL,sidef1[j][n].x,sidef1[j][n].y,3,5,(pu8) siDefs1,GDI_ROP_COPY);
+ } else {
+ gdiBitBlt(NULL,sidef1[j][n].x,sidef1[j][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ }
+ break;
+ case 1: if (sidef2[j][n].mode == SI_ALIVE) {
+ gdiBitBlt(NULL,sidef2[j][n].x,sidef2[j][n].y,3,5,(pu8) siDefs1,GDI_ROP_COPY);
+ } else {
+ gdiBitBlt(NULL,sidef2[j][n].x,sidef2[j][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ }
+ break;
+ case 2: if (sidef3[j][n].mode == SI_ALIVE) {
+ gdiBitBlt(NULL,sidef3[j][n].x,sidef3[j][n].y,3,5,(pu8) siDefs1,GDI_ROP_COPY);
+ } else {
+ gdiBitBlt(NULL,sidef3[j][n].x,sidef3[j][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ }
+ break;
+ case 3: if (sidef4[j][n].mode == SI_ALIVE) {
+ gdiBitBlt(NULL,sidef4[j][n].x,sidef4[j][n].y,3,5,(pu8) siDefs1,GDI_ROP_COPY);
+ } else {
+ gdiBitBlt(NULL,sidef4[j][n].x,sidef4[j][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ }
+ break;
+
+
+ }
+ }
+ }
+ }
+}
+CCM void siMoveGoodBoys(void) {
+
+ if (--siGoodBoysKeyDelay > 0) return;
+ siGoodBoysKeyDelay = SI_GOODBOYSKEYDELAY;
+ Demo_CompassReadAcc(AccBuffer);
+ int x=(int)AccBuffer[0];
+ int y=(int)AccBuffer[1];
+ int z=(int)AccBuffer[2];
+
+/*
+ numtostr(siScore,x);
+ gdiDrawTextEx(340,20,siScore,GDI_ROP_COPY);
+ numtostr(siScore,y);
+ gdiDrawTextEx(340,40,siScore,GDI_ROP_COPY);
+ numtostr(siScore,z);
+ gdiDrawTextEx(340,60,siScore,GDI_ROP_COPY);
+*/
+
+// if ((GPIOA->IDR & SI_LEFT_BUTTON) == 0) {
+ if (y<-100) {
+ if (siXGoodBoy > 8) {
+ siXGoodBoy -= 2;
+ gdiBitBlt(NULL,siXGoodBoy,siYGoodBoy,24,9,(pu8) siGoodBoys,GDI_ROP_COPY);
+ }
+ }
+// if ((GPIOA->IDR & SI_RIGHT_BUTTON) == 0) {
+ if (y>100) {
+ if (siXGoodBoy < 290) {
+ siXGoodBoy += 2;
+ gdiBitBlt(NULL,siXGoodBoy,siYGoodBoy,24,9,(pu8) siGoodBoys,GDI_ROP_COPY);
+ }
+ }
+
+
+}
+
+CCM void siMoveGoodBomb(void) {
+
+i16 d, i, n;
+
+ if (!siGoodBombActive) return;
+ if (--siGoodBombDelay > 0) return;
+ siGoodBombDelay = SI_GOODBOMBDELAY;
+
+ gdiBitBlt(NULL,siGoodBombX,siGoodBombY,2,6,(pu8) siGoodBomb1,GDI_ROP_COPY);
+
+// Test if bomb touch defenses
+
+ for (d = 0; d < 4; d++) {
+ for (i = 0; i < SI_MAXDEFENSES_ROWS; i++) {
+ for (n = 0; n < SI_MAXDEFENSES_COLS; n++) {
+ switch(d) {
+ case 0: if (sidef1[i][n].mode == SI_ALIVE) {
+ if (siGoodBombX >= sidef1[i][n].x && siGoodBombX <= (sidef1[i][n].x + 3)) {
+ if (siGoodBombY <= (sidef1[i][n].y + 5) && siGoodBombY >= sidef1[i][n].y) {
+ sidef1[i][n].mode = SI_DEAD;
+ gdiBitBlt(NULL,sidef1[i][n].x,sidef1[i][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siGoodBombX,siGoodBombY,2,6,(pu8) siGoodBomb2,GDI_ROP_COPY);
+ siGoodBombActive = 0;
+// siShowDefenses();
+ return;
+ }
+ }
+ }
+ break;
+ case 1: if (sidef2[i][n].mode == SI_ALIVE) {
+ if (siGoodBombX >= sidef2[i][n].x && siGoodBombX <= (sidef2[i][n].x + 3)) {
+ if (siGoodBombY <= (sidef2[i][n].y + 5) && siGoodBombY >= sidef2[i][n].y) {
+ sidef2[i][n].mode = SI_DEAD;
+ gdiBitBlt(NULL,sidef2[i][n].x,sidef2[i][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siGoodBombX,siGoodBombY,2,6,(pu8) siGoodBomb2,GDI_ROP_COPY);
+ siGoodBombActive = 0;
+// siShowDefenses();
+ return;
+ }
+ }
+ }
+ break;
+ case 2: if (sidef3[i][n].mode == SI_ALIVE) {
+ if (siGoodBombX >= sidef3[i][n].x && siGoodBombX <= (sidef3[i][n].x + 3)) {
+ if (siGoodBombY <= (sidef3[i][n].y + 5) && siGoodBombY >= sidef3[i][n].y) {
+ sidef3[i][n].mode = SI_DEAD;
+ gdiBitBlt(NULL,sidef3[i][n].x,sidef3[i][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siGoodBombX,siGoodBombY,2,6,(pu8) siGoodBomb2,GDI_ROP_COPY);
+ siGoodBombActive = 0;
+// siShowDefenses();
+ return;
+ }
+ }
+ }
+ break;
+ case 3: if (sidef4[i][n].mode == SI_ALIVE) {
+ if (siGoodBombX >= sidef4[i][n].x && siGoodBombX <= (sidef4[i][n].x + 3)) {
+ if (siGoodBombY <= (sidef4[i][n].y + 5) && siGoodBombY >= sidef4[i][n].y) {
+ sidef4[i][n].mode = SI_DEAD;
+ gdiBitBlt(NULL,sidef4[i][n].x,sidef4[i][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siGoodBombX,siGoodBombY,2,6,(pu8) siGoodBomb2,GDI_ROP_COPY);
+ siGoodBombActive = 0;
+// siShowDefenses();
+ return;
+ }
+ }
+ }
+ break;
+
+ }
+ }
+ }
+ }
+
+// Test if bomb touch any Bad Boy
+
+ for (i = 0; i < SI_MAXBADBOYS_ROWS; i++) {
+ for (n = 0; n < SI_MAXBADBOYS_COLS; n++) {
+ if (sibb[i][n].mode == SI_ALIVE) {
+ if (siGoodBombX >= (sibb[i][n].x + siBadBoysShiftX) && siGoodBombX <= (sibb[i][n].x + siBadBoysShiftX + 15)) {
+ if (siGoodBombY <= (sibb[i][n].y + siBadBoysShiftY + 12) && siGoodBombY >= (sibb[i][n].y + siBadBoysShiftY)) {
+ sibb[i][n].mode = SI_DESTROYED;
+// gdiBitBlt(NULL,sibb[i][n].x + siBadBoysShiftX,sibb[i][n].y + siBadBoysShiftY,15,12,(pu8) siBadBoys99,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siGoodBombX,siGoodBombY,2,6,(pu8) siGoodBomb2,GDI_ROP_COPY);
+ siGoodBombActive = 0;
+ --siBadBoysCount;
+ switch(i) {
+ case 0: siCurrentScore += 30; break;
+ case 1: siCurrentScore += 20; break;
+ case 2: siCurrentScore += 20; break;
+ case 3: siCurrentScore += 10; break;
+ }
+ return;
+ }
+ }
+ }
+ }
+ }
+
+
+ if (siGoodBombY < 5) {
+ gdiBitBlt(NULL,siGoodBombX,siGoodBombY,2,6,(pu8) siGoodBomb2,GDI_ROP_COPY);
+ siGoodBombActive = 0;
+ } else {
+ siGoodBombY -= 3;
+ }
+}
+
+void siGoodBombStart(void) {
+
+ if ((GPIOA->IDR & SI_FIRE_BUTTON) == 0) {
+ if (siGoodBombKeyState == 0 && siGoodBombActive == 0) {
+ siGoodBombX = siXGoodBoy + SI_GOODBOYSHOTPOINT;
+ siGoodBombY = SI_GOODBOYSTART_Y - 6;
+ siGoodBombActive = 1;
+ siGoodBombKeyState = 1;
+ }
+ } else {
+ siGoodBombKeyState = 0;
+ }
+
+}
+
+CCM void siBadBoysFire(void) {
+
+i16 i, r, col = 0, row = 0,x;
+
+ if (siBadBoyBombOK == 0) return; // Bomb disabled
+
+ if (--siBadBoysBombDelay != 0) return;
+ siBadBoysBombDelay = SI_BADBOYSBOMBDELAY;
+
+ srand(sysTicks);
+ r = rand();
+ if ((r & 0x03) == 0x01) { // Fire bomb
+
+// Select a random Bad Boy to fire bomb
+// Select a random Bad Boy to fire bomb
+ for(x=0;x<20;x++) {
+ col = rand() % SI_MAXBADBOYS_COLS;
+ for (row = (SI_MAXBADBOYS_ROWS - 1); row >= 0; row--) {
+ if (sibb[row][col].mode == SI_ALIVE){
+ for (i = 0; i < SI_MAXBADBOYSBOMB; i++) {
+ if (siBomb[i].mode == SI_DEAD) {
+ siBomb[i].x = sibb[row][col].x + 7 + siBadBoysShiftX;
+ siBomb[i].y = sibb[row][col].y + 12 + siBadBoysShiftY;
+ siBomb[i].mode = SI_ALIVE;
+ return;
+ }
+ }
+ }
+ }
+ }
+/*
+ while(1) {
+ col = rand() % SI_MAXBADBOYS_COLS;
+ for (row = (SI_MAXBADBOYS_ROWS - 1); row >= 0; row--) {
+ if (sibb[row][col].mode == SI_ALIVE) {
+ for (i = 0; i < SI_MAXBADBOYSBOMB; i++) {
+ if (siBomb[i].mode == SI_DEAD) {
+ siBomb[i].x = sibb[row][col].x + 7 + siBadBoysShiftX;
+ siBomb[i].y = sibb[row][col].y + 12 + siBadBoysShiftY;
+ siBomb[i].mode = SI_ALIVE;
+ return;
+ }
+ }
+ }
+ }
+ }
+*/
+ }
+
+}
+
+CCM i16 siDrawBadBoyBomb(void) {
+
+i16 i, v, d, n;
+i16 ret = 0;
+
+ siBadBoysFire();
+
+ if (--siBadBombMoveDelay != 0) return(ret);;
+ siBadBombMoveDelay = SI_BADBOMBMOVEDELAY;
+
+ for (v = 0; v < SI_MAXBADBOYSBOMB; v++) {
+ if (siBomb[v].mode == SI_ALIVE) {
+ if (siBomb[v].flip == 0) {
+ gdiBitBlt(NULL,siBomb[v].x,siBomb[v].y,3,14,(pu8) siBadBomb01,GDI_ROP_COPY);
+ siBomb[v].flip = 1;
+ } else {
+ gdiBitBlt(NULL,siBomb[v].x,siBomb[v].y,3,14,(pu8) siBadBomb02,GDI_ROP_COPY);
+ siBomb[v].flip = 0;
+ }
+
+// See if Bad Boys bomb touch defenses
+
+ for (d = 0; d < 4; d++) {
+ for (i = 0; i < SI_MAXDEFENSES_ROWS; i++) {
+ for (n = 0; n < SI_MAXDEFENSES_COLS; n++) {
+ switch(d) {
+ case 0: if (sidef1[i][n].mode == SI_ALIVE) {
+ if (siBomb[v].x >= sidef1[i][n].x && siBomb[v].x <= (sidef1[i][n].x + 3)) {
+ if ((siBomb[v].y + 12) >= sidef1[i][n].y && (siBomb[v].y + 12) <= (sidef1[i][n].y + 5)) {
+ sidef1[i][n].mode = SI_DEAD;
+ gdiBitBlt(NULL,sidef1[i][n].x,sidef1[i][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siBomb[v].x,siBomb[v].y,3,14,(pu8) siBadBomb00,GDI_ROP_COPY);
+ siBomb[v].mode = SI_DEAD;
+ }
+ }
+ }
+ break;
+ case 1: if (sidef2[i][n].mode == SI_ALIVE) {
+ if (siBomb[v].x >= sidef2[i][n].x && siBomb[v].x <= (sidef2[i][n].x + 3)) {
+ if ((siBomb[v].y + 12) >= sidef2[i][n].y && (siBomb[v].y + 12) <= (sidef2[i][n].y + 5)) {
+ sidef2[i][n].mode = SI_DEAD;
+ gdiBitBlt(NULL,sidef2[i][n].x,sidef2[i][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siBomb[v].x,siBomb[v].y,3,14,(pu8) siBadBomb00,GDI_ROP_COPY);
+ siBomb[v].mode = SI_DEAD;
+ }
+ }
+ }
+ break;
+ case 2: if (sidef3[i][n].mode == SI_ALIVE) {
+ if (siBomb[v].x >= sidef3[i][n].x && siBomb[v].x <= (sidef3[i][n].x + 3)) {
+ if ((siBomb[v].y + 12) >= sidef3[i][n].y && (siBomb[v].y + 12) <= (sidef3[i][n].y + 5)) {
+ sidef3[i][n].mode = SI_DEAD;
+ gdiBitBlt(NULL,sidef3[i][n].x,sidef3[i][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siBomb[v].x,siBomb[v].y,3,14,(pu8) siBadBomb00,GDI_ROP_COPY);
+ siBomb[v].mode = SI_DEAD;
+ }
+ }
+ }
+ break;
+ case 3: if (sidef4[i][n].mode == SI_ALIVE) {
+ if (siBomb[v].x >= sidef4[i][n].x && siBomb[v].x <= (sidef4[i][n].x + 3)) {
+ if ((siBomb[v].y + 12) >= sidef4[i][n].y && (siBomb[v].y + 12) <= (sidef4[i][n].y + 5)) {
+ sidef4[i][n].mode = SI_DEAD;
+ gdiBitBlt(NULL,sidef4[i][n].x,sidef4[i][n].y,3,5,(pu8) siDefs2,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siBomb[v].x,siBomb[v].y,3,14,(pu8) siBadBomb00,GDI_ROP_COPY);
+ siBomb[v].mode = SI_DEAD;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+// See if Bad Boys bomb touch Good Boy
+
+ if (siBomb[v].x >= siXGoodBoy && siBomb[v].x <= (siXGoodBoy + 24)) {
+ if ((siBomb[v].y + 12) >= siYGoodBoy && (siBomb[v].y + 12) <= (siYGoodBoy + 9)) {
+ gdiBitBlt(NULL,siBomb[v].x,siBomb[v].y,3,14,(pu8) siBadBomb00,GDI_ROP_COPY);
+ gdiBitBlt(NULL,siXGoodBoy,SI_GOODBOYSTART_Y,24,9,(pu8) siGoodBoysBlk,GDI_ROP_COPY);
+ ret = 1; // Good Boy was killed
+ }
+ }
+
+// Touch nothing, go ahead
+
+ if (siBomb[v].mode != SI_DEAD) {
+ siBomb[v].y += 3;
+ if (siBomb[v].y >= (VID_PIXELS_Y - 16)) {
+ gdiBitBlt(NULL,siBomb[v].x,siBomb[v].y - 3,3,14,(pu8) siBadBomb00,GDI_ROP_COPY);
+ siBomb[v].mode = SI_DEAD;
+ }
+ }
+ }
+ }
+ return(ret);
+}
+
+void siCancelAllBadBoms(void) {
+
+i16 i;
+
+ for (i = 0; i < SI_MAXBADBOYSBOMB; i++) {
+ if (siBomb[i].mode != SI_DEAD) {
+ gdiBitBlt(NULL,siBomb[i].x,siBomb[i].y - 3,3,14,(pu8) siBadBomb00,GDI_ROP_COPY);
+ siBomb[i].mode = SI_DEAD;
+ }
+ }
+}
+
+void numtostr(char *buffer,int n) {
+int i = 0;
+int isNeg = n<0;
+unsigned int n1 = isNeg ? -n : n;
+int t;
+
+while(n1!=0)
+{
+ buffer[i++] = n1%10+'0';
+ n1=n1/10;
+}
+
+if(isNeg)
+ buffer[i++] = '-';
+
+buffer[i] = '\0';
+
+for(t = 0; t < i/2; t++)
+{
+ buffer[t] ^= buffer[i-t-1];
+ buffer[i-t-1] ^= buffer[t];
+ buffer[t] ^= buffer[i-t-1];
+}
+
+if(n == 0)
+{
+ buffer[0] = '0';
+ buffer[1] = '\0';
+}
+}
+
+CCM void siDrawGoodBoyLeft(void) {
+
+i16 i, x, t;
+
+ if (siGoodBoyCount != siGoodBoyCountOld) {
+ strcpy((char*) siScore,"LEFT: ");
+ numtostr(siScore+6,siGoodBoyCount - 1);
+// sprintf((char*) siScore,"LEFT: %d",siGoodBoyCount - 1);
+ gdiDrawTextEx(340,170,siScore,GDI_ROP_COPY);
+
+ siGoodBoyCountOld = siGoodBoyCount;
+ for (t = 0; t < 4; t++) {
+ x = 322;
+ for (i = 1; i < SI_MAXGOODBOYS; i++) {
+ gdiBitBlt(NULL,x,SI_GOODBOYSTART_Y,24,9,(pu8) siGoodBoysBlk,GDI_ROP_COPY);
+ x += 24;
+ }
+ sysDelayMs(200);
+ x = 322;
+ for (i = 1; i < SI_MAXGOODBOYS; i++) {
+ if (i < siGoodBoyCount) {
+ gdiBitBlt(NULL,x,SI_GOODBOYSTART_Y,24,9,(pu8) siGoodBoys,GDI_ROP_COPY);
+ } else {
+ gdiBitBlt(NULL,x,SI_GOODBOYSTART_Y,24,9,(pu8) siGoodBoysBlk,GDI_ROP_COPY);
+ }
+ x += 24;
+ }
+ sysDelayMs(300);
+ }
+ siXGoodBoy = SI_GOODBOYSTART_X;
+ gdiBitBlt(NULL,siXGoodBoy,siYGoodBoy,24,9,(pu8) siGoodBoys,GDI_ROP_COPY);
+ }
+}
+
+// Test if Bad Boys are closed to defenses. 0 = No, 1 = Game Over
+
+i16 siBadBoysClosed(void) {
+
+int i, n;
+
+ for (i = (SI_MAXBADBOYS_ROWS - 1); i >= 0; i--) {
+ for (n = 0; n < SI_MAXBADBOYS_COLS; n++) {
+ if (sibb[i][n].mode == SI_ALIVE) {
+ if (sibb[i][n].y + siBadBoysShiftY + 12 >= SI_DEFSSTARTY) {
+ return(1);
+ } else {
+ return(0);
+ }
+ }
+ }
+ }
+ return(0);
+}
+
+// The game
+
+void siTheGame(void) {
+
+ while(1) {
+
+ sysDelayMs(1);
+
+ siDrawGoodBoyLeft();
+ siMoveGoodBoys();
+ siGoodBombStart();
+ siMoveGoodBomb();
+ if (siBadBoysClosed() == 1) {
+ siYouLose();
+ return;
+ }
+ if (siBadBoysCount > 0) {
+ if (siDrawBadBoyBomb()) { // Good Boy was killed
+ if (--siGoodBoyCount == 0) { // Game over
+ siYouLose();
+ return;
+ } else {
+ siCancelAllBadBoms();
+ gdiBitBlt(NULL,siXGoodBoy,siYGoodBoy,24,9,(pu8) siGoodBoysBlk,GDI_ROP_COPY);
+ }
+ }
+ } else {
+ siYouWin();
+ return;
+ }
+ siDrawBadboys();
+ if (siBakScore != siCurrentScore) {
+ siBakScore = siCurrentScore;
+ strcpy((char*) siScore,"SCORE: ");
+ numtostr(siScore+7,siCurrentScore);
+
+ // sprintf((char*) siScore,"SCORE: %04d",siCurrentScore);
+ gdiDrawTextEx(328,20,siScore,GDI_ROP_COPY);
+ //sprintf((char*) siScore,"BEST: %04d",siBestScore);
+ strcpy((char*) siScore,"BEST: ");
+ numtostr(siScore+6,siBestScore);
+ gdiDrawTextEx(328,29,siScore,GDI_ROP_COPY);
+
+ }
+ }
+}
+
+//*****************************************************************************
+// Function siInit
+//
+// Init Space Invaders
+//
+// return none
+//*****************************************************************************
+void siInit(void) {
+
+GPIO_InitTypeDef GPIO_InitStructure;
+u16 i, n, j, x, y;
+
+// Configure button pins
+
+ GPIO_InitStructure.GPIO_Pin = SI_FIRE_BUTTON | SI_LEFT_BUTTON | SI_RIGHT_BUTTON;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+ gdiBitBlt(NULL,0,0,(VID_PIXELS_X - 1),232,(pu8) siLogo,0);
+ sysDelayMs(5000);
+
+ Demo_CompassConfig();
+
+start:
+
+ siInitialScreen();
+
+ vidClearScreen();
+ gdiRectangle(0,0,(VID_PIXELS_X - 1),VID_VSIZE - 1,0);
+ gdiLine(NULL,320,0,320,VID_VSIZE,GDI_ROP_COPY);
+
+// Preload Bad Boys
+ siBadBoysShiftY=0;
+ siBadBoysShiftX=0;
+
+ for (i = 0; i < SI_MAXBADBOYS_ROWS; i++) {
+ x = 15;
+ y = SI_BADBOYS_START_Y + ((SI_MAXBADBOYS_ROWS + 12) * i);
+ for (n = 0; n < SI_MAXBADBOYS_COLS; n++) {
+ sibb[i][n].x = x;
+ sibb[i][n].y = y;
+ sibb[i][n].mode = SI_ALIVE;
+ sibb[i][n].flip = 0;
+ if (i == 0) {
+ sibb[i][n].b1 = (pu8) siBadBoys01;
+ sibb[i][n].b2 = (pu8) siBadBoys02;
+ }
+ if (i == 1 || i == 2) {
+ sibb[i][n].b1 = (pu8) siBadBoys11;
+ sibb[i][n].b2 = (pu8) siBadBoys12;
+ }
+ if (i >= 3) {
+ sibb[i][n].b1 = (pu8) siBadBoys21;
+ sibb[i][n].b2 = (pu8) siBadBoys22;
+ }
+ x += 20;
+ }
+ }
+
+// Preload defenses
+
+ for (i = 0; i < 4; i++) {
+ y = SI_DEFSSTARTY;
+ for (j = 0; j < SI_MAXDEFENSES_ROWS; j++) {
+ x = SI_DEFSSTARTX + (i * SI_DEFXSEPARATOR);;
+ for (n = 0; n < SI_MAXDEFENSES_COLS; n++) {
+ switch(i) {
+ case 0: if (j == 0 || j == 1) {
+ sidef1[j][n].x = x;
+ sidef1[j][n].y = y;
+ sidef1[j][n].mode = SI_ALIVE;
+ } else {
+ if (n == 0 || n == (SI_MAXDEFENSES_COLS - 1)) {
+ sidef1[j][n].x = x;
+ sidef1[j][n].y = y;
+ sidef1[j][n].mode = SI_ALIVE;
+ } else {
+ sidef1[j][n].x = x;
+ sidef1[j][n].y = y;
+ sidef1[j][n].mode = SI_DEAD;
+ }
+ }
+ x += 3;
+ break;
+ case 1: if (j == 0 || j == 1) {
+ sidef2[j][n].x = x;
+ sidef2[j][n].y = y;
+ sidef2[j][n].mode = SI_ALIVE;
+ } else {
+ if (n == 0 || n == (SI_MAXDEFENSES_COLS - 1)) {
+ sidef2[j][n].x = x;
+ sidef2[j][n].y = y;
+ sidef2[j][n].mode = SI_ALIVE;
+ } else {
+ sidef2[j][n].x = x;
+ sidef2[j][n].y = y;
+ sidef2[j][n].mode = SI_DEAD;
+ }
+ }
+ x += 3;
+ break;
+ case 2: if (j == 0 || j == 1) {
+ sidef3[j][n].x = x;
+ sidef3[j][n].y = y;
+ sidef3[j][n].mode = SI_ALIVE;
+ } else {
+ if (n == 0 || n == (SI_MAXDEFENSES_COLS - 1)) {
+ sidef3[j][n].x = x;
+ sidef3[j][n].y = y;
+ sidef3[j][n].mode = SI_ALIVE;
+ } else {
+ sidef3[j][n].x = x;
+ sidef3[j][n].y = y;
+ sidef3[j][n].mode = SI_DEAD;
+ }
+ }
+ x += 3;
+ break;
+ case 3: if (j == 0 || j == 1) {
+ sidef4[j][n].x = x;
+ sidef4[j][n].y = y;
+ sidef4[j][n].mode = SI_ALIVE;
+ } else {
+ if (n == 0 || n == (SI_MAXDEFENSES_COLS - 1)) {
+ sidef4[j][n].x = x;
+ sidef4[j][n].y = y;
+ sidef4[j][n].mode = SI_ALIVE;
+ } else {
+ sidef4[j][n].x = x;
+ sidef4[j][n].y = y;
+ sidef4[j][n].mode = SI_DEAD;
+ }
+ }
+ x += 3;
+ break;
+ }
+ }
+ y += 5;
+ }
+ }
+
+// Init default variables
+
+ siXGoodBoy = SI_GOODBOYSTART_X;
+ siYGoodBoy = SI_GOODBOYSTART_Y;
+
+ siBadBoysDelay = SI_BADBOYSSTARTDELAY;
+ siBadBoysShiftX = 0;
+ siBadBoysShiftX = 0;
+ siBadBoysMode = 0;
+ siBadBoysFlip = 0;
+ siBadBoysYCount = 0;
+ siGoodBoysKeyDelay = SI_GOODBOYSKEYDELAY;
+ siGoodBombDelay = SI_GOODBOMBDELAY;
+ if (siCurrentScore > siBestScore) siBestScore = siCurrentScore;
+ siCurrentScore = 0;
+ siBadBoysBombDelay = SI_BADBOYSBOMBDELAY;
+ siBadBombMoveDelay = SI_BADBOMBMOVEDELAY;
+ siBadBoysCount = SI_MAXBADBOYS_COLS * SI_MAXBADBOYS_ROWS;
+ siBakScore = -1;
+ siGoodBoyCount = SI_MAXGOODBOYS;
+ siGoodBoyCountOld = 0;
+
+// Show Good Boy first time
+
+ gdiBitBlt(NULL,siXGoodBoy,siYGoodBoy,24,9,(pu8) siGoodBoys,GDI_ROP_COPY);
+
+// Show Bad Boys first time
+
+ siDrawBadboys();
+
+// Show defenses first time
+
+ siShowDefenses();
+
+// Start Gane
+
+ siTheGame();
+ goto start;
+}
+
+