diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | animation.c | 10 | ||||
-rw-r--r-- | animation.h | 3 | ||||
-rw-r--r-- | animation_system.c | 5 | ||||
-rw-r--r-- | bullet.c | 27 | ||||
-rw-r--r-- | collision_system.c | 105 | ||||
-rw-r--r-- | components.h | 25 | ||||
-rw-r--r-- | enemy.c | 29 | ||||
-rw-r--r-- | fx.c | 40 | ||||
-rw-r--r-- | fx.h | 14 | ||||
-rw-r--r-- | intermediate/bullet.bmp | bin | 2714 -> 6026 bytes | |||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | player.c | 11 | ||||
-rw-r--r-- | rect.c | 25 | ||||
-rw-r--r-- | rect.h | 13 | ||||
-rw-r--r-- | systems.h | 4 | ||||
-rw-r--r-- | world.h | 1 |
17 files changed, 294 insertions, 21 deletions
@@ -89,7 +89,9 @@ sources = \ animation_system.c \ asset.c \ bullet.c \ + collision_system.c \ enemy.c \ + fx.c \ main.c \ malware.c \ platform.c \ diff --git a/animation.c b/animation.c index 6dbb08f..6cf2584 100644 --- a/animation.c +++ b/animation.c @@ -43,6 +43,16 @@ static const Animation animations[] = { 1, 1 }, + /* animation_enemy_bullet_explode */ + { + { + { 24, 0, 7, 7 }, + { 31, 0, 7, 7 }, + { 38, 0, 7, 7 } + }, + 3, + 5 + } }; const Animation* get_animation(Animation_ID id) { diff --git a/animation.h b/animation.h index e9e1399..65956a6 100644 --- a/animation.h +++ b/animation.h @@ -8,7 +8,8 @@ typedef enum { animation_player_walk_left = 0, animation_player_walk_right, animation_player_idle_left, - animation_player_idle_right + animation_player_idle_right, + animation_enemy_bullet_explode } Animation_ID; typedef struct { diff --git a/animation_system.c b/animation_system.c index 22317ac..8411e64 100644 --- a/animation_system.c +++ b/animation_system.c @@ -23,6 +23,11 @@ void animation_system(World* world) { } if (animated->frame >= animation->frame_count) { + if (bits & ctype_destroy_on_anim_done) { + destroy_entity(world, i); + continue; + } + animated->frame = 0; animated->timer = 0; } @@ -3,6 +3,7 @@ #include "error.h" #include "platform.h" #include "sprite.h" +#include "standard.h" #include "world.h" Entity new_player_bullet( @@ -17,6 +18,7 @@ Entity new_player_bullet( CBullet* bullet; CPosition* pos; CSprite* sprite; + CCollider* col; Sprite_ID sprid; e = new_entity(world); @@ -27,11 +29,13 @@ Entity new_player_bullet( ctype_sprite | ctype_position | ctype_bullet | - ctype_player_bullet + ctype_player_bullet | + ctype_collider ); pos = &world->positions[e]; sprite = &world->sprites[e]; bullet = &world->bullets[e]; + col = &world->colliders[e]; pos->x = x; pos->y = y; @@ -39,14 +43,25 @@ Entity new_player_bullet( bullet->vy = vy; bullet->life = life; + col->x = 0; + col->y = 0; + if (vx < 0) { sprid = sprite_player_bullet_left; + col->w = 9 << fbits; + col->h = 14 << fbits; } else if (vx > 0) { sprid = sprite_player_bullet_right; + col->w = 9 << fbits; + col->h = 14 << fbits; } else if (vy < 0) { sprid = sprite_player_bullet_up; + col->w = 9 << fbits; + col->h = 14 << fbits; } else if (vy > 0) { sprid = sprite_player_bullet_down; + col->w = 9 << fbits; + col->h = 14 << fbits; } #ifdef DEBUG else { @@ -71,6 +86,7 @@ int new_enemy_bullet( CBullet* bullet; CPosition* pos; CSprite* sprite; + CCollider* col; e = new_entity(world); @@ -80,11 +96,13 @@ int new_enemy_bullet( ctype_sprite | ctype_position | ctype_bullet | - ctype_enemy_bullet + ctype_enemy_bullet | + ctype_collider ); pos = &world->positions[e]; sprite = &world->sprites[e]; bullet = &world->bullets[e]; + col = &world->colliders[e]; pos->x = x; pos->y = y; @@ -92,6 +110,11 @@ int new_enemy_bullet( bullet->vy = vy; bullet->life = 500; + col->x = 1 << fbits; + col->y = 1 << fbits; + col->w = 3 << fbits; + col->h = 3 << fbits; + init_csprite(sprite, sprite_enemy_bullet); return e; diff --git a/collision_system.c b/collision_system.c new file mode 100644 index 0000000..abd5dc9 --- /dev/null +++ b/collision_system.c @@ -0,0 +1,105 @@ +#ifndef systems_h +#define systems_h + +#include "config.h" +#include "fx.h" +#include "rect.h" +#include "world.h" + +static void handle_bullet_vs_player( + World* world, + Entity bullet, + Entity player +) { + const CPosition* pos; + + pos = &world->positions[bullet]; + + destroy_entity(world, bullet); + new_enemy_bullet_explosion(world, pos->x, pos->y); +} + +static void handle_bullet_vs_enemy( + World* world, + Entity bullet, + Entity enemy +) { + CEnemy* e; + + e = &world->enemies[enemy]; + e->hp--; + destroy_entity(world, bullet); +} + +static void handle(World* world, Entity a, Entity b) { + unsigned ab, bb; + + ab = world->bitmask[a]; + bb = world->bitmask[b]; + + if ((ab & ctype_enemy_bullet) && (bb & ctype_player)) { + handle_bullet_vs_player(world, a, b); + return; + } + + if ((ab & ctype_player) && (bb & ctype_enemy_bullet)) { + handle_bullet_vs_player(world, b, a); + return; + } + + if ((ab & ctype_player_bullet) && (bb & ctype_enemy)) { + handle_bullet_vs_enemy(world, a, b); + return; + } + + if ((ab & ctype_enemy) && (bb & ctype_player_bullet)) { + handle_bullet_vs_enemy(world, b, a); + return; + } +} + +void collision_system(World* world) { + int i, j, p0x, p0y; + unsigned bits; + const CPosition* pos0, * pos1; + const CCollider* col0, * col1; + + for (i = 0; i < world->entity_count; i++) { + bits = world->bitmask[i]; + if ( + !(bits & ctype_collider) || + !(bits & ctype_position) + ) { continue; } + + pos0 = &world->positions[i]; + col0 = &world->colliders[i]; + p0x = pos0->x + col0->x; + p0y = pos0->y + col0->y; + + for (j = i + 1; j < world->entity_count; j++) { + bits = world->bitmask[j]; + if ( + !(bits & ctype_collider) || + !(bits & ctype_position) + ) { continue; } + + pos1 = &world->positions[j]; + col1 = &world->colliders[j]; + + if (rects_overlap2( + p0x, + p0y, + col0->w, + col0->h, + pos1->x + col1->x, + pos1->y + col1->y, + col1->w, + col1->h + )) { + handle(world, i, j); + } + } + } +} + +#endif diff --git a/components.h b/components.h index d288ac5..f23b35e 100644 --- a/components.h +++ b/components.h @@ -39,16 +39,23 @@ typedef struct { int vx, vy; } CDebris; +typedef struct { + int x, y, w, h; +} CCollider; + typedef enum { - ctype_sprite = 1 << 0, - ctype_position = 1 << 1, - ctype_animated = 1 << 2, - ctype_bullet = 1 << 3, - ctype_player_bullet = 1 << 4, - ctype_enemy_bullet = 1 << 5, - ctype_enemy = 1 << 6, - ctype_skull = 1 << 7, - ctype_debris = 1 << 8 + ctype_sprite = 1 << 0, + ctype_position = 1 << 1, + ctype_animated = 1 << 2, + ctype_bullet = 1 << 3, + ctype_player_bullet = 1 << 4, + ctype_enemy_bullet = 1 << 5, + ctype_enemy = 1 << 6, + ctype_skull = 1 << 7, + ctype_debris = 1 << 8, + ctype_collider = 1 << 9, + ctype_player = 1 << 10, + ctype_destroy_on_anim_done = 1 << 11 } CType; #endif @@ -9,6 +9,7 @@ Entity new_skull(World* world, int x, int y) { CSprite* sprite; CPosition* pos; CEnemy* enemy; + CCollider* col; Entity e; e = new_entity(world); @@ -18,15 +19,22 @@ Entity new_skull(World* world, int x, int y) { ctype_position | ctype_sprite | ctype_enemy | - ctype_skull + ctype_skull | + ctype_collider ); pos = &world->positions[e]; sprite = &world->sprites[e]; enemy = &world->enemies[e]; + col = &world->colliders[e]; pos->x = x; pos->y = y; + col->x = 2 << fbits; + col->y = 2 << fbits; + col->w = 14 << fbits; + col->h = 14 << fbits; + init_csprite(sprite, sprite_skull_right); enemy->hp = skull_hp; @@ -44,13 +52,22 @@ void enemy_system(World* world) { Player* player; CPosition* ppos; int dpx, dpy, tpx, tpy, d; - char buf[32]; player = &world->player; ppos = &world->positions[player->entity]; for (i = 0; i < world->entity_count; i++) { bits = world->bitmask[i]; + if (bits & ctype_enemy) { + enemy = &world->enemies[i]; + if (enemy->hp <= 0) { + destroy_entity(world, i); + } + } + } + + for (i = 0; i < world->entity_count; i++) { + bits = world->bitmask[i]; if ( (bits & ctype_position) && (bits & ctype_enemy) && @@ -59,8 +76,8 @@ void enemy_system(World* world) { pos = &world->positions[i]; enemy = &world->enemies[i]; - dpx = (ppos->x - pos->x) >> 4; - dpy = (ppos->y - pos->y) >> 4; + dpx = ((ppos->x - pos->x) >> 4) + 256; + dpy = ((ppos->y - pos->y) >> 4) + 256; tpx = dpx; tpy = dpy; d = ((dpx * dpx) >> fbits) + ((dpy * dpy) >> fbits); @@ -89,8 +106,8 @@ void enemy_system(World* world) { new_enemy_bullet( world, - pos->x, - pos->y, + pos->x + 2560, + pos->y + 2560, tpx * enemy_bullet_speed, tpy * enemy_bullet_speed ); @@ -0,0 +1,40 @@ +#include "components.h" +#include "fx.h" +#include "world.h" + +int new_enemy_bullet_explosion( + World* world, + int x, + int y +) { + Entity e; + CPosition* pos; + CSprite* sprite; + CAnimated* animated; + + e = new_entity(world); + add_components( + world, + e, + ctype_sprite | + ctype_position | + ctype_animated | + ctype_destroy_on_anim_done + ); + + pos = &world->positions[e]; + sprite = &world->sprites[e]; + animated = &world->animateds[e]; + + pos->x = x; + pos->y = y; + + sprite->id = asset_id_bullet; + sprite->rect = make_rect(0, 0, 16, 16); + + animated->id = animation_enemy_bullet_explode; + animated->frame = 0; + animated->timer = 0; + + return e; +} @@ -0,0 +1,14 @@ +#ifndef fx_h +#define fx_h + +#include "animation.h" + +struct World; + +int new_enemy_bullet_explosion( + struct World* world, + int x, + int y +); + +#endif diff --git a/intermediate/bullet.bmp b/intermediate/bullet.bmp Binary files differindex e6735ce..e92d3fb 100644 --- a/intermediate/bullet.bmp +++ b/intermediate/bullet.bmp @@ -27,6 +27,7 @@ void on_update() { update_player(&world.player, &world); enemy_system(&world); bullet_system(&world); + collision_system(&world); animation_system(&world); sprite_system(&world); } @@ -11,6 +11,7 @@ void init_player(Player* player, World* world) { CSprite* sprite; CPosition* pos; CAnimated* animated; + CCollider* col; Entity e; e = new_entity(world); @@ -20,11 +21,14 @@ void init_player(Player* player, World* world) { e, ctype_sprite | ctype_position | - ctype_animated + ctype_animated | + ctype_collider | + ctype_player ); pos = &world->positions[e]; sprite = &world->sprites[e]; animated = &world->animateds[e]; + col = &world->colliders[e]; pos->x = 32 << fbits; pos->y = 70 << fbits; @@ -36,6 +40,11 @@ void init_player(Player* player, World* world) { animated->frame = 0; animated->timer = 0; + col->x = 3 << fbits; + col->y = 1 << fbits; + col->w = 10 << fbits; + col->h = 15 << fbits; + player->face = 0; player->shoot_cooldown = 15; player->shoot_countdown = 0; @@ -8,3 +8,28 @@ Rectangle make_rect(int x, int y, int w, int h) { r.h = h; return r; } + +int rects_overlap(const Rectangle* a, const Rectangle* b) { + return + a->x + a->w > b->x && + a->y + a->h > b->y && + a->x < b->x + b->w && + a->y < b->y + b->h; +} + +int rects_overlap2( + int x0, + int y0, + int w0, + int h0, + int x1, + int y1, + int w1, + int h1 +) { + return + x0 + w0 > x1 && + y0 + h0 > y1 && + x0 < x1 + w1 && + y0 < y1 + h1; +} @@ -7,4 +7,17 @@ typedef struct { Rectangle make_rect(int x, int y, int w, int h); +int rects_overlap(const Rectangle* a, const Rectangle* b); + +int rects_overlap2( + int x0, + int y0, + int w0, + int h0, + int x1, + int y1, + int w1, + int h1 +); + #endif @@ -5,8 +5,8 @@ void animation_system(World* world); void bullet_system(World* world); -void sprite_system(const World* world); +void collision_system(World* world); void enemy_system(World* world); - +void sprite_system(const World* world); #endif @@ -21,6 +21,7 @@ struct World { CAnimated animateds [max_entities]; CBullet bullets [max_entities]; CEnemy enemies [max_entities]; + CCollider colliders [max_entities]; Player player; }; |