Compare commits

...

4 Commits

Author SHA1 Message Date
En Yi f4167c6270 Add chest count in main game 2024-08-20 16:38:07 +08:00
En Yi bae17e8a87 Add level ending in main game 2024-08-20 14:52:26 +08:00
En Yi f208964e7f Fix rendering for finishing the level 2024-08-20 14:03:59 +08:00
En Yi 2be80ea6bf Add sprites for player finishing the stage
Also add cave exit sprite

They are all placeholder for now.
2024-08-20 14:03:41 +08:00
10 changed files with 169 additions and 29 deletions

View File

@ -275,7 +275,7 @@ static LevelPack_t* add_level_pack_zst(Assets_t* assets, const char* name, const
for (lvls = 0; lvls < n_levels; ++lvls)
{
printf("Parsing level %u\n", lvls);
output.size = 36;
output.size = 38;
output.pos = 0;
do
@ -310,6 +310,7 @@ static LevelPack_t* add_level_pack_zst(Assets_t* assets, const char* name, const
memcpy(pack_info->pack.levels[lvls].level_name, level_decompressor.out_buffer, 32);
memcpy(&pack_info->pack.levels[lvls].width, level_decompressor.out_buffer + 32, 2);
memcpy(&pack_info->pack.levels[lvls].height, level_decompressor.out_buffer + 34, 2);
memcpy(&pack_info->pack.levels[lvls].n_chests, level_decompressor.out_buffer + 36, 2);
pack_info->pack.levels[lvls].level_name[31] = '\0';
printf("Level name: %s\n", pack_info->pack.levels[lvls].level_name);
printf("WxH: %u %u\n", pack_info->pack.levels[lvls].width, pack_info->pack.levels[lvls].height);

View File

@ -58,6 +58,7 @@ typedef struct LevelMap
char level_name[32];
uint16_t width;
uint16_t height;
uint16_t n_chests;
LevelTileInfo_t* tiles;
}LevelMap_t;

View File

@ -38,6 +38,7 @@ ENUMIDS_TILETYPE_MAPPING = {
'Runner': 21,
'Player': 22,
'Chest': 23,
'Exit': 24,
}
#ENTID_MAPPING = {
@ -76,6 +77,7 @@ with open(converted_filename, 'wb+') as out_file:
out_file.write(struct.pack("<I", n_levels))
# Then loop the levels. Read the layerIndstances
for level in level_pack_data["levels"]:
n_chests : int = 0
# Search for __identifier for the level layout
level_name = level["identifier"]
print("Parsing level", level_name)
@ -103,6 +105,8 @@ with open(converted_filename, 'wb+') as out_file:
for i, tile in enumerate(level_layout["gridTiles"]):
try:
tiles_info[tile["d"][0]][0] = ids_tiletype_map[tile["t"]]
if tiles_info[tile["d"][0]][0] == ENUMIDS_TILETYPE_MAPPING ["Chest"]:
n_chests += 1
except Exception as e:
print("Error on tile", i, i % width, i // height)
print(e)
@ -116,7 +120,7 @@ with open(converted_filename, 'wb+') as out_file:
x,y = ent["__grid"]
tiles_info[y*width + x][0] = ENUMIDS_TILETYPE_MAPPING[ent["__identifier"]]
out_file.write(struct.pack("<32s2H", level_name.encode('utf-8'), width, height))
out_file.write(struct.pack("<32s3H", level_name.encode('utf-8'), width, height, n_chests))
for tile in tiles_info:
out_file.write(struct.pack("<3Bx", *tile))

View File

@ -248,10 +248,38 @@ static void render_editor_game_scene(Scene_t* scene)
}
}
sc_map_foreach_value(&scene->ent_manager.entities_map[LEVEL_END_TAG], p_ent)
{
CSprite_t* p_cspr = get_component(p_ent, CSPRITE_T);
if (p_cspr != NULL)
{
const SpriteRenderInfo_t spr = p_cspr->sprites[p_cspr->current_idx];
if (spr.sprite != NULL)
{
Vector2 pos = p_ent->position;
pos = Vector2Subtract(
pos,
get_anchor_offset(spr.sprite->frame_size, spr.src_anchor, p_cspr->flip_x)
);
Vector2 offset = spr.offset;
if (p_cspr->flip_x) offset.x *= -1;
pos = Vector2Add(pos, offset);
draw_sprite(spr.sprite, (data->coins.current < data->coins.total) ? 0 : 1, pos, 0.0f, p_cspr->flip_x);
}
}
else
{
DrawCircleV(p_ent->position, tilemap.tile_size >> 1, (data->coins.current < data->coins.total)? RED : GREEN);
}
}
char buffer[64] = {0};
sc_map_foreach_value(&scene->ent_manager.entities, p_ent)
{
if (p_ent->m_tag == LEVEL_END_TAG) continue;
CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
// Entity culling
@ -393,11 +421,11 @@ static void render_editor_game_scene(Scene_t* scene)
pos,
get_anchor_offset(p_bbox->size, spr.dest_anchor, p_cspr->flip_x)
);
pos = Vector2Subtract(
pos,
get_anchor_offset(spr.sprite->frame_size, spr.src_anchor, p_cspr->flip_x)
);
}
pos = Vector2Subtract(
pos,
get_anchor_offset(spr.sprite->frame_size, spr.src_anchor, p_cspr->flip_x)
);
Vector2 offset = spr.offset;
if (p_cspr->flip_x) offset.x *= -1;
@ -408,11 +436,6 @@ static void render_editor_game_scene(Scene_t* scene)
}
}
sc_map_foreach_value(&scene->ent_manager.entities_map[LEVEL_END_TAG], p_ent)
{
DrawCircleV(p_ent->position, tilemap.tile_size >> 1, (data->coins.current < data->coins.total)? RED : GREEN);
}
for (int tile_y = min.y; tile_y < max.y; tile_y++)
{
for (int tile_x = min.x; tile_x < max.x; tile_x++)
@ -1131,7 +1154,7 @@ static void at_level_complete(Scene_t* scene)
data->sm.fractional -= 1.0f;
data->sm.counter++;
}
if (data->sm.counter >= 3)
if (data->sm.counter >= 1)
{
do_action(scene, ACTION_NEXTLEVEL, true);
at_level_dead(scene);
@ -1195,6 +1218,20 @@ void init_sandbox_scene(LevelScene_t* scene)
scene->data.game_rec
);
{
Entity_t* p_player = create_player(&scene->scene.ent_manager);
CSprite_t* p_cspr = get_component(p_player, CSPRITE_T);
p_cspr->flip_x = true;
p_player->position.x = 100;
p_player->position.y = (scene->data.tilemap.height - 2) * scene->data.tilemap.tile_size;
scene->data.player_spawn = p_player->position;
scene->data.camera.target_pos = p_player->position;
scene->data.camera.cam.target = p_player->position;
}
update_entity_manager(&scene->scene.ent_manager);
BeginTextureMode(scene->scene.layers.render_layers[SELECTION_LAYER].layer_tex);
ClearBackground(LIGHTGRAY);
Vector2 draw_pos = {0, 0};
@ -1370,8 +1407,6 @@ void init_sandbox_scene(LevelScene_t* scene)
EndTextureMode();
create_player(&scene->scene.ent_manager);
update_entity_manager(&scene->scene.ent_manager);
// insert level scene systems
sc_array_add(&scene->scene.systems, &update_tilemap_system);

View File

@ -7,6 +7,7 @@ bool init_player_creation(const char* info_file, Assets_t* assets);
bool init_player_creation_rres(const char* rres_file, const char* file, Assets_t* assets);
Entity_t* create_player(EntityManager_t* ent_manager);
Entity_t* create_dead_player(EntityManager_t* ent_manager);
Entity_t* create_player_finish(EntityManager_t* ent_manager);
bool init_item_creation(Assets_t* assets);

View File

@ -51,6 +51,8 @@ static void level_scene_render_func(Scene_t* scene)
print_mempool_stats(buffer);
DrawText(buffer, gui_x, 150, 12, BLACK);
sprintf(buffer, "Chests: %u / %u", data->coins.current, data->coins.total);
DrawText(buffer, gui_x, data->game_rec.y + data->game_rec.height, 24, BLACK);
EndTextureMode();
}
@ -174,8 +176,38 @@ static void render_regular_game_scene(Scene_t* scene)
}
}
sc_map_foreach_value(&scene->ent_manager.entities_map[LEVEL_END_TAG], p_ent)
{
// There is only a few exits, can may be get away without culling
CSprite_t* p_cspr = get_component(p_ent, CSPRITE_T);
if (p_cspr != NULL)
{
const SpriteRenderInfo_t spr = p_cspr->sprites[p_cspr->current_idx];
if (spr.sprite != NULL)
{
Vector2 pos = p_ent->position;
pos = Vector2Subtract(
pos,
get_anchor_offset(spr.sprite->frame_size, spr.src_anchor, p_cspr->flip_x)
);
Vector2 offset = spr.offset;
if (p_cspr->flip_x) offset.x *= -1;
pos = Vector2Add(pos, offset);
draw_sprite(spr.sprite, (data->coins.current < data->coins.total) ? 0 : 1, pos, 0.0f, p_cspr->flip_x);
}
}
else
{
DrawCircleV(p_ent->position, tilemap.tile_size >> 1, (data->coins.current < data->coins.total)? RED : GREEN);
}
}
sc_map_foreach_value(&scene->ent_manager.entities, p_ent)
{
if (p_ent->m_tag == LEVEL_END_TAG) continue;
CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
// Entity culling
@ -202,11 +234,11 @@ static void render_regular_game_scene(Scene_t* scene)
pos,
get_anchor_offset(p_bbox->size, spr.dest_anchor, p_cspr->flip_x)
);
pos = Vector2Subtract(
pos,
get_anchor_offset(spr.sprite->frame_size, spr.src_anchor, p_cspr->flip_x)
);
}
pos = Vector2Subtract(
pos,
get_anchor_offset(spr.sprite->frame_size, spr.src_anchor, p_cspr->flip_x)
);
Vector2 offset = spr.offset;
if (p_cspr->flip_x) offset.x *= -1;
@ -374,14 +406,14 @@ static void render_regular_game_scene(Scene_t* scene)
}
sc_map_foreach_value(&scene->ent_manager.entities_map[DYNMEM_ENT_TAG], p_ent)
{
CWaterRunner_t* p_runner = get_component(p_ent, CWATERRUNNER_T);
//sc_map_foreach_value(&scene->ent_manager.entities_map[DYNMEM_ENT_TAG], p_ent)
//{
// CWaterRunner_t* p_runner = get_component(p_ent, CWATERRUNNER_T);
unsigned int x = ((p_runner->current_tile) % tilemap.width) * tilemap.tile_size;
unsigned int y = ((p_runner->current_tile) / tilemap.width) * tilemap.tile_size;
DrawCircle(x+16, y+16, 8, ColorAlpha(BLUE, 0.6));
}
// unsigned int x = ((p_runner->current_tile) % tilemap.width) * tilemap.tile_size;
// unsigned int y = ((p_runner->current_tile) / tilemap.width) * tilemap.tile_size;
// DrawCircle(x+16, y+16, 8, ColorAlpha(BLUE, 0.6));
//}
draw_particle_system(&scene->part_sys);
// Draw water tile
@ -425,8 +457,17 @@ static void at_level_start(Scene_t* scene)
static void at_level_complete(Scene_t* scene)
{
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
do_action(scene, ACTION_NEXTLEVEL, true);
data->sm.state = LEVEL_STATE_STARTING;
data->sm.fractional += scene->delta_time;
if (data->sm.fractional > 1.0f)
{
data->sm.fractional -= 1.0f;
data->sm.counter++;
}
if (data->sm.counter >= 1)
{
do_action(scene, ACTION_NEXTLEVEL, false);
data->sm.state = LEVEL_STATE_STARTING;
}
}
void init_game_scene(LevelScene_t* scene)

View File

@ -2017,6 +2017,16 @@ void level_end_detection_system(Scene_t* scene)
)
)
{
Entity_t* ent = create_player_finish(&scene->ent_manager);
if (ent != NULL)
{
ent->position = p_flag->position;
ent->position.y += tilemap.tile_size >> 1;
CSprite_t* p_cspr = get_component(p_other_ent, CSPRITE_T);
CSprite_t* new_cspr = get_component(ent, CSPRITE_T);
new_cspr->flip_x = p_cspr->flip_x;
}
destroy_entity(scene, &lvl_scene->data.tilemap, p_other_ent);
change_level_state(&lvl_scene->data, LEVEL_STATE_COMPLETE);

View File

@ -2,7 +2,7 @@
#include "constants.h"
#include "raymath.h"
static SpriteRenderInfo_t item_sprite_map[20] = {0};
static SpriteRenderInfo_t item_sprite_map[21] = {0};
bool init_item_creation(Assets_t* assets)
{
@ -29,6 +29,10 @@ bool init_item_creation(Assets_t* assets)
item_sprite_map[17].offset = (Vector2){-12, -12};
item_sprite_map[18].sprite = get_sprite(assets, "chest");
item_sprite_map[19].sprite = get_sprite(assets, "boulder");
item_sprite_map[20].sprite = get_sprite(assets, "exit");
item_sprite_map[20].src_anchor = AP_BOT_CENTER;
item_sprite_map[20].src_anchor = AP_BOT_CENTER;
item_sprite_map[20].offset = (Vector2){0, TILE_SIZE >> 1};
return true;
}
@ -256,6 +260,10 @@ Entity_t* create_level_end(EntityManager_t* ent_manager)
Entity_t* p_flag = add_entity(ent_manager, LEVEL_END_TAG);
if (p_flag == NULL) return NULL;
CSprite_t* p_cspr = add_component(p_flag, CSPRITE_T);
p_cspr->sprites = item_sprite_map;
p_cspr->current_idx = 20;
add_component(p_flag, CTILECOORD_COMP_T);
return p_flag;
}

View File

@ -4,7 +4,7 @@
#include <string.h>
#include "raymath.h"
#define N_PLAYER_SPRITES 11
#define N_PLAYER_SPRITES 12
enum PlayerSpriteEnum
{
SPR_PLAYER_STAND = 0,
@ -18,6 +18,7 @@ enum PlayerSpriteEnum
SPR_PLAYER_USWIM,
SPR_PLAYER_DSWIM,
SPR_PLAYER_DEAD,
SPR_PLAYER_ENTER,
};
static SpriteRenderInfo_t player_sprite_map[N_PLAYER_SPRITES] = {0};
@ -136,6 +137,32 @@ Entity_t* create_dead_player(EntityManager_t* ent_manager)
return p_ent;
}
static unsigned int player_finish_transition_func(Entity_t* ent)
{
CSprite_t* p_spr = get_component(ent, CSPRITE_T);
// Due to index-from-0
if (p_spr->current_frame == p_spr->sprites[p_spr->current_idx].sprite->frame_count - 1)
{
p_spr->pause = true;
}
return p_spr->current_idx;
}
Entity_t* create_player_finish(EntityManager_t* ent_manager)
{
Entity_t* p_ent = add_entity(ent_manager, NO_ENT_TAG);
if (p_ent == NULL) return NULL;
CSprite_t* p_cspr = add_component(p_ent, CSPRITE_T);
p_cspr->sprites = player_sprite_map;
p_cspr->current_idx = SPR_PLAYER_ENTER;
p_cspr->transition_func = &player_finish_transition_func;
add_component(p_ent, CTILECOORD_COMP_T);
return p_ent;
}
static AnchorPoint_t parse_anchor_symbol(const char symbol[2])
{
if (symbol[0] == 't')

View File

@ -65,6 +65,8 @@ bool load_level_tilemap(LevelScene_t* scene, unsigned int level_num)
scene->data.tilemap.width = lvl_map.width;
scene->data.tilemap.height = lvl_map.height;
scene->data.tilemap.n_tiles = n_tiles;
scene->data.coins.current = 0;
scene->data.coins.total = lvl_map.n_chests;
clear_entity_manager(&scene->scene.ent_manager);
@ -158,6 +160,16 @@ bool load_level_tilemap(LevelScene_t* scene, unsigned int level_num)
p_ctransform->active = true;
}
break;
case 24:
{
Entity_t* ent = create_level_end(&scene->scene.ent_manager);
if (ent != NULL)
{
ent->position.x = (i % scene->data.tilemap.width) * scene->data.tilemap.tile_size;
ent->position.y = (i / scene->data.tilemap.width) * scene->data.tilemap.tile_size + (scene->data.tilemap.tile_size >> 1);
}
}
break;
default:
break;
}