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 0000000..e81fb69 Binary files /dev/null and b/assets/small_old_man.png differ diff --git a/codegen.c b/codegen.c index 1793881..ea207cb 100644 --- a/codegen.c +++ b/codegen.c @@ -114,6 +114,7 @@ int main(int argc, char **argv) { MD_String8List load_list = {0}; MD_String8List level_decl_list = {0}; MD_String8List tileset_decls = {0}; + MD_String8List object_decls_list = {0}; for(MD_EachNode(node, parse.node->first_child)) { 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; } } }