Compare commits

...

6 Commits

Author SHA1 Message Date
En Yi 259fa114ca Fix water filling rate 2024-08-13 18:17:52 +08:00
En Yi c3924c862b Adjust player swimming behaviour
Internal Changelog:
- Slightly increase upthrust
- Slightly reduce air time
2024-08-13 18:17:33 +08:00
En Yi 979533092e Update main game render 2024-08-13 15:34:31 +08:00
En Yi 639aed69db Reposition level select UI 2024-08-13 15:33:38 +08:00
En Yi 0e9ba5795c Center menu screen 2024-08-13 15:33:18 +08:00
En Yi 65b04523ce Update game rendering
Internal Changelog:
- Port editor scene rendering improvements
- Make game scene ~640x480 for testing
2024-08-12 16:06:36 +08:00
10 changed files with 160 additions and 82 deletions

5
main.c
View File

@ -63,7 +63,10 @@ int main(void)
level_scene.data.tile_sprites[SPIKES + TILE_90CWROT] = get_sprite(&engine.assets, "l_spikes");
level_scene.data.tile_sprites[SPIKES + TILE_90CCWROT] = get_sprite(&engine.assets, "r_spikes");
level_scene.data.tile_sprites[SPIKES + TILE_180ROT] = get_sprite(&engine.assets, "u_spikes");
LevelPack_t* pack = get_level_pack(&engine.assets, "TestLevels");
Texture2D* tex = get_texture(&engine.assets, "bg_tex");
SetTextureWrap(*tex, TEXTURE_WRAP_REPEAT);
LevelPack_t* pack = get_level_pack(&engine.assets, "DefLevels");
if (pack != NULL)
{
level_scene.data.level_pack = pack;

View File

@ -5,8 +5,10 @@
#define TILE_SIZE 32
#define DEFAULT_MAP_WIDTH 48
#define DEFAULT_MAP_HEIGHT 32
#define VIEWABLE_MAP_WIDTH 32
#define VIEWABLE_MAP_HEIGHT 16
#define VIEWABLE_EDITOR_MAP_WIDTH 32
#define VIEWABLE_EDITOR_MAP_HEIGHT 16
#define VIEWABLE_MAP_WIDTH 25
#define VIEWABLE_MAP_HEIGHT 14
#else
#define TILE_SIZE 16
#define DEFAULT_MAP_WIDTH 64
@ -21,9 +23,9 @@
#define MOVE_ACCEL 1300
#ifndef TILE16_SIZE
#define PLAYER_WIDTH 28
#define PLAYER_WIDTH 22
#define PLAYER_HEIGHT 42
#define PLAYER_C_WIDTH 28
#define PLAYER_C_WIDTH 22
#define PLAYER_C_HEIGHT 26
#else
#define PLAYER_WIDTH 14
@ -39,7 +41,7 @@
#define GROUND_X_FRICTION 6.1
#define GROUND_Y_FRICTION 1.0
#define ARROW_SPEED 350
#define ARROW_SPEED 400
#define MAX_WATER_LEVEL 4
#define WATER_BBOX_STEP (TILE_SIZE / MAX_WATER_LEVEL)

View File

@ -1048,7 +1048,7 @@ void init_sandbox_scene(LevelScene_t* scene)
scene->data.tilemap.tiles = all_tiles;
init_level_scene_data(
&scene->data, MAX_N_TILES, all_tiles,
(Rectangle){25, 25, VIEWABLE_MAP_WIDTH*TILE_SIZE, VIEWABLE_MAP_HEIGHT*TILE_SIZE}
(Rectangle){25, 25, VIEWABLE_EDITOR_MAP_WIDTH*TILE_SIZE, VIEWABLE_EDITOR_MAP_HEIGHT*TILE_SIZE}
);
scene->data.show_grid = true;
scene->data.tile_sprites[ONEWAY_TILE] = get_sprite(&scene->scene.engine->assets, "tl_owp");

View File

@ -9,6 +9,12 @@
#include <stdio.h>
static Tile_t all_tiles[MAX_N_TILES] = {0};
static const uint8_t CONNECTIVITY_TILE_MAPPING[16] = {
0,3,15,14,
1,2,12,13,
7,6,11,10,
4,5,8 ,9 ,
};
#define GAME_LAYER 0
#define CONTROL_LAYER 1
@ -24,10 +30,13 @@ static void level_scene_render_func(Scene_t* scene)
sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_ent)
{
CAirTimer_t* p_air = get_component(p_ent, CAIRTIMER_T);
Vector2 air_pos = {data->game_rec.x + data->game_rec.width - 16, data->game_rec.y + data->game_rec.height - 16};
Sprite_t* spr = get_sprite(&scene->engine->assets, "p_bigbubble");
Vector2 air_pos = {data->game_rec.x + data->game_rec.width - 32, data->game_rec.y + data->game_rec.height - 32};
for (uint8_t i = 0; i < p_air->curr_count; i++)
{
DrawCircleV(air_pos, 16, BLUE);
draw_sprite(spr, 0, air_pos, 0, false);
//DrawCircleV(air_pos, 16, BLUE);
air_pos.x -= 32;
}
}
@ -106,11 +115,11 @@ static void render_regular_game_scene(Scene_t* scene)
TileGrid_t tilemap = data->tilemap;
Entity_t* p_ent;
Vector2 min = GetScreenToWorld2D((Vector2){data->game_rec.x, data->game_rec.y}, data->camera.cam);
Vector2 min = GetScreenToWorld2D((Vector2){0, 0}, data->camera.cam);
Vector2 max = GetScreenToWorld2D(
(Vector2){
data->game_rec.x + data->game_rec.width,
data->game_rec.y + data->game_rec.height
data->game_rec.width,
data->game_rec.height
},
data->camera.cam
);
@ -121,8 +130,17 @@ static void render_regular_game_scene(Scene_t* scene)
max.x = (int)fmin(tilemap.width, max.x + 1);
max.y = (int)fmin(tilemap.height, max.y + 1);
Texture2D* bg = get_texture(&scene->engine->assets, "bg_tex");
BeginTextureMode(scene->layers.render_layers[GAME_LAYER].layer_tex);
ClearBackground(WHITE);
DrawTexturePro(*bg,
//(Rectangle){0,0,64,64},
(Rectangle){min.x,0, data->game_rec.width, data->game_rec.height},
(Rectangle){0,0, data->game_rec.width, data->game_rec.height},
//(Rectangle){0,0,game_rec.width, game_rec.height},
(Vector2){0,0}, 0.0f, WHITE
);
BeginMode2D(data->camera.cam);
for (int tile_y = min.y; tile_y < max.y; tile_y++)
@ -133,61 +151,15 @@ static void render_regular_game_scene(Scene_t* scene)
int x = tile_x * TILE_SIZE;
int y = tile_y * TILE_SIZE;
if (data->tile_sprites[tilemap.tiles[i].tile_type] != NULL)
if (tilemap.tiles[i].tile_type == LADDER)
{
draw_sprite(data->tile_sprites[tilemap.tiles[i].tile_type], 0, (Vector2){x,y}, 0.0f, false);
}
else if (tilemap.tiles[i].tile_type == SOLID_TILE)
{
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, BLACK);
}
else if (tilemap.tiles[i].tile_type == ONEWAY_TILE)
{
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, MAROON);
}
else if (tilemap.tiles[i].tile_type == LADDER)
{
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, ORANGE);
}
else if (tilemap.tiles[i].tile_type == SPIKES)
{
DrawRectangle(
x + tilemap.tiles[i].offset.x, y + tilemap.tiles[i].offset.y,
tilemap.tiles[i].size.x, tilemap.tiles[i].size.y, RED
);
}
if (tilemap.tiles[i].wet)
{
#define SURFACE_THICKNESS 4
int up = i - tilemap.width;
unsigned int bot = i + tilemap.width;
int right = i + 1;
int left = i - 1;
int bot_line = y + TILE_SIZE - tilemap.tiles[i].water_level * WATER_BBOX_STEP - SURFACE_THICKNESS / 2;
if (up >= 0 && tilemap.tiles[up].wet)
if (data->tile_sprites[tilemap.tiles[i].tile_type] != NULL)
{
DrawLineEx((Vector2){x + TILE_SIZE / 2, y}, (Vector2){x + TILE_SIZE / 2, y + TILE_SIZE - tilemap.tiles[i].water_level * WATER_BBOX_STEP}, SURFACE_THICKNESS, ColorAlpha(BLUE, 0.7));
draw_sprite(data->tile_sprites[tilemap.tiles[i].tile_type], 0, (Vector2){x,y}, 0.0f, false);
}
if (
bot <= tilemap.n_tiles
&& tilemap.tiles[i].water_level == 0
)
else
{
if (i % tilemap.width != 0 && tilemap.tiles[left].wet && (tilemap.tiles[bot].solid == SOLID || tilemap.tiles[bot-1].solid == SOLID))
{
DrawLineEx((Vector2){x, bot_line}, (Vector2){x + TILE_SIZE / 2, bot_line}, SURFACE_THICKNESS, ColorAlpha(BLUE, 0.7));
}
if (right % tilemap.width != 0 && tilemap.tiles[right].wet && (tilemap.tiles[bot].solid == SOLID || tilemap.tiles[bot+1].solid == SOLID))
{
DrawLineEx((Vector2){x + TILE_SIZE / 2, bot_line}, (Vector2){x + TILE_SIZE, bot_line}, SURFACE_THICKNESS, ColorAlpha(BLUE, 0.7));
}
}
if (tilemap.tiles[i].max_water_level < MAX_WATER_LEVEL)
{
DrawRectangleLinesEx((Rectangle){x, y, TILE_SIZE, TILE_SIZE}, 2.0, ColorAlpha(BLUE, 0.5));
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, ORANGE);
}
}
}
@ -319,6 +291,79 @@ static void render_regular_game_scene(Scene_t* scene)
}
}
for (int tile_y = min.y; tile_y < max.y; tile_y++)
{
for (int tile_x = min.x; tile_x < max.x; tile_x++)
{
int i = tile_x + tile_y * tilemap.width;
int x = tile_x * TILE_SIZE;
int y = tile_y * TILE_SIZE;
if (tilemap.tiles[i].tile_type != LADDER)
{
uint8_t tile_sprite_idx = tilemap.tiles[i].tile_type + tilemap.tiles[i].rotation;
if (data->tile_sprites[tile_sprite_idx] != NULL)
{
draw_sprite(data->tile_sprites[tile_sprite_idx], 0, (Vector2){x,y}, 0.0f, false);
}
else if (tilemap.tiles[i].tile_type == SOLID_TILE)
{
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, BLACK);
draw_sprite(
data->solid_tile_sprites,
CONNECTIVITY_TILE_MAPPING[tilemap.tiles[i].connectivity],
(Vector2){x,y}, 0.0f, false
);
}
else if (tilemap.tiles[i].tile_type == ONEWAY_TILE)
{
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, MAROON);
}
else if (tilemap.tiles[i].tile_type == SPIKES)
{
DrawRectangle(
x + tilemap.tiles[i].offset.x, y + tilemap.tiles[i].offset.y,
tilemap.tiles[i].size.x, tilemap.tiles[i].size.y, RED
);
}
}
if (tilemap.tiles[i].wet)
{
#define SURFACE_THICKNESS 4
int up = i - tilemap.width;
unsigned int bot = i + tilemap.width;
int right = i + 1;
int left = i - 1;
int bot_line = y + TILE_SIZE - tilemap.tiles[i].water_level * WATER_BBOX_STEP - SURFACE_THICKNESS / 2;
if (up >= 0 && tilemap.tiles[up].wet)
{
DrawLineEx((Vector2){x + TILE_SIZE / 2, y}, (Vector2){x + TILE_SIZE / 2, y + TILE_SIZE - tilemap.tiles[i].water_level * WATER_BBOX_STEP}, SURFACE_THICKNESS, ColorAlpha(BLUE, 0.7));
}
if (
bot <= tilemap.n_tiles
&& tilemap.tiles[i].water_level == 0
)
{
if (i % tilemap.width != 0 && tilemap.tiles[left].wet && (tilemap.tiles[bot].solid == SOLID || tilemap.tiles[bot-1].solid == SOLID))
{
DrawLineEx((Vector2){x, bot_line}, (Vector2){x + TILE_SIZE / 2, bot_line}, SURFACE_THICKNESS, ColorAlpha(BLUE, 0.7));
}
if (right % tilemap.width != 0 && tilemap.tiles[right].wet && (tilemap.tiles[bot].solid == SOLID || tilemap.tiles[bot+1].solid == SOLID))
{
DrawLineEx((Vector2){x + TILE_SIZE / 2, bot_line}, (Vector2){x + TILE_SIZE, bot_line}, SURFACE_THICKNESS, ColorAlpha(BLUE, 0.7));
}
}
if (tilemap.tiles[i].max_water_level < MAX_WATER_LEVEL)
{
DrawRectangleLinesEx((Rectangle){x, y, TILE_SIZE, TILE_SIZE}, 2.0, ColorAlpha(BLUE, 0.5));
}
}
}
}
sc_map_foreach_value(&scene->ent_manager.entities_map[DYNMEM_ENT_TAG], p_ent)
{
@ -351,13 +396,13 @@ static void render_regular_game_scene(Scene_t* scene)
}
}
// Draw Border
DrawLine(0, 0, 0, tilemap.height * tilemap.tile_size, BLACK);
DrawLine(0, 0, tilemap.width * TILE_SIZE, 0, BLACK);
int val = (tilemap.width) * tilemap.tile_size;
DrawLine(val, 0, val, tilemap.height * tilemap.tile_size, BLACK);
val = (tilemap.height) * tilemap.tile_size;
DrawLine(0, val, tilemap.width * TILE_SIZE, val, BLACK);
//// Draw Border (remove later)
//DrawLine(0, 0, 0, tilemap.height * tilemap.tile_size, BLACK);
//DrawLine(0, 0, tilemap.width * TILE_SIZE, 0, BLACK);
//int val = (tilemap.width) * tilemap.tile_size;
//DrawLine(val, 0, val, tilemap.height * tilemap.tile_size, BLACK);
//val = (tilemap.height) * tilemap.tile_size;
//DrawLine(0, val, tilemap.width * TILE_SIZE, val, BLACK);
EndMode2D();
EndTextureMode();
}
@ -373,7 +418,11 @@ void init_game_scene(LevelScene_t* scene)
scene->data.tilemap.tiles = all_tiles;
init_level_scene_data(
&scene->data, MAX_N_TILES, all_tiles,
(Rectangle){25, 25, 32*TILE_SIZE, 18*TILE_SIZE}
(Rectangle){
(scene->scene.engine->intended_window_size.x- VIEWABLE_MAP_WIDTH*TILE_SIZE) / 2.0f,
(scene->scene.engine->intended_window_size.y- VIEWABLE_MAP_HEIGHT*TILE_SIZE) / 2.0f,
VIEWABLE_MAP_WIDTH*TILE_SIZE, VIEWABLE_MAP_HEIGHT*TILE_SIZE
}
);
scene->scene.bg_colour = LIGHTGRAY;
@ -394,6 +443,9 @@ void init_game_scene(LevelScene_t* scene)
create_player(&scene->scene.ent_manager);
update_entity_manager(&scene->scene.ent_manager);
// Set up textures
scene->data.solid_tile_sprites = get_sprite(&scene->scene.engine->assets, "stile0");
sc_array_add(&scene->scene.systems, &update_tilemap_system);
sc_array_add(&scene->scene.systems, &player_movement_input_system);
sc_array_add(&scene->scene.systems, &player_bbox_update_system);

View File

@ -11,7 +11,7 @@ void floating_particle_system_update(Particle_t* part, void* user_data, float de
bool check_in_water(const ParticleEmitter_t* emitter, float delta_time);
static const Vector2 GRAVITY = {0, GRAV_ACCEL};
static const Vector2 UPTHRUST = {0, -GRAV_ACCEL * 1.1};
static const Vector2 UPTHRUST = {0, -GRAV_ACCEL * 1.15};
static inline unsigned int get_tile_idx(int x, int y, TileGrid_t gridmap)
{

View File

@ -90,6 +90,8 @@ static void level_select_do_action(Scene_t* scene, ActionType_t action, bool pre
}
}
#define START_X 300
#define START_Y 100
#define FONT_SIZE 30
#define TEXT_PADDING 3
#define DISPLAY_AREA_HEIGHT 400
@ -99,7 +101,7 @@ void init_level_select_scene(LevelSelectScene_t* scene)
init_scene(&scene->scene, &level_select_do_action);
add_scene_layer(
&scene->scene, 400, 800,
(Rectangle){0, 0, 400, 800}
(Rectangle){START_X, START_Y, 400, 800}
);
vert_scrollarea_init(&scene->data.scroll_area, (Rectangle){50, 100, 150, DISPLAY_AREA_HEIGHT - 100}, (Vector2){150, SCROLL_TOTAL_HEIGHT});
vert_scrollarea_set_item_dims(&scene->data.scroll_area, FONT_SIZE, TEXT_PADDING);

View File

@ -3,17 +3,26 @@
#include "raymath.h"
#include <stdio.h>
#define START_X 300
static void menu_scene_render_func(Scene_t* scene)
{
MenuSceneData_t* data = &(CONTAINER_OF(scene, MenuScene_t, scene)->data);
Texture2D* bg = get_texture(&scene->engine->assets, "title_tex");
BeginTextureMode(scene->layers.render_layers[0].layer_tex);
ClearBackground(RAYWHITE);
DrawText("This is a game", 25, 220, 12, BLACK);
DrawText("Bunny's Spelunking Adventure", START_X, 100, 32, BLACK);
UI_button(data->buttons, "Start");
UI_button(data->buttons + 1, "Sandbox");
UI_button(data->buttons + 2, "Continue");
UI_button(data->buttons + 3, "Exit");
DrawTexturePro(*bg,
(Rectangle){0, 0, bg->width, bg->height},
(Rectangle){START_X + 200, 120, bg->width, bg->height},
(Vector2){0,0}, 0.0f, WHITE
);
EndTextureMode();
}
@ -139,22 +148,22 @@ void init_menu_scene(MenuScene_t* scene)
sc_array_add(&scene->scene.systems, &menu_scene_render_func);
scene->data.buttons[0] = (UIComp_t) {
.bbox = {25,255,125,30},
.bbox = {START_X,255,125,30},
.state = STATE_NORMAL,
.alpha = 1.0
};
scene->data.buttons[1] = (UIComp_t) {
.bbox = {25,300,125,30},
.bbox = {START_X,300,125,30},
.state = STATE_NORMAL,
.alpha = 1.0
};
scene->data.buttons[2] = (UIComp_t) {
.bbox = {25,345,125,30},
.bbox = {START_X,345,125,30},
.state = STATE_NORMAL,
.alpha = 1.0
};
scene->data.buttons[3] = (UIComp_t) {
.bbox = {25,390,125,30},
.bbox = {START_X,390,125,30},
.state = STATE_NORMAL,
.alpha = 1.0
};

View File

@ -104,7 +104,7 @@ Entity_t* create_player(EntityManager_t* ent_manager)
CAirTimer_t* p_air = add_component(p_ent, CAIRTIMER_T);
p_air->max_count = 10;
p_air->curr_count = 10;
p_air->max_ftimer = 1.0f;
p_air->max_ftimer = 0.9f;
p_air->decay_rate = 1.0f;
CSprite_t* p_cspr = add_component(p_ent, CSPRITE_T);

View File

@ -75,10 +75,11 @@ bool load_level_tilemap(LevelScene_t* scene, unsigned int level_num)
if (lvl_map.tiles[i].tile_type == 1)
{
change_a_tile(&scene->data.tilemap, i, SOLID_TILE);
change_a_tile(&scene->data.tilemap, i, SOLID_TILE);
}
scene->data.tilemap.tiles[i].water_level = lvl_map.tiles[i].water;
scene->data.tilemap.tiles[i].water_level = lvl_map.tiles[i].water;
scene->data.tilemap.tiles[i].wet = scene->data.tilemap.tiles[i].water_level > 0;
}
// Two pass
for (size_t i = 0; i < scene->data.tilemap.n_tiles;i++)
@ -139,6 +140,15 @@ bool load_level_tilemap(LevelScene_t* scene, unsigned int level_num)
ent->spawn_pos = ent->position;
}
break;
case 23:
{
Entity_t* ent = create_chest(&scene->scene.ent_manager);
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;
CTransform_t* p_ctransform = get_component(ent, CTRANSFORM_COMP_T);
p_ctransform->active = true;
}
break;
default:
break;
}

View File

@ -293,7 +293,6 @@ void update_water_runner_system(Scene_t* scene)
p_crunner->fractional += scene->delta_time;
if (p_crunner->fractional < FILL_RATE) break;
p_crunner->fractional -= FILL_RATE;
// Unsigned usage here is okay
unsigned int start_tile =
(p_crunner->current_tile / p_crunner->bfs_tilemap.width) * p_crunner->bfs_tilemap.width;
@ -308,6 +307,7 @@ void update_water_runner_system(Scene_t* scene)
if (curr_tile->water_level < curr_tile->max_water_level)
{
curr_tile->water_level++;
p_crunner->fractional -= FILL_RATE;
}
if (curr_tile->water_level < curr_tile->max_water_level)
{