mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-25 18:33:11 +00:00
654 lines
19 KiB
C
654 lines
19 KiB
C
|
|
|
|
#include "williams.h"
|
|
//#link "williams.c"
|
|
|
|
#include "stdlib.h"
|
|
|
|
//#link "font.c"
|
|
#include "font.h"
|
|
|
|
// for CMOC (??)
|
|
void stkcheck() { }
|
|
|
|
// GRAPHIC DATA
|
|
|
|
const byte palette_data[16] = {/*{pal:332,n:16}*/
|
|
0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1f, 0x37, 0xe0, 0xa4, 0xfd, 0xff, 0x38, 0x70, 0x7f, 0xf8, };
|
|
|
|
const byte laser_vert[2+1*8] = {
|
|
1,8,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
};
|
|
|
|
const byte laser_horiz[2+4*2] = {
|
|
4,2,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
0xff,
|
|
};
|
|
|
|
|
|
const byte playersprite1[] = {
|
|
7,16,/*{w:14,h:16,bpp:4,brev:1}*/
|
|
0x00,0x00,0xEF,0xEF,0xE0,0x00,0x00,
|
|
0x00,0xEE,0xEE,0xFE,0xEE,0xE0,0x00,
|
|
0x0E,0xED,0xEF,0xEF,0xED,0xEE,0x00,
|
|
0x0E,0xEE,0xDD,0xDD,0xDE,0xEE,0x00,
|
|
0x0E,0xEE,0xEC,0xDC,0xEE,0xEE,0x00,
|
|
0x00,0xEE,0xEE,0xDE,0xEE,0xE0,0x00,
|
|
0x00,0xEE,0xEE,0xDE,0xEE,0xE0,0x00,
|
|
0x00,0x00,0xED,0xDD,0xE0,0x00,0x00,
|
|
0xDD,0xDD,0xEE,0xEE,0xED,0xDD,0xD0,
|
|
0x0C,0xEE,0xEE,0xEE,0xEE,0xEC,0x00,
|
|
0x0E,0xE0,0xEE,0xEE,0xE0,0xEE,0x00,
|
|
0x0E,0xE0,0xEE,0xEE,0xE0,0xEE,0x00,
|
|
0x0E,0xE0,0xDD,0xDD,0xD0,0xDE,0x00,
|
|
0x0D,0x00,0xEE,0x0E,0xE0,0x0D,0x00,
|
|
0x00,0x00,0xEC,0x0C,0xE0,0x00,0x00,
|
|
0x00,0x0D,0xDD,0x0D,0xDD,0x00,0x00,
|
|
};
|
|
|
|
const byte sprite1[2+16*16/2] = {
|
|
8,16,/*{w:16,h:16,bpp:4,brev:1}*/
|
|
0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
|
|
0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00,
|
|
0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90,
|
|
0x94,0x99,0x94,0x90,0x09,0x49,0x99,0x49,
|
|
0x99,0x99,0x49,0x93,0x39,0x94,0x99,0x99,
|
|
0x04,0x49,0x99,0x94,0x49,0x99,0x94,0x90,
|
|
0x00,0x94,0x94,0x43,0x34,0x49,0x49,0x00,
|
|
0x00,0x09,0x43,0x94,0x49,0x34,0x90,0x00,
|
|
0x00,0x90,0x00,0x39,0x93,0x00,0x09,0x00,
|
|
0x00,0x09,0x83,0x33,0x33,0x33,0x90,0x00,
|
|
0x00,0x09,0x32,0x23,0x32,0x23,0x90,0x00,
|
|
0x00,0x03,0x03,0x23,0x82,0x30,0x30,0x00,
|
|
0x03,0x30,0x00,0x33,0x33,0x00,0x03,0x30,
|
|
0x00,0x30,0x03,0x00,0x00,0x30,0x03,0x00,
|
|
0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00,
|
|
0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
|
|
};
|
|
|
|
const byte sprite2[2+16*16/2] = {
|
|
8,16,/*{w:16,h:16,bpp:4,brev:1}*/
|
|
0x00,0x08,0x80,0x40,0x00,0x00,0x8D,0x00,
|
|
0x80,0x94,0x88,0x90,0x09,0x48,0x89,0x00,
|
|
0x08,0x49,0x48,0x66,0x66,0x98,0x94,0x98,
|
|
0x94,0x89,0x66,0x66,0x66,0x66,0x98,0x89,
|
|
0x99,0x66,0x67,0x76,0x67,0x76,0x69,0x98,
|
|
0x88,0x67,0x77,0x66,0x66,0x77,0x74,0x90,
|
|
0x09,0x97,0x74,0x46,0x64,0x47,0x78,0x88,
|
|
0x09,0x89,0x43,0x96,0x69,0x34,0x99,0x90,
|
|
0x08,0x89,0xBB,0x39,0x93,0xBB,0x98,0x90,
|
|
0x80,0x99,0x3B,0x33,0x33,0xB0,0x99,0x88,
|
|
0x00,0x09,0x9C,0xC3,0x3C,0xC8,0x99,0x08,
|
|
0x00,0x00,0x03,0xC3,0x8C,0x30,0x00,0x00,
|
|
0x00,0x00,0x0D,0xD3,0x3D,0x00,0x00,0x00,
|
|
0x00,0x00,0x0D,0x00,0x0D,0xD0,0x00,0x00,
|
|
0x00,0x00,0xDD,0x30,0x03,0xD0,0x00,0x00,
|
|
0x00,0x00,0xD0,0x40,0x00,0xD0,0x00,0x00,
|
|
};
|
|
|
|
const byte sprite3[2+16*16/2] = {
|
|
8,16,/*{w:16,h:16,bpp:4,brev:1}*/
|
|
0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x11,0x11,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
|
|
0x00,0x11,0x10,0x01,0x10,0x01,0x11,0x00,
|
|
0x11,0x00,0x10,0x11,0x11,0x01,0x00,0x11,
|
|
0x10,0x00,0x11,0x11,0x11,0x11,0x00,0x01,
|
|
0x10,0x00,0x00,0x11,0x11,0x00,0x00,0x01,
|
|
0x00,0x01,0x10,0x11,0x41,0x01,0x10,0x00,
|
|
0x00,0x10,0x11,0x11,0x11,0x11,0x01,0x00,
|
|
0x01,0x00,0x00,0x51,0x15,0x00,0x00,0x10,
|
|
0x01,0x00,0x01,0x10,0x01,0x10,0x00,0x10,
|
|
0x01,0x00,0x10,0x00,0x00,0x01,0x00,0x10,
|
|
0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00,
|
|
0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,
|
|
0x00,0x01,0x10,0x00,0x00,0x01,0x10,0x00,
|
|
};
|
|
|
|
const byte sprite4[2+16*16/2] = {
|
|
8,16,/*{w:16,h:16,bpp:4,brev:1}*/
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00,
|
|
0x00,0x00,0xbb,0xbb,0xbb,0xbb,0x00,0x00,
|
|
0x00,0x0b,0x4b,0xbb,0xbb,0xb4,0xb0,0x00,
|
|
0x00,0x0b,0x44,0xbb,0xbb,0x49,0xb0,0x00,
|
|
0x00,0xbb,0x99,0x4b,0xb4,0x99,0xbb,0x00,
|
|
0x00,0x4b,0xb9,0x9b,0xb4,0x4b,0xb4,0x00,
|
|
0x00,0x04,0xbb,0x4b,0xb9,0xbb,0x40,0x00,
|
|
0x00,0x00,0x4b,0xbb,0xbb,0xb4,0x00,0x00,
|
|
0x11,0x00,0x0b,0xbb,0xbb,0xb0,0x00,0x11,
|
|
0x10,0x10,0x0b,0x41,0x14,0xb0,0x01,0x01,
|
|
0x10,0x00,0x05,0x11,0x11,0x50,0x00,0x01,
|
|
0x01,0x00,0x01,0x51,0x15,0x10,0x00,0x10,
|
|
0x00,0x10,0x01,0x10,0x01,0x10,0x01,0x00,
|
|
0x01,0x01,0x10,0x10,0x01,0x01,0x10,0x10,
|
|
};
|
|
|
|
const byte sprite5[2+16*16/2] = {
|
|
8,16,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x22,0x00,0x00,0x22,0x00,0x00,
|
|
0x00,0x20,0x20,0x00,0x00,0x02,0x02,0x00,
|
|
0x02,0x22,0x12,0x00,0x00,0x21,0x22,0x20,
|
|
0x00,0x02,0x11,0x00,0x00,0x11,0x20,0x00,
|
|
0x00,0x00,0x02,0x11,0x11,0x20,0x00,0x00,
|
|
0x00,0x00,0x02,0x22,0x22,0x20,0x00,0x00,
|
|
0x00,0x00,0x21,0x22,0x22,0x12,0x00,0x00,
|
|
0x00,0x00,0x22,0x12,0x21,0x22,0x00,0x00,
|
|
0x02,0x00,0x22,0x12,0x21,0x22,0x00,0x20,
|
|
0x20,0x02,0x21,0x11,0x11,0x12,0x20,0x02,
|
|
0x02,0x22,0x15,0x12,0x21,0x51,0x22,0x20,
|
|
0x02,0x11,0x15,0x52,0x25,0x51,0x11,0x20,
|
|
0x20,0x00,0x22,0x12,0x21,0x22,0x00,0x02,
|
|
0x20,0x02,0x20,0x20,0x02,0x02,0x20,0x02,
|
|
0x02,0x02,0x00,0x20,0x02,0x00,0x20,0x20,
|
|
};
|
|
|
|
const byte sprite6[2+10*16/2] = {
|
|
8,10,/*{w:16,h:10,bpp:4,brev:1}*/
|
|
0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00,
|
|
0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x40,
|
|
0x00,0x00,0x04,0x04,0x49,0x49,0x99,0x44,
|
|
0x00,0x00,0x44,0x44,0x99,0x94,0x44,0x40,
|
|
0x00,0x04,0x49,0x99,0x94,0x49,0x99,0x40,
|
|
0x00,0x44,0x99,0x94,0x49,0x99,0x44,0x00,
|
|
0x04,0x49,0x44,0x99,0x99,0x44,0x00,0x00,
|
|
0x04,0x44,0x00,0x49,0x44,0x40,0x00,0x00,
|
|
0x04,0x40,0x00,0x04,0x00,0x00,0x00,0x00,
|
|
0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
};
|
|
|
|
const byte sprite7[2+14*16/2] = {
|
|
8,14,/*{w:16,h:14,bpp:4,brev:1}*/
|
|
0x00,0x60,0x00,0x00,0x00,0x00,0x06,0x00,
|
|
0x60,0x60,0x00,0x00,0x00,0x00,0x06,0x06,
|
|
0x60,0x60,0x50,0x00,0x00,0x05,0x06,0x06,
|
|
0x60,0x60,0x06,0x00,0x00,0x60,0x06,0x06,
|
|
0x66,0x60,0x06,0x06,0x60,0x60,0x06,0x66,
|
|
0x66,0x60,0x66,0x66,0x66,0x66,0x06,0x66,
|
|
0x66,0x60,0x6b,0x6b,0xb6,0xb6,0x06,0x66,
|
|
0x06,0x66,0x66,0xb6,0x6b,0x66,0x66,0x60,
|
|
0x00,0x67,0x66,0x66,0x66,0x66,0x66,0x00,
|
|
0x00,0x11,0x11,0x66,0x66,0x11,0x11,0x00,
|
|
0x01,0x11,0x21,0x11,0x11,0x12,0x11,0x10,
|
|
0x00,0x10,0x01,0x01,0x10,0x10,0x01,0x00,
|
|
0x00,0x10,0x11,0x00,0x00,0x11,0x01,0x00,
|
|
0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
|
|
};
|
|
|
|
const byte sprite8[2+15*16/2] = {
|
|
8,15,/*{w:16,h:15,bpp:4,brev:1}*/
|
|
0x00,0x00,0x11,0x11,0x11,0x11,0x00,0x00,
|
|
0x00,0x01,0x61,0x11,0x21,0x12,0x10,0x00,
|
|
0x00,0x11,0x12,0x11,0x61,0x11,0x11,0x00,
|
|
0x00,0x11,0x71,0x21,0x61,0x17,0x11,0x00,
|
|
0x00,0x11,0x77,0x11,0x12,0x77,0x11,0x00,
|
|
0x00,0x11,0x17,0x17,0x71,0x72,0x11,0x00,
|
|
0x00,0x16,0x21,0x78,0x87,0x11,0x11,0x00,
|
|
0x00,0x01,0x81,0x88,0x88,0x18,0x10,0x00,
|
|
0x00,0x08,0x18,0x58,0x85,0x81,0x80,0x00,
|
|
0x00,0x88,0x01,0x88,0x88,0x10,0x88,0x00,
|
|
0x00,0x08,0x07,0x78,0x87,0x70,0x80,0x00,
|
|
0x08,0x80,0x07,0x80,0x08,0x70,0x08,0x80,
|
|
0x88,0x00,0x88,0x00,0x00,0x88,0x00,0x88,
|
|
0x80,0x00,0x08,0x80,0x08,0x80,0x00,0x08,
|
|
0x00,0x00,0x00,0x80,0x08,0x00,0x00,0x00,
|
|
};
|
|
|
|
const byte sprite9[2+13*16/2] = {
|
|
8,13,/*{w:16,h:13,bpp:4,brev:1}*/
|
|
0x00,0x00,0xaa,0x00,0x00,0xaa,0x00,0x00,
|
|
0x00,0x00,0xa0,0x0a,0xa0,0x0a,0x00,0x00,
|
|
0x0a,0xaa,0xa4,0xaa,0xaa,0x3a,0xaa,0xa0,
|
|
0x00,0x0a,0x3a,0x9a,0xa9,0xa3,0xa0,0x00,
|
|
0x00,0x0a,0xaa,0x99,0xa4,0xaa,0xa0,0x00,
|
|
0x00,0x0a,0xaa,0x99,0x94,0xaa,0xa0,0x00,
|
|
0x00,0xaa,0x33,0xaa,0xaa,0x43,0xaa,0x00,
|
|
0x0a,0x3a,0xaa,0x3a,0xa3,0xaa,0xa3,0xa0,
|
|
0x00,0xaa,0xaa,0x30,0x03,0xaa,0xaa,0x00,
|
|
0x00,0x0a,0xa0,0x30,0x03,0x0a,0xa0,0x00,
|
|
0x00,0xa3,0xa0,0x00,0x00,0x0a,0x4a,0x00,
|
|
0x00,0xaa,0xa0,0x00,0x00,0x0a,0xaa,0x00,
|
|
0x00,0x0a,0xa0,0x00,0x00,0x0a,0xa0,0x00,
|
|
};
|
|
|
|
const byte* const all_sprites[9] = {
|
|
sprite1,
|
|
sprite2,
|
|
sprite3,
|
|
sprite4,
|
|
sprite5,
|
|
sprite6,
|
|
sprite7,
|
|
sprite8,
|
|
sprite9,
|
|
};
|
|
|
|
// GAME CODE
|
|
|
|
typedef struct Actor {
|
|
struct Actor* next;
|
|
struct Actor** prevptr;
|
|
byte x,y;
|
|
const byte* shape;
|
|
void (*update)(struct Actor* a);
|
|
void (*draw)(struct Actor* a);
|
|
union u {
|
|
struct { sbyte dx,dy; } laser;
|
|
struct { byte exploding; } enemy;
|
|
} u;
|
|
} Actor;
|
|
|
|
#define MAX_ACTORS 128
|
|
|
|
static Actor actors[MAX_ACTORS];
|
|
static Actor* player_list;
|
|
static Actor* fast_list;
|
|
static Actor* slow_lists[4];
|
|
static Actor* obstacle_list;
|
|
static Actor* free_list;
|
|
static Actor* effects_list;
|
|
static byte frame;
|
|
|
|
static word score; // bcd score
|
|
|
|
#define PLAYER 1
|
|
#define LASER 2
|
|
|
|
void add_actor(Actor** list, Actor* a) {
|
|
if (*list) (*list)->prevptr = &a->next;
|
|
a->next = *list;
|
|
a->prevptr = list;
|
|
*list = a;
|
|
}
|
|
|
|
void remove_actor(Actor* a) {
|
|
if (a->next) a->next->prevptr = a->prevptr;
|
|
*a->prevptr = a->next;
|
|
}
|
|
|
|
void draw_actor_normal(Actor* a) {
|
|
blit_sprite(a->shape, a->x, a->y);
|
|
}
|
|
|
|
void draw_actor_exploding(Actor* a) {
|
|
unblit_sprite_strided(a->shape, a->x, a->y, a->u.enemy.exploding);
|
|
if (a->u.enemy.exploding > 10) {
|
|
a->draw = NULL;
|
|
} else {
|
|
blit_sprite_strided(a->shape, a->x, a->y, ++a->u.enemy.exploding);
|
|
}
|
|
}
|
|
|
|
void update_actor(Actor* a) {
|
|
// if NULL shape, we don't have anything
|
|
if (a->shape) {
|
|
// erase the sprite
|
|
blit_sprite_solid(a->shape, a->x, a->y, 0);
|
|
// call update callback
|
|
if (a->update) {
|
|
a->update(a);
|
|
}
|
|
// did we delete it?
|
|
if (a->shape) {
|
|
// draw the sprite
|
|
if (a->draw) {
|
|
a->draw(a);
|
|
}
|
|
} else {
|
|
// shape became null, remove from list
|
|
remove_actor(a);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
|
|
word lfsr = 1;
|
|
|
|
word xrand() {
|
|
byte lsb = (byte)lfsr & 1;
|
|
lfsr >>= 1;
|
|
if (lsb) lfsr ^= 0xd400;
|
|
return lfsr;
|
|
}
|
|
|
|
signed char random_dir() {
|
|
byte x = (byte)xrand();
|
|
if (x < 85) return 0;
|
|
else if (x < 85*2) return -1;
|
|
else return 1;
|
|
}
|
|
|
|
void update_actor_list(Actor* a) {
|
|
while (a) {
|
|
update_actor(a);
|
|
a = a->next;
|
|
}
|
|
}
|
|
|
|
static byte g_section;
|
|
|
|
void update_actors_partial(Actor* a) {
|
|
while (a) {
|
|
if (g_section ^ (a->y < 0x80)) {
|
|
update_actor(a);
|
|
}
|
|
a = a->next;
|
|
}
|
|
}
|
|
|
|
void update_screen_section(byte section) {
|
|
g_section = section;
|
|
update_actors_partial(player_list);
|
|
update_actors_partial(fast_list);
|
|
update_actors_partial(slow_lists[frame & 3]);
|
|
}
|
|
|
|
static Actor* test_actor;
|
|
static byte test_x, test_y;
|
|
|
|
byte minbyte(byte a, byte b) { return a<b?a:b; }
|
|
byte maxbyte(byte a, byte b) { return a>b?a:b; }
|
|
|
|
bool test_actor_pixels(Actor* a) {
|
|
if (a->shape) {
|
|
byte x,y;
|
|
const byte *p1, *p2;
|
|
byte x1 = maxbyte(test_actor->x, a->x);
|
|
byte y1 = maxbyte(test_actor->y, a->y);
|
|
byte x2 = minbyte(test_actor->x + test_actor->shape[0]*2,
|
|
a->x + a->shape[0]*2);
|
|
byte y2 = minbyte(test_actor->y + test_actor->shape[1],
|
|
a->y + a->shape[1]);
|
|
if (x2 < x1) x2 = 255; // clip to 8-bit coord.
|
|
if (y2 < y1) y2 = 255; // clip to 8-bit coord.
|
|
if (x2 <= x1 || y2 <= y1) return false;
|
|
//draw_box(x1,y1,x2,y2,0xff);
|
|
p1 = &test_actor->shape[2+(y1-test_actor->y)*test_actor->shape[0]];
|
|
p2 = &a->shape[2+(y1-a->y)*a->shape[0]];
|
|
p1 += (x1 - test_actor->x) >> 1;
|
|
p2 += (x1 - a->x) >> 1;
|
|
for (y=y1; y<y2; y++) {
|
|
for (x=x1; x<x2; x++) {
|
|
if (p1[x] && p2[x]) return true;
|
|
}
|
|
p1 += test_actor->shape[0];
|
|
p2 += a->shape[0];
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool test_collision_actor(Actor* a) {
|
|
return ((byte)(test_y - a->y + 16) < 32 &&
|
|
(byte)(test_x - a->x + 16) < 32 &&
|
|
test_actor_pixels(a));
|
|
}
|
|
|
|
Actor* test_collisions(Actor* a) {
|
|
while (a) {
|
|
if (test_collision_actor(a)) {
|
|
return a;
|
|
}
|
|
a = a->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void setup_collision(Actor* a) {
|
|
test_actor = a;
|
|
test_x = a->x;
|
|
test_y = a->y;
|
|
}
|
|
|
|
void destroy_player() {
|
|
Actor* a = &actors[PLAYER];
|
|
byte i;
|
|
sound_pia = 1; // play sound
|
|
for (i=0; i<60; i++) {
|
|
WATCHDOG;
|
|
while (video_counter != 0xfc) ;
|
|
blit_sprite_solid(a->shape, a->x, a->y, i);
|
|
while (video_counter == 0xfc) ;
|
|
}
|
|
for (i=1; i<60; i++) {
|
|
WATCHDOG;
|
|
while (video_counter != 0xfc) ;
|
|
blit_sprite_strided(a->shape, a->x+i, a->y, i);
|
|
blit_sprite_strided(a->shape, a->x-i, a->y, i);
|
|
while (video_counter == 0xfc) ;
|
|
}
|
|
}
|
|
|
|
void random_walk(Actor* a) {
|
|
a->x += random_dir();
|
|
a->y += random_dir();
|
|
setup_collision(a);
|
|
if (actors[PLAYER].shape && test_collision_actor(&actors[PLAYER])) {
|
|
destroy_player();
|
|
actors[PLAYER].shape = NULL;
|
|
}
|
|
}
|
|
|
|
void laser_move(Actor* a) {
|
|
// did we hit something?
|
|
Actor* collided;
|
|
setup_collision(a);
|
|
collided = test_collisions(fast_list);
|
|
if (!collided) collided = test_collisions(slow_lists[0]);
|
|
if (!collided) collided = test_collisions(slow_lists[1]);
|
|
if (!collided) collided = test_collisions(slow_lists[2]);
|
|
if (!collided) collided = test_collisions(slow_lists[3]);
|
|
if (collided) {
|
|
// get rid of laser (we can do this in our 'update' fn)
|
|
a->shape = NULL;
|
|
// set exploding counter for enemy, change fn pointers
|
|
collided->draw = draw_actor_exploding;
|
|
collided->update = NULL;
|
|
collided->u.enemy.exploding = 1;
|
|
// move enemy to effects list
|
|
remove_actor(collided);
|
|
add_actor(&effects_list, collided);
|
|
// play sound
|
|
sound_pia = 2;
|
|
// add score
|
|
score = bcd_add(score, 5);
|
|
return;
|
|
}
|
|
// move laser
|
|
// check for wall collisions
|
|
a->x += a->u.laser.dx;
|
|
if (a->u.laser.dx > 0 && a->x < 8) a->shape = NULL;
|
|
if (a->u.laser.dx < 0 && a->x > 255-8) a->shape = NULL;
|
|
a->y += a->u.laser.dy;
|
|
if (a->y > 255-8) a->shape = NULL;
|
|
}
|
|
|
|
void shoot_laser(sbyte dx, sbyte dy, const byte* shape) {
|
|
Actor* a = &actors[LASER];
|
|
a->shape = (byte*) shape;
|
|
a->x = actors[PLAYER].x + 6;
|
|
a->y = actors[PLAYER].y + 8;
|
|
a->u.laser.dx = dx;
|
|
a->u.laser.dy = dy;
|
|
add_actor(&player_list, a);
|
|
}
|
|
|
|
void player_laser() {
|
|
// is the laser being used?
|
|
if (actors[LASER].shape == NULL) { // no, check controls
|
|
if (UP2) shoot_laser(0,-8,laser_vert);
|
|
else if (DOWN2) shoot_laser(0,8,laser_vert);
|
|
else if (LEFT2) shoot_laser(-8,0,laser_horiz);
|
|
else if (RIGHT2) shoot_laser(8,0,laser_horiz);
|
|
}
|
|
}
|
|
|
|
void player_move(Actor* a) {
|
|
byte x = a->x;
|
|
byte y = a->y;
|
|
if (UP1) y-=1;
|
|
if (DOWN1) y+=1;
|
|
if (LEFT1) x-=1;
|
|
if (RIGHT1) x+=1;
|
|
a->x = x;
|
|
a->y = y;
|
|
player_laser();
|
|
}
|
|
|
|
static Actor* current_effect;
|
|
|
|
void effects_new_frame() {
|
|
current_effect = effects_list;
|
|
}
|
|
|
|
void effects_next() {
|
|
if (current_effect) {
|
|
if (current_effect->draw) {
|
|
current_effect->draw(current_effect);
|
|
} else {
|
|
remove_actor(current_effect);
|
|
}
|
|
current_effect = current_effect->next;
|
|
}
|
|
}
|
|
|
|
Actor* new_actor() {
|
|
Actor* a = free_list;
|
|
remove_actor(a);
|
|
a->draw = draw_actor_normal;
|
|
return a;
|
|
}
|
|
|
|
Actor* new_effect(void (*draw)(struct Actor *)) {
|
|
Actor* a = new_actor();
|
|
a->draw = draw;
|
|
add_actor(&effects_list, a);
|
|
return a;
|
|
}
|
|
|
|
void init() {
|
|
byte i;
|
|
blit_solid(0, 0, 255, 255, 0);
|
|
memset(actors, 0, sizeof(actors));
|
|
memcpy(palette, palette_data, 16);
|
|
player_list = fast_list = obstacle_list = free_list = NULL;
|
|
memset(slow_lists, 0, sizeof(slow_lists));
|
|
// add all actors to free list
|
|
for (i=MAX_ACTORS-1; i>0; i--) {
|
|
add_actor(&free_list, &actors[i]);
|
|
}
|
|
score = 0;
|
|
}
|
|
|
|
void make_player_actors() {
|
|
// make player
|
|
Actor* a = new_actor();
|
|
a->x = 128;
|
|
a->y = 120;
|
|
a->shape = (byte*) playersprite1;
|
|
a->update = player_move;
|
|
add_actor(&player_list, a);
|
|
// make laser
|
|
a = new_actor();
|
|
a->update = laser_move;
|
|
a->shape = NULL;
|
|
}
|
|
|
|
void make_enemy_actors() {
|
|
byte i;
|
|
const byte num_actors = 32;
|
|
for (i=3; i<num_actors; i++) {
|
|
Actor* a = new_actor();
|
|
do {
|
|
a->x = (byte)xrand();
|
|
a->y = (byte)xrand() + 24;
|
|
} while ((byte)(a->x - 96) < 64 && (byte)(a->y - 96) < 64);
|
|
a->shape = (byte*) all_sprites[i%9];
|
|
a->update = random_walk;
|
|
a->draw = draw_actor_normal;
|
|
if (i < 5) add_actor(&fast_list, a);
|
|
else add_actor(&slow_lists[i&3], a);
|
|
WATCHDOG;
|
|
}
|
|
}
|
|
|
|
void draw_bcd_word(word bcd, word x, byte y, byte color) {
|
|
byte j;
|
|
x += 4*4;
|
|
for (j=0; j<4; j++) {
|
|
x -= 4;
|
|
draw_char('0'+((byte)bcd & 0xf), x, y, color);
|
|
bcd >>= 4;
|
|
}
|
|
}
|
|
|
|
void draw_score(Actor* a) {
|
|
a;
|
|
draw_string("Plyr 1", 278, 8, 0xee);
|
|
// draw digits in color 0 so the background is erased
|
|
draw_bcd_word(score, 278, 20, 0);
|
|
// last two digits of score are "00"
|
|
draw_char('0', 278+16, 20, 0);
|
|
draw_char('0', 278+20, 20, 0);
|
|
}
|
|
|
|
void draw_playfield(Actor* a) {
|
|
// draw_box(0,0,275,255,0x11);
|
|
}
|
|
|
|
int main() {
|
|
init();
|
|
make_player_actors();
|
|
make_enemy_actors();
|
|
// add low-priority effects here, because new effects
|
|
// are added to the head of the list
|
|
new_effect(draw_score);
|
|
new_effect(draw_playfield);
|
|
// main loop
|
|
while (actors[PLAYER].shape) {
|
|
WATCHDOG;
|
|
effects_new_frame();
|
|
while (video_counter >= 0x90) effects_next();
|
|
update_screen_section(1);
|
|
while (video_counter < 0x90) effects_next();
|
|
update_screen_section(0);
|
|
switch (frame & 7) {
|
|
case 0:
|
|
break;
|
|
}
|
|
score = bcd_add(score, 1);
|
|
frame++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// SOUND ROM
|
|
/*
|
|
const byte __at(0x9000) SOUND_ROM[] = {
|
|
0xdb,0x00,0xb7,0x20,0x01,0x76,0x31,0x00,0x80,0xf3,0x11,0x00,0x40,0xdb,0x00,0x4f,0x0d,0x06,0x00,0x69,0x60,0x29,0x09,0x29,0x29,0x01,0x2b,0x01,0x09,0x01,0x0c,0x00,0xed,0xb0,0xcd,0xb5,0x01,0x3e,0x00,0xd3,0x00,0x76,0xc9,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0xc0,0x40,0x00,0x03,0x06,0x09,0x0c,0x10,0x13,0x16,0x19,0x1c,0x1f,0x22,0x25,0x28,0x2b,0x2e,0x31,0x33,0x36,0x39,0x3c,
|
|
0x3f,0x41,0x44,0x47,0x49,0x4c,0x4e,0x51,0x53,0x55,0x58,0x5a,0x5c,0x5e,0x60,0x62,0x64,0x66,0x68,0x6a,0x6b,0x6d,0x6f,0x70,0x71,0x73,0x74,0x75,0x76,0x78,0x79,0x7a,0x7a,0x7b,0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7e,0x7e,0x7e,0x7d,0x7d,0x7c,0x7b,0x7a,0x7a,0x79,0x78,0x76,0x75,0x74,0x73,0x71,0x70,0x6f,0x6d,0x6b,0x6a,0x68,0x66,0x64,0x62,0x60,0x5e,0x5c,0x5a,0x58,0x55,0x53,0x51,0x4e,0x4c,0x49,0x47,0x44,0x41,0x3f,0x3c,0x39,0x36,0x33,0x31,0x2e,0x2b,0x28,0x25,0x22,0x1f,0x1c,0x19,0x16,0x13,0x10,0x0c,0x09,0x06,0x03,0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8,0x00,0x08,0x10,0x18,0x20,
|
|
0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x60,0x37,0x3f,0x5c,0x16,0xca,0xc2,0xa5,0xfe,0xba,0x77,0x89,0xaa,0x77,0x13,0xd8,0xae,0x82,0xfd,0x22,0x9c,0x46,0xde,0x14,0x50,0xb4,0x97,0x46,0x54,0x9d,0x60,0x2b,0xb0,0x04,0x00,0x00,0x00,0x00,0x01,0x00,0x0b,0x01,0xff,0x00,0xfa,0x00,0x00,0x00,0xe8,0x03,0xfc,0xff,0x6b,0x00,0x7f,0x00,0xf4,0x01,0x00,0x00,0xe8,0x03,0x02,0x00,0xeb,0x00,0x1f,0x00,0x58,0x02,0x00,0x00,0xb8,0x0b,0xff,0xff,0x2b,0x00,0x1f,0x00,0x58,0x02,0x00,0x00,0xb8,0x0b,0xff,0xff,0x4b,0x00,0x1f,0x00,0x58,0x02,0x00,0x00,0xb8,0x0b,0x01,0x00,0x2b,0x00,0x3f,0x00,0xb0,0x04,0x00,0x00,0x00,0x00,0x01,0x00,0x6b,0x00,0x7f,0x01,0xdd,
|
|
0xe5,0xdd,0x21,0x00,0x00,0xdd,0x39,0x3b,0xed,0x5b,0x08,0x40,0xed,0x4b,0x02,0x40,0xdd,0x70,0xff,0x3a,0x0a,0x40,0xdd,0xa6,0xff,0x6f,0x26,0x00,0x19,0x5e,0x3a,0x0c,0x40,0x93,0x38,0x03,0x7b,0xd3,0x00,0x2a,0x04,0x40,0x09,0x4d,0x44,0xed,0x43,0x02,0x40,0x33,0xdd,0xe1,0xc9,0x21,0x0c,0x40,0x36,0xff,0xed,0x4b,0x00,0x40,0x59,0x50,0x1b,0xed,0x53,0x00,0x40,0x78,0xb1,0xc8,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xcd,0x7f,0x01,0xed,0x4b,0x04,0x40,0x2a,0x06,0x40,0x09,0x4d,0x44,0xed,0x43,0x04,0x40,0xed,0x4b,0x06,0x40,0x3a,0x0b,0x40,0x6f,0x17,0x9f,0x67,0x09,0x4d,0x44,0xed,0x43,0x06,0x40,
|
|
0x2a,0x00,0x40,0x3e,0xff,0xbd,0x3e,0x00,0x9c,0x38,0xaf,0xfd,0x21,0x0c,0x40,0xfd,0x75,0x00,0x18,0xa6,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,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,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,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,
|
|
};
|
|
*/
|