From 1ee06fa381595297e0c2bb7d52abe1a8074b2e23 Mon Sep 17 00:00:00 2001 From: Cameron Reikes Date: Tue, 21 Feb 2023 23:52:50 -0800 Subject: [PATCH] Entity array, codegen all object spawnpoints --- assets.mdesk | 4 ++ assets/small_old_man.png | Bin 0 -> 10774 bytes codegen.c | 13 ++--- main.c | 108 ++++++++++++++++++++++++++++----------- 4 files changed, 88 insertions(+), 37 deletions(-) create mode 100644 assets/small_old_man.png diff --git a/assets.mdesk b/assets.mdesk index 2257566..9d6c6f9 100644 --- a/assets.mdesk +++ b/assets.mdesk @@ -14,6 +14,10 @@ { filepath: "_Attack.png", } +@image old_man: +{ + filepath: "small_old_man.png", +} @image animated_terrain: { filepath: "copyrighted/animated_terrain.png", diff --git a/assets/small_old_man.png b/assets/small_old_man.png new file mode 100644 index 0000000000000000000000000000000000000000..e81fb69af90148c0e7b460c29d8ee8d3c7c8aa49 GIT binary patch literal 10774 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 { if(MD_S8Match(node->first_tag->string, MD_S8Lit("image"), 0)) { MD_String8 variable_name = MD_S8Fmt(cg_arena, "image_%.*s", MD_S8VArg(node->string)); @@ -180,11 +181,10 @@ int main(int argc, char **argv) { if(MD_S8Match(type, MD_S8Lit("objectgroup"), 0)) { for(MD_EachNode(object, MD_ChildFromString(lay, MD_S8Lit("objects"), 0)->first_child)) { dump(object); - if(MD_S8Match(MD_ChildFromString(object, MD_S8Lit("name"), 0)->first_child->string, MD_S8Lit("spawn"), 0)) { - MD_String8 x_string = MD_ChildFromString(object, MD_S8Lit("x"), 0)->first_child->string; - MD_String8 y_string = MD_ChildFromString(object, MD_S8Lit("y"), 0)->first_child->string; - fprintf(output, ".spawnpoint = { %.*s, %.*s },\n", MD_S8VArg(x_string), MD_S8VArg(y_string)); - } + MD_String8 name = MD_ChildFromString(object, MD_S8Lit("name"), 0)->first_child->string; + MD_String8 x_string = MD_ChildFromString(object, MD_S8Lit("x"), 0)->first_child->string; + MD_String8 y_string = MD_ChildFromString(object, MD_S8Lit("y"), 0)->first_child->string; + list_printf(&object_decls_list, "Vec2 %.*s_tilepoint = { %.*s, %.*s };\n", MD_S8VArg(name), MD_S8VArg(x_string), MD_S8VArg(y_string)); } } if(MD_S8Match(type, MD_S8Lit("tilelayer"), 0)) { @@ -215,9 +215,10 @@ int main(int argc, char **argv) { MD_StringJoin join = MD_ZERO_STRUCT; MD_String8 declarations = MD_S8ListJoin(cg_arena, declarations_list, &join); + MD_String8 object_declarations = MD_S8ListJoin(cg_arena, object_decls_list, &join); MD_String8 loads = MD_S8ListJoin(cg_arena, load_list, &join); fprintf(output, "%.*s\nvoid load_assets() {\n%.*s\n}\n", MD_S8VArg(declarations), MD_S8VArg(loads)); - fprintf(output, "%.*s\n", MD_S8VArg(MD_S8ListJoin(cg_arena, tileset_decls, &join))); + fprintf(output, "%.*s\n%.*s\n", MD_S8VArg(MD_S8ListJoin(cg_arena, tileset_decls, &join)), MD_S8VArg(object_declarations)); fclose(output); return 0; diff --git a/main.c b/main.c index b40f51d..9cadb91 100644 --- a/main.c +++ b/main.c @@ -16,6 +16,8 @@ #include +#define ARRLEN(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + typedef struct AABB { Vec2 upper_left; @@ -137,6 +139,13 @@ Vec2 tilecoord_to_world(TileCoord t) return V2( (float)t.x * (float)TILE_SIZE * 1.0f, -(float)t.y * (float)TILE_SIZE * 1.0f ); } +// points from tiled editor have their own strange and alien coordinate system (local to the tilemap Y+ down) +Vec2 tilepoint_to_world(Vec2 tilepoint) +{ + Vec2 tilecoord = MulV2F(tilepoint, 1.0/TILE_SIZE); + return tilecoord_to_world((TileCoord){(int)tilecoord.X, (int)tilecoord.Y}); +} + TileCoord world_to_tilecoord(Vec2 w) { // world = V2(tilecoord.x * tile_size, -tilecoord.y * tile_size) @@ -251,6 +260,16 @@ AnimatedSprite knight_attack = .no_wrap = true, }; +AnimatedSprite old_man_idle = +{ + .img = &image_old_man, + .time_per_frame = 0.4, + .num_frames = 4, + .start = {0.0, 0.0}, + .horizontal_diff_btwn_frames = 16.0f, + .region_size = {16.0f, 16.0f}, +}; + sg_image image_font = {0}; const float font_size = 32.0; stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs @@ -272,17 +291,44 @@ typedef enum CharacterState CHARACTER_ATTACK, } CharacterState; -typedef struct Character +typedef enum EntityKind { - CharacterState state; + Player, + OldMan, +} EntityKind; + +typedef struct Entity +{ + bool exists; + EntityKind kind; + Vec2 pos; bool facing_left; - // swinging + // character + CharacterState state; double swing_progress; -} Character; -Character player = {0}; +} Entity; + +Entity entities[128] = {0}; +Entity *player = NULL; + +Entity *new_entity() +{ + for(int i = 0; i < ARRLEN(entities); i++) + { + if(!entities[i].exists) + { + Entity *to_return = &entities[i]; + *to_return = (Entity){0}; + to_return->exists = true; + return to_return; + } + } + assert(false); + return NULL; +} void init(void) { @@ -294,9 +340,8 @@ void init(void) load_assets(); - // player spawnpoint - Vec2 spawnpoint_tilecoord = MulV2F(level_level0.spawnpoint, 1.0/TILE_SIZE); - player.pos = tilecoord_to_world((TileCoord){(int)spawnpoint_tilecoord.X, (int)spawnpoint_tilecoord.Y}); + player = new_entity(); + player->pos = tilepoint_to_world(spawn_tilepoint); // load font { @@ -555,8 +600,7 @@ bool overlapping(AABB a, AABB b) return true; // both segments overlapping } -// points must be of length 4, and be in the order: upper left, upper right, lower right, lower left -// the points are in pixels in screen space. The image region is in pixel space of the image +// The image region is in pixel space of the image void draw_quad(bool world_space, Quad quad, sg_image image, AABB image_region, Color tint) { Vec2 *points = quad.points; @@ -597,6 +641,7 @@ void draw_quad(bool world_space, Quad quad, sg_image image, AABB image_region, C AddV2(image_region.upper_left, V2(region_size.X, region_size.Y)), AddV2(image_region.upper_left, V2(0.0, region_size.Y)), }; + // convert to uv space sg_image_info info = sg_query_image_info(image); for(int i = 0; i < 4; i++) @@ -935,7 +980,7 @@ void frame(void) } #endif - //if(LengthV2(movement) > 0.01 && player.state == CHARACTER_) + //if(LengthV2(movement) > 0.01 && player->state == CHARACTER_) #ifdef DEVTOOLS dbgsquare(screen_to_world(mouse_pos)); @@ -950,7 +995,7 @@ void frame(void) // line test { - dbgline(player.pos, screen_to_world(mouse_pos)); + dbgline(player->pos, screen_to_world(mouse_pos)); } // debug draw font image @@ -973,7 +1018,7 @@ void frame(void) #if 0 const char *text = "great idea\nother idea"; // measure text - Vec2 pos = player.pos; + Vec2 pos = player->pos; { AABB bounds = draw_text(true, true, text, strlen(text), pos, WHITE); @@ -988,43 +1033,44 @@ void frame(void) #endif // devtools + draw_animated_sprite(&old_man_idle, time, false, V2(884.788635f, -928.000000f), WHITE); // player character { - Vec2 character_sprite_pos = AddV2(player.pos, V2(0.0, 20.0f)); + Vec2 character_sprite_pos = AddV2(player->pos, V2(0.0, 20.0f)); - if(attack && (player.state == CHARACTER_IDLE || player.state == CHARACTER_WALKING)) + if(attack && (player->state == CHARACTER_IDLE || player->state == CHARACTER_WALKING)) { - player.state = CHARACTER_ATTACK; - player.swing_progress = 0.0; + player->state = CHARACTER_ATTACK; + player->swing_progress = 0.0; } - cam.pos = LerpV2(cam.pos, dt*8.0f, MulV2F(player.pos, -1.0f * cam.scale)); - if(player.state == CHARACTER_WALKING) + cam.pos = LerpV2(cam.pos, dt*8.0f, MulV2F(player->pos, -1.0f * cam.scale)); + if(player->state == CHARACTER_WALKING) { - player.pos = move_and_slide(player.pos, MulV2F(movement, dt * pixels_per_meter * 4.0f), V2(TILE_SIZE, TILE_SIZE)); - draw_animated_sprite(&knight_running, time, player.facing_left, character_sprite_pos, WHITE); + player->pos = move_and_slide(player->pos, MulV2F(movement, dt * pixels_per_meter * 4.0f), V2(TILE_SIZE, TILE_SIZE)); + draw_animated_sprite(&knight_running, time, player->facing_left, character_sprite_pos, WHITE); if(LenV2(movement) == 0.0) { - player.state = CHARACTER_IDLE; + player->state = CHARACTER_IDLE; } else { - player.facing_left = movement.X < 0.0f; + player->facing_left = movement.X < 0.0f; } } - else if(player.state == CHARACTER_IDLE) + else if(player->state == CHARACTER_IDLE) { - draw_animated_sprite(&knight_idle, time, player.facing_left, character_sprite_pos, WHITE); - if(LenV2(movement) > 0.01) player.state = CHARACTER_WALKING; + draw_animated_sprite(&knight_idle, time, player->facing_left, character_sprite_pos, WHITE); + if(LenV2(movement) > 0.01) player->state = CHARACTER_WALKING; } - else if(player.state == CHARACTER_ATTACK) + else if(player->state == CHARACTER_ATTACK) { - player.swing_progress += dt; - draw_animated_sprite(&knight_attack, player.swing_progress, player.facing_left, character_sprite_pos, WHITE); - if(player.swing_progress > anim_sprite_duration(&knight_attack)) + player->swing_progress += dt; + draw_animated_sprite(&knight_attack, player->swing_progress, player->facing_left, character_sprite_pos, WHITE); + if(player->swing_progress > anim_sprite_duration(&knight_attack)) { - player.state = CHARACTER_IDLE; + player->state = CHARACTER_IDLE; } } }