mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-28 08:50:22 +00:00
new williams sprites
This commit is contained in:
parent
9da265f7e5
commit
56288f58bb
File diff suppressed because it is too large
Load Diff
@ -62,6 +62,7 @@ struct {
|
|||||||
//
|
//
|
||||||
|
|
||||||
void main();
|
void main();
|
||||||
|
void _sdcc_heap_init(void); // for malloc()
|
||||||
|
|
||||||
// start routine @ 0x0
|
// start routine @ 0x0
|
||||||
// set stack pointer, enable interrupts
|
// set stack pointer, enable interrupts
|
||||||
@ -76,7 +77,9 @@ __asm
|
|||||||
LD HL, #s__INITIALIZER
|
LD HL, #s__INITIALIZER
|
||||||
LDIR
|
LDIR
|
||||||
__endasm;
|
__endasm;
|
||||||
main();
|
|
||||||
|
_sdcc_heap_init();
|
||||||
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOCHAR 0x21
|
#define LOCHAR 0x21
|
||||||
@ -102,6 +105,7 @@ void fill_char_table_entry(char ch) {
|
|||||||
b <<= 2;
|
b <<= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
WATCHDOG;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_char_table() {
|
void fill_char_table() {
|
||||||
@ -178,6 +182,43 @@ inline void draw_sprite_solid(const byte* data, byte x, byte y, byte color) {
|
|||||||
blitter.flags = (x&1) ? DSTSCREEN|FGONLY|RSHIFT|SOLID : DSTSCREEN|FGONLY|SOLID;
|
blitter.flags = (x&1) ? DSTSCREEN|FGONLY|RSHIFT|SOLID : DSTSCREEN|FGONLY|SOLID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_sprite_strided(const byte* data, byte x, byte y, byte stride) {
|
||||||
|
byte i;
|
||||||
|
byte width = data[0];
|
||||||
|
byte height = data[1];
|
||||||
|
byte yy = y-(height*(stride-1)/2);
|
||||||
|
word dest = (x>>1)+yy*256+XBIAS;
|
||||||
|
blitter.width = width^4;
|
||||||
|
blitter.height = 1^4;
|
||||||
|
for (i=0; i<height; i++) {
|
||||||
|
if ((dest & 0xff) < 0x90) {
|
||||||
|
blitter.sstart = swapw((word)(data+2));
|
||||||
|
blitter.dstart = dest; // swapped
|
||||||
|
blitter.flags = DSTSCREEN|FGONLY;
|
||||||
|
}
|
||||||
|
dest += stride << 8;
|
||||||
|
data += width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase_sprite_strided(const byte* data, byte x, byte y, byte stride) {
|
||||||
|
byte i;
|
||||||
|
byte width = data[0];
|
||||||
|
byte height = data[1];
|
||||||
|
byte yy = y-(height*(stride-1)/2);
|
||||||
|
word dest = (x>>1)+yy*256+XBIAS;
|
||||||
|
blitter.width = width^4;
|
||||||
|
blitter.height = 1^4;
|
||||||
|
blitter.solid = 0;
|
||||||
|
for (i=0; i<height; i++) {
|
||||||
|
if ((dest & 0xff) < 0x90) {
|
||||||
|
blitter.dstart = dest; // swapped
|
||||||
|
blitter.flags = DSTSCREEN|SOLID;
|
||||||
|
}
|
||||||
|
dest += stride << 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void draw_char(char ch, byte x, byte y, byte color) {
|
inline void draw_char(char ch, byte x, byte y, byte color) {
|
||||||
if (ch < LOCHAR || ch > HICHAR) return;
|
if (ch < LOCHAR || ch > HICHAR) return;
|
||||||
blit_copy_solid(x, y, 4, 8, font_table[ch - LOCHAR], color);
|
blit_copy_solid(x, y, 4, 8, font_table[ch - LOCHAR], color);
|
||||||
@ -429,22 +470,15 @@ const byte* const all_sprites[9] = {
|
|||||||
// GAME CODE
|
// GAME CODE
|
||||||
|
|
||||||
typedef struct Actor;
|
typedef struct Actor;
|
||||||
typedef struct Task;
|
|
||||||
|
|
||||||
typedef void (*ActorUpdateFn)(struct Actor* a);
|
typedef void (*ActorUpdateFn)(struct Actor* a);
|
||||||
typedef void (*ActorDrawFn)(const struct Actor* a);
|
typedef void (*ActorDrawFn)(struct Actor* a);
|
||||||
typedef void (*ActorEnumerateFn)(const struct Actor* a);
|
|
||||||
typedef bool (*TaskFn)(struct Task* task);
|
|
||||||
|
|
||||||
typedef struct Actor {
|
typedef struct Actor {
|
||||||
byte grid_index;
|
struct Actor* next;
|
||||||
byte next_actor;
|
struct Actor** prevptr;
|
||||||
byte last_update_frame;
|
|
||||||
byte x,y;
|
byte x,y;
|
||||||
byte* shape;
|
byte* shape;
|
||||||
byte flags;
|
|
||||||
byte updatefreq;
|
|
||||||
byte updatetimer;
|
|
||||||
ActorUpdateFn update;
|
ActorUpdateFn update;
|
||||||
ActorDrawFn draw;
|
ActorDrawFn draw;
|
||||||
union {
|
union {
|
||||||
@ -453,66 +487,30 @@ typedef struct Actor {
|
|||||||
} u;
|
} u;
|
||||||
} Actor;
|
} Actor;
|
||||||
|
|
||||||
typedef struct Task {
|
|
||||||
Actor* actor;
|
|
||||||
struct Task* next;
|
|
||||||
TaskFn func;
|
|
||||||
} Task;
|
|
||||||
|
|
||||||
#define GBITS 3
|
|
||||||
#define GDIM (1<<GBITS)
|
|
||||||
#define GDIM2 (1<<(GBITS+GBITS))
|
|
||||||
#define GMASK (GDIM2-1)
|
|
||||||
#define MAX_ACTORS 128
|
#define MAX_ACTORS 128
|
||||||
#define MAX_TASKS 256
|
|
||||||
|
|
||||||
static byte grid[GDIM*GDIM]; // should be 256
|
|
||||||
static Actor actors[MAX_ACTORS];
|
static Actor actors[MAX_ACTORS];
|
||||||
static Task taskarray[MAX_TASKS];
|
static Actor* player_list;
|
||||||
static Task* first_task;
|
static Actor* fast_list;
|
||||||
static Task* last_task;
|
static Actor* slow_lists[4];
|
||||||
|
static Actor* obstacle_list;
|
||||||
|
static Actor* free_list;
|
||||||
|
static Actor* effects_list;
|
||||||
static byte frame;
|
static byte frame;
|
||||||
|
|
||||||
#define PLAYER 1
|
#define PLAYER 1
|
||||||
#define LASER 2
|
#define LASER 2
|
||||||
#define F_PLAYER 0x1
|
|
||||||
#define F_KILLABLE 0x2
|
|
||||||
|
|
||||||
byte xy2grid(byte x, byte y) {
|
void add_actor(Actor** list, Actor* a) {
|
||||||
return (x >> (8-GBITS)) | ((y >> (8-GBITS)) << GBITS);
|
if (*list) (*list)->prevptr = &a->next;
|
||||||
|
a->next = *list;
|
||||||
|
a->prevptr = list;
|
||||||
|
*list = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert_into_grid(byte gi, byte actor_index) {
|
void remove_actor(Actor* a) {
|
||||||
struct Actor* a = &actors[actor_index];
|
if (a->next) a->next->prevptr = a->prevptr;
|
||||||
a->grid_index = gi;
|
*a->prevptr = a->next;
|
||||||
a->next_actor = grid[gi];
|
|
||||||
grid[gi] = actor_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_from_grid(byte gi, byte actor_index) {
|
|
||||||
byte i = grid[gi];
|
|
||||||
byte next = actors[actor_index].next_actor;
|
|
||||||
// is actor to delete at head of list?
|
|
||||||
if (i == actor_index) {
|
|
||||||
grid[gi] = next;
|
|
||||||
} else {
|
|
||||||
// iterate through the list
|
|
||||||
do {
|
|
||||||
byte j = actors[i].next_actor;
|
|
||||||
if (j == actor_index) {
|
|
||||||
actors[i].next_actor = next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i = j;
|
|
||||||
} while (1); // watchdog reset if actor not found to delete
|
|
||||||
}
|
|
||||||
actors[actor_index].next_actor = 0;
|
|
||||||
actors[actor_index].grid_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_actor(byte actor_index) {
|
|
||||||
struct Actor* a = &actors[actor_index];
|
|
||||||
insert_into_grid(xy2grid(a->x, a->y), actor_index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char in_rect(const Actor* e, byte x, byte y, byte w, byte h) {
|
char in_rect(const Actor* e, byte x, byte y, byte w, byte h) {
|
||||||
@ -521,78 +519,39 @@ char in_rect(const Actor* e, byte x, byte y, byte w, byte h) {
|
|||||||
return (x >= e->x-w && x <= e->x+ew && y >= e->y-h && y <= e->y+eh);
|
return (x >= e->x-w && x <= e->x+ew && y >= e->y-h && y <= e->y+eh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enumerate_actors_at_grid(ActorEnumerateFn enumfn, byte gi) {
|
|
||||||
byte ai = grid[gi & GMASK];
|
|
||||||
while (ai) {
|
|
||||||
const Actor* a = &actors[ai];
|
|
||||||
ai = a->next_actor;
|
|
||||||
enumfn(a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void enumerate_actors_in_rect(ActorEnumerateFn enumfn,
|
|
||||||
byte x1, byte y1, byte x2, byte y2) {
|
|
||||||
byte gi = xy2grid(x1, y1);
|
|
||||||
byte gi1 = xy2grid(x2, y2) + 1;
|
|
||||||
byte gwidth = 1 + ((gi1 - gi) & (GDIM-1));
|
|
||||||
byte x;
|
|
||||||
do {
|
|
||||||
for (x=0; x<gwidth; x++) {
|
|
||||||
byte ai = grid[gi];
|
|
||||||
while (ai) {
|
|
||||||
Actor* a = &actors[ai];
|
|
||||||
enumfn(a);
|
|
||||||
ai = a->next_actor;
|
|
||||||
}
|
|
||||||
gi++;
|
|
||||||
}
|
|
||||||
if (gi == gi1) break;
|
|
||||||
gi += GDIM - gwidth;
|
|
||||||
} while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_actor_normal(Actor* a) {
|
void draw_actor_normal(Actor* a) {
|
||||||
draw_sprite(a->shape, a->x, a->y);
|
draw_sprite(a->shape, a->x, a->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_actor_debug(Actor* a) {
|
void draw_actor_exploding(Actor* a) {
|
||||||
draw_sprite_solid(a->shape, a->x, a->y, a->grid_index);
|
erase_sprite_strided(a->shape, a->x, a->y, a->u.enemy.exploding);
|
||||||
|
if (a->u.enemy.exploding > 10) {
|
||||||
|
a->draw = NULL;
|
||||||
|
} else {
|
||||||
|
draw_sprite_strided(a->shape, a->x, a->y, ++a->u.enemy.exploding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte time_to_update(Actor* a) {
|
void update_actor(Actor* a) {
|
||||||
byte t0 = a->updatetimer;
|
|
||||||
return (a->updatetimer += a->updatefreq) < t0;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte update_actor(byte actor_index) {
|
|
||||||
struct Actor* a = &actors[actor_index];
|
|
||||||
byte next_actor = a->next_actor;
|
|
||||||
byte gi0,gi1;
|
|
||||||
// if NULL shape, we don't have anything
|
// if NULL shape, we don't have anything
|
||||||
if (a->shape && time_to_update(a)) {
|
if (a->shape) {
|
||||||
gi0 = a->grid_index;
|
|
||||||
// erase the sprite
|
// erase the sprite
|
||||||
draw_sprite_solid(a->shape, a->x, a->y, 0);
|
draw_sprite_solid(a->shape, a->x, a->y, 0);
|
||||||
// call update callback
|
// call update callback
|
||||||
if (a->update) a->update(a);
|
if (a->update) {
|
||||||
// set last_update_frame
|
a->update(a);
|
||||||
a->last_update_frame = frame;
|
}
|
||||||
// did we delete it?
|
// did we delete it?
|
||||||
if (a->shape) {
|
if (a->shape) {
|
||||||
// draw the sprite
|
// draw the sprite
|
||||||
if (a->draw) a->draw(a);
|
if (a->draw) {
|
||||||
// grid bucket changed?
|
a->draw(a);
|
||||||
gi1 = xy2grid(a->x, a->y);
|
|
||||||
if (gi0 != gi1) {
|
|
||||||
delete_from_grid(gi0, actor_index);
|
|
||||||
insert_into_grid(gi1, actor_index);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// shape NULL, delete from grid
|
// shape became null, remove from list
|
||||||
delete_from_grid(gi0, actor_index);
|
remove_actor(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return next_actor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -613,68 +572,133 @@ signed char random_dir() {
|
|||||||
else 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;
|
||||||
|
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 || 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline 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;
|
||||||
|
for (i=0; i<60; i++) {
|
||||||
|
WATCHDOG;
|
||||||
|
while (video_counter != 0xfc) ;
|
||||||
|
draw_sprite_solid(a->shape, a->x, a->y, i);
|
||||||
|
while (video_counter == 0xfc) ;
|
||||||
|
}
|
||||||
|
for (i=1; i<60; i++) {
|
||||||
|
WATCHDOG;
|
||||||
|
while (video_counter != 0xfc) ;
|
||||||
|
draw_sprite_strided(a->shape, a->x+i, a->y, i);
|
||||||
|
draw_sprite_strided(a->shape, a->x-i, a->y, i);
|
||||||
|
while (video_counter == 0xfc) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void random_walk(Actor* a) {
|
void random_walk(Actor* a) {
|
||||||
a->x += random_dir();
|
a->x += random_dir();
|
||||||
a->y += random_dir();
|
a->y += random_dir();
|
||||||
if (a->u.enemy.exploding) {
|
setup_collision(a);
|
||||||
a->shape = NULL;
|
if (actors[PLAYER].shape && test_collision_actor(&actors[PLAYER])) {
|
||||||
|
destroy_player();
|
||||||
|
actors[PLAYER].shape = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_grid_cell(byte grid_index) {
|
|
||||||
byte actor_index = grid[grid_index];
|
|
||||||
while (actor_index) {
|
|
||||||
actor_index = update_actor(actor_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_screen_section(byte gi0, byte gi1, byte vc0, byte vc1) {
|
|
||||||
while (!(video_counter >= vc0 && video_counter <= vc1)) ;
|
|
||||||
while (gi0 < gi1) {
|
|
||||||
update_grid_cell(gi0++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ensure_update(byte actor_index) {
|
|
||||||
if (actors[actor_index].last_update_frame != frame) {
|
|
||||||
update_actor(actor_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte did_overflow() {
|
|
||||||
__asm
|
|
||||||
ld l,#0
|
|
||||||
ret nc
|
|
||||||
inc l
|
|
||||||
__endasm;
|
|
||||||
}
|
|
||||||
|
|
||||||
static byte test_flags;
|
|
||||||
static byte test_x, test_y;
|
|
||||||
static Actor* test_collided;
|
|
||||||
|
|
||||||
void enumerate_check_point(Actor* a) {
|
|
||||||
// check flags to see if we should test this
|
|
||||||
if (!(a->flags & test_flags)) return;
|
|
||||||
draw_actor_debug(a);
|
|
||||||
if (in_rect(a, test_x, test_y, 1, 1)) test_collided = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void laser_move(Actor* a) {
|
void laser_move(Actor* a) {
|
||||||
// did we hit something?
|
// did we hit something?
|
||||||
test_x = a->x;
|
static Actor* collided;
|
||||||
test_y = a->y;
|
setup_collision(a);
|
||||||
test_flags = F_KILLABLE;
|
collided = test_collisions(fast_list);
|
||||||
test_collided = NULL;
|
if (!collided) collided = test_collisions(slow_lists[0]);
|
||||||
enumerate_actors_at_grid(enumerate_check_point, a->grid_index);
|
if (!collided) collided = test_collisions(slow_lists[1]);
|
||||||
enumerate_actors_at_grid(enumerate_check_point, a->grid_index-1);
|
if (!collided) collided = test_collisions(slow_lists[2]);
|
||||||
enumerate_actors_at_grid(enumerate_check_point, a->grid_index-GDIM);
|
if (!collided) collided = test_collisions(slow_lists[3]);
|
||||||
enumerate_actors_at_grid(enumerate_check_point, a->grid_index-GDIM-1);
|
if (collided) {
|
||||||
if (test_collided) {
|
|
||||||
// get rid of laser (we can do this in our 'update' fn)
|
// get rid of laser (we can do this in our 'update' fn)
|
||||||
a->shape = NULL;
|
a->shape = NULL;
|
||||||
// set exploding flag for enemy (we're not in its update)
|
// set exploding counter for enemy, change fn pointers
|
||||||
test_collided->u.enemy.exploding = 1;
|
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);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// move laser
|
// move laser
|
||||||
@ -686,21 +710,22 @@ void laser_move(Actor* a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void shoot_laser(sbyte dx, sbyte dy, const byte* shape) {
|
void shoot_laser(sbyte dx, sbyte dy, const byte* shape) {
|
||||||
actors[LASER].shape = (void*) shape;
|
Actor* a = &actors[LASER];
|
||||||
actors[LASER].x = actors[1].x;
|
a->shape = (void*) shape;
|
||||||
actors[LASER].y = actors[1].y;
|
a->x = actors[PLAYER].x + 6;
|
||||||
actors[LASER].u.laser.dx = dx;
|
a->y = actors[PLAYER].y + 8;
|
||||||
actors[LASER].u.laser.dy = dy;
|
a->u.laser.dx = dx;
|
||||||
add_actor(LASER);
|
a->u.laser.dy = dy;
|
||||||
|
add_actor(&player_list, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void player_laser() {
|
void player_laser() {
|
||||||
// shoot laser
|
// is the laser being used?
|
||||||
if (actors[LASER].shape == NULL) {
|
if (actors[LASER].shape == NULL) { // no, check controls
|
||||||
if (UP2) shoot_laser(0,-4,laser_vert);
|
if (UP2) shoot_laser(0,-8,laser_vert);
|
||||||
else if (DOWN2) shoot_laser(0,4,laser_vert);
|
else if (DOWN2) shoot_laser(0,8,laser_vert);
|
||||||
else if (LEFT2) shoot_laser(-4,0,laser_horiz);
|
else if (LEFT2) shoot_laser(-8,0,laser_horiz);
|
||||||
else if (RIGHT2) shoot_laser(4,0,laser_horiz);
|
else if (RIGHT2) shoot_laser(8,0,laser_horiz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,43 +741,107 @@ void player_move(Actor* a) {
|
|||||||
player_laser();
|
player_laser();
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void redraw_playfield(Actor* a) {
|
||||||
|
a;
|
||||||
|
draw_box(0,0,303,255,0x11);
|
||||||
|
}
|
||||||
|
|
||||||
|
Actor* new_effect(ActorDrawFn draw) {
|
||||||
|
Actor* a = new_actor();
|
||||||
|
a->draw = draw;
|
||||||
|
add_actor(&effects_list, a);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
byte i;
|
byte i;
|
||||||
byte num_actors = 16;
|
|
||||||
blit_solid(0, 0, 255, 255, 0);
|
blit_solid(0, 0, 255, 255, 0);
|
||||||
memset(grid, 0, sizeof(grid));
|
|
||||||
memset(actors, 0, sizeof(actors));
|
memset(actors, 0, sizeof(actors));
|
||||||
memcpy(palette, palette_data, 16);
|
memcpy(palette, palette_data, 16);
|
||||||
draw_box(0,0,303,255,0x11);
|
|
||||||
fill_char_table();
|
fill_char_table();
|
||||||
WATCHDOG;
|
player_list = fast_list = obstacle_list = free_list = NULL;
|
||||||
for (i=1; i<num_actors; i++) {
|
memset(slow_lists, 0, sizeof(slow_lists));
|
||||||
Actor* a = &actors[i];
|
// add all actors to free list
|
||||||
a->x = (i & 7) * 24 + 16;
|
for (i=MAX_ACTORS-1; i>0; i--) {
|
||||||
a->y = (i / 4) * 24 + 16;
|
add_actor(&free_list, &actors[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void make_player_actors() {
|
||||||
|
// make player
|
||||||
|
Actor* a = new_actor();
|
||||||
|
a->x = 128;
|
||||||
|
a->y = 120;
|
||||||
|
a->shape = (void*) 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 = rand() + rand();
|
||||||
|
a->y = rand() + rand();
|
||||||
|
} while ((byte)(a->x - 96) < 64 && (byte)(a->y - 96) < 64);
|
||||||
a->shape = (void*) all_sprites[i%9];
|
a->shape = (void*) all_sprites[i%9];
|
||||||
a->update = random_walk;
|
a->update = random_walk;
|
||||||
a->draw = draw_actor_normal;
|
a->draw = draw_actor_normal;
|
||||||
a->updatefreq = i*8;
|
if (i < 5) add_actor(&fast_list, a);
|
||||||
a->updatetimer = i*8;
|
else add_actor(&slow_lists[i&3], a);
|
||||||
if (i > LASER) a->flags = F_KILLABLE;
|
|
||||||
if (i != LASER) add_actor(i);
|
|
||||||
}
|
|
||||||
actors[PLAYER].shape = (void*) playersprite1;
|
|
||||||
actors[PLAYER].update = player_move;
|
|
||||||
actors[PLAYER].updatefreq = 0xff;
|
|
||||||
actors[LASER].update = laser_move;
|
|
||||||
actors[LASER].shape = NULL;
|
|
||||||
actors[LASER].updatefreq = 0xff;
|
|
||||||
WATCHDOG;
|
|
||||||
while (1) {
|
|
||||||
update_screen_section(GDIM2*3/4, GDIM2*4/4, 0x00, 0x2f);
|
|
||||||
update_screen_section(GDIM2*0/4, GDIM2*1/4, 0x30, 0x7f);
|
|
||||||
update_screen_section(GDIM2*1/4, GDIM2*2/4, 0x80, 0xbf);
|
|
||||||
update_screen_section(GDIM2*2/4, GDIM2*3/4, 0xc0, 0xff);
|
|
||||||
ensure_update(PLAYER);
|
|
||||||
ensure_update(LASER);
|
|
||||||
frame++;
|
|
||||||
WATCHDOG;
|
WATCHDOG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
init();
|
||||||
|
make_player_actors();
|
||||||
|
make_enemy_actors();
|
||||||
|
new_effect(redraw_playfield);
|
||||||
|
WATCHDOG;
|
||||||
|
while (actors[PLAYER].shape) {
|
||||||
|
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:
|
||||||
|
draw_box(0,0,303,255,0x11);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
frame++;
|
||||||
|
WATCHDOG;
|
||||||
|
}
|
||||||
|
main();
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
var WILLIAMS_PRESETS = [
|
var WILLIAMS_PRESETS = [
|
||||||
{id:'gfxtest.c', name:'Graphics Test'},
|
{id:'gfxtest.c', name:'Graphics Test'},
|
||||||
{id:'sprites.c', name:'Sprite Test'},
|
{id:'sprites.c', name:'Sprite Test'},
|
||||||
{id:'game1.c', name:'Game'},
|
{id:'game1.c', name:'Raster Paranoia Game'},
|
||||||
{id:'bitmap_rle.c', name:'RLE Bitmap'},
|
{id:'bitmap_rle.c', name:'RLE Bitmap'},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ var WilliamsPlatform = function(mainElement, proto) {
|
|||||||
var cpuFrequency = xtal/3/4;
|
var cpuFrequency = xtal/3/4;
|
||||||
var cpuCyclesPerFrame = cpuFrequency/60; // TODO
|
var cpuCyclesPerFrame = cpuFrequency/60; // TODO
|
||||||
var cpuScale = 1;
|
var cpuScale = 1;
|
||||||
var INITIAL_WATCHDOG = 64;
|
var INITIAL_WATCHDOG = 8;
|
||||||
var PIXEL_ON = 0xffeeeeee;
|
var PIXEL_ON = 0xffeeeeee;
|
||||||
var PIXEL_OFF = 0xff000000;
|
var PIXEL_OFF = 0xff000000;
|
||||||
|
|
||||||
@ -304,19 +304,25 @@ var WilliamsPlatform = function(mainElement, proto) {
|
|||||||
timer = new AnimationTimer(60, function() {
|
timer = new AnimationTimer(60, function() {
|
||||||
if (!self.isRunning())
|
if (!self.isRunning())
|
||||||
return;
|
return;
|
||||||
// interrupts happen every 1/4 of the screen
|
var cpuCyclesPerSection = Math.round(cpuCyclesPerFrame / 65);
|
||||||
for (var quarter=0; quarter<4; quarter++) {
|
for (var sl=0; sl<256; sl+=4) {
|
||||||
video_counter = [0x00, 0x3c, 0xbc, 0xfc][quarter];
|
video_counter = sl;
|
||||||
if (membus.read != memread_defender || pia6821[7] == 0x3c) { // TODO?
|
// interrupts happen every 1/4 of the screen
|
||||||
if (cpu.interrupt)
|
if (sl == 0 || sl == 0x3c || sl == 0xbc || sl == 0xfc) {
|
||||||
cpu.interrupt();
|
if (membus.read != memread_defender || pia6821[7] == 0x3c) { // TODO?
|
||||||
if (cpu.requestInterrupt)
|
if (cpu.interrupt)
|
||||||
cpu.requestInterrupt();
|
cpu.interrupt();
|
||||||
|
if (cpu.requestInterrupt)
|
||||||
|
cpu.requestInterrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!self.wasBreakpointHit())
|
if (!self.wasBreakpointHit())
|
||||||
self.runCPU(cpu, cpuCyclesPerFrame/4);
|
self.runCPU(cpu, cpuCyclesPerSection);
|
||||||
video.updateFrame(0, 0, quarter*64, 0, 64, 304);
|
if (sl < 256) video.updateFrame(0, 0, 256-4-sl, 0, 4, 304);
|
||||||
}
|
}
|
||||||
|
// last 6 lines
|
||||||
|
if (!self.wasBreakpointHit())
|
||||||
|
self.runCPU(cpu, cpuCyclesPerSection*2);
|
||||||
if (screenNeedsRefresh) {
|
if (screenNeedsRefresh) {
|
||||||
for (var i=0; i<0x9800; i++)
|
for (var i=0; i<0x9800; i++)
|
||||||
drawDisplayByte(i, ram.mem[i]);
|
drawDisplayByte(i, ram.mem[i]);
|
||||||
|
@ -451,8 +451,9 @@ worker.onmessage = function(e) {
|
|||||||
if (pendingWorkerMessages > 1) {
|
if (pendingWorkerMessages > 1) {
|
||||||
pendingWorkerMessages = 0;
|
pendingWorkerMessages = 0;
|
||||||
setCode(editor.getValue());
|
setCode(editor.getValue());
|
||||||
|
} else {
|
||||||
|
pendingWorkerMessages = 0;
|
||||||
}
|
}
|
||||||
pendingWorkerMessages = 0;
|
|
||||||
setCompileOutput(e.data);
|
setCompileOutput(e.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user