From d61dcdcc384249ec7ea60c9cc18aab9df1f80577 Mon Sep 17 00:00:00 2001 From: quou Date: Thu, 4 May 2023 14:10:41 +1000 Subject: Add shooting. --- Makefile | 2 ++ bullet.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bullet.h | 15 +++++++++++ components.h | 17 ++++++++++--- config.h | 4 +++ error.h | 3 ++- game_config.h | 1 + main.c | 1 + player.c | 21 ++++++++++++++++ player.h | 3 +++ sprite.c | 32 ++++++++++++++++++++++++ sprite.h | 22 ++++++++++++++++ systems.h | 1 + world.h | 10 ++++---- 14 files changed, 203 insertions(+), 9 deletions(-) create mode 100644 bullet.c create mode 100644 bullet.h create mode 100644 sprite.c create mode 100644 sprite.h diff --git a/Makefile b/Makefile index d9c53b0..02a40ff 100644 --- a/Makefile +++ b/Makefile @@ -88,12 +88,14 @@ sources = \ animation.c \ animation_system.c \ asset.c \ + bullet.c \ main.c \ malware.c \ platform.c \ player.c \ rect.c \ render.c \ + sprite.c \ sprite_system.c \ standard.c \ world.c \ diff --git a/bullet.c b/bullet.c new file mode 100644 index 0000000..f2e1a2e --- /dev/null +++ b/bullet.c @@ -0,0 +1,80 @@ +#include "bullet.h" +#include "components.h" +#include "error.h" +#include "platform.h" +#include "sprite.h" +#include "world.h" + +Entity new_player_bullet( + World* world, + int x, + int y, + int vx, + int vy, + int life +) { + Entity e; + CBullet* bullet; + CPosition* pos; + CSprite* sprite; + Sprite_ID sprid; + + e = new_entity(world); + + add_components( + world, + e, + ctype_sprite | + ctype_position | + ctype_bullet | + ctype_player_bullet + ); + pos = &world->positions[e]; + sprite = &world->sprites[e]; + bullet = &world->bullets[e]; + pos->x = x; + pos->y = y; + + bullet->vx = vx; + bullet->vy = vy; + bullet->life = life; + + if (vx < 0) { + sprid = sprite_player_bullet_left; + } else if (vx > 0) { + sprid = sprite_player_bullet_right; + } else if (vy < 0) { + sprid = sprite_player_bullet_up; + } else if (vy > 0) { + sprid = sprite_player_bullet_down; + } +#ifdef DEBUG + else { + platform_log("Player bullets must have velocity\n"); + platform_abort(error_gameplay_error); + } +#endif + + init_csprite(sprite, sprid); + + return e; +} + +void bullet_system(World* world) { + int i; + unsigned bits; + CPosition* pos; + CBullet* bullet; + + for (i = 0; i < world->entity_count; i++) { + bits = world->bitmask[i]; + if ((bits & ctype_position) && (bits & ctype_bullet)) { + pos = &world->positions[i]; + bullet = &world->bullets[i]; + + pos->x += bullet->vx; + pos->y += bullet->vy; + bullet->life--; + } + } +} diff --git a/bullet.h b/bullet.h new file mode 100644 index 0000000..cd7a436 --- /dev/null +++ b/bullet.h @@ -0,0 +1,15 @@ +#ifndef bullet_h +#define bullet_h + +struct World; + +int new_player_bullet( + struct World* world, + int x, + int y, + int vx, + int vy, + int life +); + +#endif diff --git a/components.h b/components.h index 84cfc54..66304df 100644 --- a/components.h +++ b/components.h @@ -5,6 +5,9 @@ #include "asset.h" #include "rect.h" +/* Components are POD. If you put a pointer in one of these, + * you're a dumb poo poo head. */ + typedef struct { int x, y; } CPosition; @@ -21,10 +24,18 @@ typedef struct { int timer; } CAnimated; +typedef struct { + int life; + int vx, vy; +} CBullet; + typedef enum { - ctype_sprite = 1 << 0, - ctype_position = 1 << 1, - ctype_animated = 1 << 2 + 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; #endif diff --git a/config.h b/config.h index 273f9a5..063781b 100644 --- a/config.h +++ b/config.h @@ -17,4 +17,8 @@ #define animation_max_frames 8 +#define max_entities 256 +#define max_player_bullets 32 +#define max_enemy_bullets 256 + #endif diff --git a/error.h b/error.h index 52b9422..bd2dbd4 100644 --- a/error.h +++ b/error.h @@ -5,7 +5,8 @@ typedef enum { error_none = 0, error_file_not_found, error_out_of_memory, - error_invalid_asset + error_invalid_asset, + error_gameplay_error } Error; #endif diff --git a/game_config.h b/game_config.h index c4efee7..7bb6cdd 100644 --- a/game_config.h +++ b/game_config.h @@ -2,5 +2,6 @@ #define game_config_h #define player_move_speed (3 << fbits) +#define player_bullet_speed (10 << fbits) #endif diff --git a/main.c b/main.c index 7cfaf83..e1fd29b 100644 --- a/main.c +++ b/main.c @@ -22,6 +22,7 @@ void on_init(int argc, char** argv) { void on_update() { renderer_begin_frame(); update_player(&world.player, &world); + bullet_system(&world); animation_system(&world); sprite_system(&world); } diff --git a/player.c b/player.c index 801dc33..cadb0dc 100644 --- a/player.c +++ b/player.c @@ -5,6 +5,7 @@ #include "player.h" #include "standard.h" #include "world.h" +#include "bullet.h" void init_player(Player* player, World* world) { CSprite* sprite; @@ -36,6 +37,8 @@ void init_player(Player* player, World* world) { animated->timer = 0; player->face = 0; + player->shoot_cooldown = 15; + player->shoot_countdown = 0; } void update_player(Player* player, World* world) { @@ -78,6 +81,9 @@ void update_player(Player* player, World* world) { pos->x += (dx * player_move_speed) >> fbits; pos->y += (dy * player_move_speed) >> fbits; + player->ldx = dx; + player->ldy = dy; + moving = 1; } @@ -95,4 +101,19 @@ void update_player(Player* player, World* world) { animation_player_walk_right : animation_player_walk_left; } + + if (button_pressed(btn_shoot) && player->shoot_countdown <= 0) { + new_player_bullet( + world, + pos->x, + pos->y, + (player->ldx * player_bullet_speed) >> fbits, + (player->ldy * player_bullet_speed) >> fbits, + 100 + ); + + player->shoot_countdown = player->shoot_cooldown; + } + + player->shoot_countdown--; } diff --git a/player.h b/player.h index 8412bde..da1605e 100644 --- a/player.h +++ b/player.h @@ -6,6 +6,9 @@ struct World; typedef struct { int entity; int face; + int ldx, ldy; + int shoot_cooldown; + int shoot_countdown; } Player; void init_player(Player* player, struct World* world); diff --git a/sprite.c b/sprite.c new file mode 100644 index 0000000..8289fd2 --- /dev/null +++ b/sprite.c @@ -0,0 +1,32 @@ +#include "sprite.h" + +static const Sprite sprites[] = { + /* sprite_player_bullet_left */ + { + asset_id_bullet, + { 9, 0, 9, 14 } + }, + /* sprite_player_bullet_right */ + { + asset_id_bullet, + { 0, 0, 9, 14 } + }, + /* sprite_player_bullet_up */ + { + asset_id_bullet, + { 0, 14, 14, 9 } + }, + /* sprite_player_bullet_down */ + { + asset_id_bullet, + { 14, 14, 14, 9 } + } +}; + +void init_csprite(CSprite* sprite, Sprite_ID id) { + const Sprite* s; + + s = &sprites[id]; + sprite->id = s->bitmap; + sprite->rect = s->rect; +} diff --git a/sprite.h b/sprite.h new file mode 100644 index 0000000..a520b99 --- /dev/null +++ b/sprite.h @@ -0,0 +1,22 @@ +#ifndef sprite_h +#define sprite_h + +#include "asset.h" +#include "components.h" +#include "rect.h" + +typedef enum { + sprite_player_bullet_left = 0, + sprite_player_bullet_right, + sprite_player_bullet_up, + sprite_player_bullet_down +} Sprite_ID; + +typedef struct { + Asset_ID bitmap; + Rectangle rect; +} Sprite; + +void init_csprite(CSprite* sprite, Sprite_ID id); + +#endif diff --git a/systems.h b/systems.h index 24bc9c2..0e405dd 100644 --- a/systems.h +++ b/systems.h @@ -4,6 +4,7 @@ #include "world.h" void animation_system(World* world); +void bullet_system(World* world); void sprite_system(const World* world); #endif diff --git a/world.h b/world.h index 9871e9b..3127f37 100644 --- a/world.h +++ b/world.h @@ -2,10 +2,9 @@ #define world_h #include "components.h" +#include "config.h" #include "player.h" -#define max_entities 256 - typedef int Entity; typedef struct World World; @@ -15,9 +14,10 @@ struct World { unsigned char bitmask[max_entities]; - CSprite sprites [max_entities]; - CPosition positions[max_entities]; - CAnimated animateds[max_entities]; + CSprite sprites [max_entities]; + CPosition positions [max_entities]; + CAnimated animateds [max_entities]; + CBullet bullets [max_entities]; Player player; }; -- cgit v1.2.3-54-g00ecf