Compare commits

...

18 Commits

Author SHA1 Message Date
En Yi 0d4089d9ce Tweak scene render function
Delegate BeginDrawing and EndDrawing to individual scenes
2024-05-01 19:56:10 +08:00
En Yi 41e4b34869 Allow changing sound pitch 2024-05-01 17:08:29 +08:00
En Yi 1094e13c0a Fix some emitter positioning 2024-05-01 12:38:53 +08:00
En Yi 54acd365d4 Integrate 'pro' version of sprite drawing 2024-05-01 12:23:31 +08:00
En Yi 2bda67e917 Make player box a little smaller 2024-05-01 11:56:07 +08:00
En Yi 42c4572066 Rework sprite render system
Internal Changelog:
- Add more fields
    - Elapsed is now in sprite component
    - Add rotation fields
- Tweak early exit checks in render functions
2024-05-01 11:55:34 +08:00
En Yi 754d380221 Integrate mouse action into input process 2024-04-25 21:46:53 +08:00
En Yi 0fb1fe27de Display time scaling in sandbox 2024-04-24 22:15:52 +08:00
En Yi 204329d2aa Use float for timing in particle system
Also, update the assets_loader due to this
2024-04-24 21:47:58 +08:00
En Yi 6bcccf7412 Fix regression in water air timer 2024-04-24 21:30:34 +08:00
En Yi c76ceba9bf Add delta time into particle system updates
Only update the callbacks to use it
2024-04-24 21:06:57 +08:00
En Yi 0a3f56f730 Fix out-of-bound access in water check function 2024-04-24 20:58:54 +08:00
En Yi 0a6e7b4ddc Add delta time handling
Internal Changelog:
- Major change: all engine that does counting uses delta time instead of
  frame counting
- Animation runs at 24 FPS
- Water fill is at a constant rate as well
- Particle update will need to be given delta time as well.
- Particle system is not updated to use float, so no delta time handling
  for the system in this commit
2024-04-23 22:44:52 +08:00
En Yi 55ba03f2d6 Add asset enums & texture addition from Images
Enums is to reduce hardcoded indices

Texture can now be added from Images
2024-04-22 23:29:09 +08:00
En Yi 3961366ac4 Add function to get number of free entities 2024-04-22 22:52:59 +08:00
En Yi 6f3f391d8a Rework the offset collision checking
Change the function to check for collision at the specified point.
This is much straightforward to use.
The offset point to check must be computed before passing into the
function.
2024-04-22 22:42:32 +08:00
En Yi fec9ac268d Adjust simple collision function signatures
Remove redundant position argument for the straightforward collision
functions, as the entity would have it alread.

The collision offset check function is not as trivial and requires
some review
2024-04-22 22:31:58 +08:00
En Yi a2c061c5e8 Place position field into Entity
Position is so commonly used that placing it into Entity from the
CTransform components reduces the reference to CTransform.

Void Particle proved that it made development much easier.
2024-04-22 22:15:21 +08:00
31 changed files with 655 additions and 486 deletions

View File

@ -32,6 +32,7 @@ int main(void)
Font* fnt = get_font(&assets, "testfont");
int current_frame = 0;
int elapsed = 0;
while(!WindowShouldClose())
{
if (IsKeyReleased(KEY_C))
@ -49,12 +50,12 @@ int main(void)
EndDrawing();
// Update the animated Sprite
spr2->elapsed++;
if (spr2->elapsed == spr2->speed)
elapsed++;
if (elapsed == spr2->speed)
{
current_frame++;
current_frame %= spr2->frame_count;
spr2->elapsed = 0;
elapsed = 0;
}
}
term_assets(&assets);

View File

@ -45,13 +45,12 @@ typedef struct _CBBox_t {
typedef struct _CTransform_t {
Vector2 prev_position;
Vector2 prev_velocity;
Vector2 position;
Vector2 velocity;
Vector2 accel;
Vector2 fric_coeff;
Vector2 shape_factor;
int8_t grav_delay;
int8_t grav_timer;
float grav_delay;
float grav_timer;
MovementMode_t movement_mode;
bool active;
} CTransform_t;
@ -130,16 +129,15 @@ typedef struct _CHurtbox_t {
} CHurtbox_t;
typedef struct _CLifeTimer_t {
uint8_t timer;
uint8_t life_time;
float life_time;
} CLifeTimer_t;
typedef struct _CAirTimer_t {
float max_ftimer;
float curr_ftimer;
float decay_rate;
uint8_t max_count;
uint8_t curr_count;
uint16_t max_ftimer;
uint16_t curr_ftimer;
uint16_t decay_rate;
} CAirTimer_t;
typedef struct _BFSTile {
@ -178,6 +176,7 @@ typedef struct _CWaterRunner {
uint8_t movement_delay;
int8_t movement_speed;
int16_t counter;
float fractional;
}CWaterRunner_t;
// Credits to bedroomcoders.co.uk for this
@ -187,7 +186,6 @@ typedef struct Sprite {
Vector2 origin;
Vector2 anchor;
int frame_count;
int elapsed;
int speed;
char* name;
} Sprite_t;
@ -207,6 +205,12 @@ typedef struct _CSprite_t {
bool flip_y;
bool pause;
int current_frame;
float fractional;
float rotation; // Degree
float rotation_speed; // Degree / s
int elapsed;
Vector2 offset;
Color colour;
} CSprite_t;
typedef struct _CMoveable_t {
@ -233,6 +237,7 @@ static inline void set_bbox(CBBox_t* p_bbox, unsigned int x, unsigned int y)
struct Entity {
Vector2 spawn_pos;
Vector2 position;
unsigned long m_id;
unsigned int m_tag;
unsigned long components[N_COMPONENTS];

View File

@ -18,5 +18,8 @@ typedef enum ActionType
ACTION_PREVLEVEL,
ACTION_TOGGLE_GRID,
ACTION_SET_SPAWNPOINT,
ACTION_TOGGLE_TIMESLOW,
ACTION_SPAWN_TILE,
ACTION_REMOVE_TILE,
}ActionType_t;
#endif // __ACTIONS_H

View File

@ -8,7 +8,7 @@
#include "zstd.h"
#include <stdio.h>
uint8_t n_loaded[6] = {0};
uint8_t n_loaded[N_ASSETS_TYPE] = {0};
// Hard limit number of
typedef struct TextureData
@ -70,7 +70,7 @@ static void unload_level_pack(LevelPack_t pack)
// Maybe need a circular buffer??
Texture2D* add_texture(Assets_t* assets, const char* name, const char* path)
{
uint8_t tex_idx = n_loaded[0];
uint8_t tex_idx = n_loaded[AST_TEXTURE];
assert(tex_idx < MAX_TEXTURES);
Texture2D tex = LoadTexture(path);
if (tex.width == 0 || tex.height == 0) return NULL;
@ -78,13 +78,13 @@ Texture2D* add_texture(Assets_t* assets, const char* name, const char* path)
textures[tex_idx].texture = tex;
strncpy(textures[tex_idx].name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_textures, textures[tex_idx].name, tex_idx);
n_loaded[0]++;
n_loaded[AST_TEXTURE]++;
return &textures[tex_idx].texture;
}
Texture2D* add_texture_rres(Assets_t* assets, const char* name, const char* filename, const RresFileInfo_t* rres_file)
{
uint8_t tex_idx = n_loaded[0];
uint8_t tex_idx = n_loaded[AST_TEXTURE];
assert(tex_idx < MAX_TEXTURES);
int res_id = rresGetResourceId(rres_file->dir, filename);
@ -102,7 +102,7 @@ Texture2D* add_texture_rres(Assets_t* assets, const char* name, const char* file
textures[tex_idx].texture = tex;
strncpy(textures[tex_idx].name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_textures, textures[tex_idx].name, tex_idx);
n_loaded[0]++;
n_loaded[AST_TEXTURE]++;
out_tex = &textures[tex_idx].texture;
}
rresUnloadResourceChunk(chunk);
@ -111,7 +111,7 @@ Texture2D* add_texture_rres(Assets_t* assets, const char* name, const char* file
Sound* add_sound_rres(Assets_t* assets, const char* name, const char* filename, const RresFileInfo_t* rres_file)
{
uint8_t snd_idx = n_loaded[2];
uint8_t snd_idx = n_loaded[AST_SOUND];
assert(snd_idx < MAX_SOUNDS);
int res_id = rresGetResourceId(rres_file->dir, filename);
@ -128,55 +128,69 @@ Sound* add_sound_rres(Assets_t* assets, const char* name, const char* filename,
sfx[snd_idx].sound = snd;
strncpy(sfx[snd_idx].name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_sounds, sfx[snd_idx].name, snd_idx);
n_loaded[2]++;
n_loaded[AST_SOUND]++;
out_snd = &sfx[snd_idx].sound;
}
rresUnloadResourceChunk(chunk);
return out_snd;
}
Texture2D* add_texture_from_img(Assets_t* assets, const char* name, Image img)
{
uint8_t tex_idx = n_loaded[AST_TEXTURE];
assert(tex_idx < MAX_TEXTURES);
Texture2D tex = LoadTextureFromImage(img);
if (tex.width == 0 || tex.height == 0) return NULL;
textures[tex_idx].texture = tex;
strncpy(textures[tex_idx].name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_textures, textures[tex_idx].name, tex_idx);
n_loaded[AST_TEXTURE]++;
return &textures[tex_idx].texture;
}
Sprite_t* add_sprite(Assets_t* assets, const char* name, Texture2D* texture)
{
uint8_t spr_idx = n_loaded[1];
uint8_t spr_idx = n_loaded[AST_SPRITE];
assert(spr_idx < MAX_SPRITES);
memset(sprites + spr_idx, 0, sizeof(SpriteData_t));
sprites[spr_idx].sprite.texture = texture;
strncpy(sprites[spr_idx].name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_sprites, sprites[spr_idx].name, spr_idx);
n_loaded[1]++;
n_loaded[AST_SPRITE]++;
return &sprites[spr_idx].sprite;
}
Sound* add_sound(Assets_t* assets, const char* name, const char* path)
{
uint8_t snd_idx = n_loaded[2];
uint8_t snd_idx = n_loaded[AST_SOUND];
assert(snd_idx < MAX_SOUNDS);
sfx[snd_idx].sound = LoadSound(path);
strncpy(sfx[snd_idx].name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_sounds, sfx[snd_idx].name, snd_idx);
n_loaded[2]++;
n_loaded[AST_SOUND]++;
return &sfx[snd_idx].sound;
}
Font* add_font(Assets_t* assets, const char* name, const char* path)
{
uint8_t fnt_idx = n_loaded[3];
uint8_t fnt_idx = n_loaded[AST_FONT];
assert(fnt_idx < MAX_FONTS);
fonts[fnt_idx].font = LoadFont(path);
strncpy(fonts[fnt_idx].name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_fonts, fonts[fnt_idx].name, fnt_idx);
n_loaded[3]++;
n_loaded[AST_FONT]++;
return &fonts[fnt_idx].font;
}
EmitterConfig_t* add_emitter_conf(Assets_t* assets, const char* name)
{
uint8_t emitter_idx = n_loaded[5];
uint8_t emitter_idx = n_loaded[AST_EMITTER_CONF];
assert(emitter_idx < MAX_EMITTER_CONF);
memset(emitter_confs + emitter_idx, 0, sizeof(EmitterConfData_t));
strncpy(emitter_confs[emitter_idx].name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_emitter_confs, emitter_confs[emitter_idx].name, emitter_idx);
n_loaded[5]++;
n_loaded[AST_EMITTER_CONF]++;
return &emitter_confs[emitter_idx].conf;
}
@ -185,7 +199,7 @@ LevelPack_t* add_level_pack(Assets_t* assets, const char* name, const char* path
FILE* file = fopen(path, "rb");
if (file == NULL) return NULL;
LevelPackData_t* pack_info = levelpacks + n_loaded[4];
LevelPackData_t* pack_info = levelpacks + n_loaded[AST_LEVELPACK];
fread(&pack_info->pack.n_levels, sizeof(uint32_t), 1, file);
pack_info->pack.levels = calloc(pack_info->pack.n_levels, sizeof(LevelMap_t));
@ -201,10 +215,10 @@ LevelPack_t* add_level_pack(Assets_t* assets, const char* name, const char* path
}
fclose(file);
uint8_t pack_idx = n_loaded[4];
uint8_t pack_idx = n_loaded[AST_LEVELPACK];
strncpy(pack_info->name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_levelpacks, levelpacks[pack_idx].name, pack_idx);
n_loaded[4]++;
n_loaded[AST_LEVELPACK]++;
return &levelpacks[pack_idx].pack;
}
@ -212,7 +226,7 @@ LevelPack_t* add_level_pack(Assets_t* assets, const char* name, const char* path
static LevelPack_t* add_level_pack_zst(Assets_t* assets, const char* name, const uint8_t* zst_buffer, uint32_t len)
{
LevelPackData_t* pack_info = levelpacks + n_loaded[4];
LevelPackData_t* pack_info = levelpacks + n_loaded[AST_LEVELPACK];
size_t read = 0;
ZSTD_inBuffer input = { level_decompressor.in_buffer, read, 0 };
@ -350,10 +364,10 @@ load_end:
}
pack_info->pack.n_levels = lvls;
uint8_t pack_idx = n_loaded[4];
uint8_t pack_idx = n_loaded[AST_LEVELPACK];
strncpy(pack_info->name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_levelpacks, levelpacks[pack_idx].name, pack_idx);
n_loaded[4]++;
n_loaded[AST_LEVELPACK]++;
return &levelpacks[pack_idx].pack;
}
@ -415,19 +429,19 @@ void init_assets(Assets_t* assets)
void free_all_assets(Assets_t* assets)
{
for (uint8_t i = 0; i < n_loaded[0]; ++i)
for (uint8_t i = 0; i < n_loaded[AST_TEXTURE]; ++i)
{
UnloadTexture(textures[i].texture);
}
for (uint8_t i = 0; i < n_loaded[2]; ++i)
for (uint8_t i = 0; i < n_loaded[AST_SOUND]; ++i)
{
UnloadSound(sfx[i].sound);
}
for (uint8_t i = 0; i < n_loaded[3]; ++i)
for (uint8_t i = 0; i < n_loaded[AST_FONT]; ++i)
{
UnloadFont(fonts[i].font);
}
for (uint8_t i = 0; i < n_loaded[4]; ++i)
for (uint8_t i = 0; i < n_loaded[AST_LEVELPACK]; ++i)
{
unload_level_pack(levelpacks[i].pack);
}
@ -516,24 +530,36 @@ LevelPack_t* get_level_pack(Assets_t* assets, const char* name)
void draw_sprite(Sprite_t* spr, int frame_num, Vector2 pos, float rotation, bool flip_x)
{
draw_sprite_pro(
spr, frame_num, pos, rotation, flip_x ? 1: 0,
(Vector2){1, 1}, WHITE
);
}
void draw_sprite_pro(Sprite_t* spr, int frame_num, Vector2 pos, float rotation, uint8_t flip, Vector2 scale, Color colour)
{
if (frame_num >= spr->frame_count) frame_num = spr->frame_count - 1;
if (frame_num < 0) frame_num = 0;
Rectangle rec = {
spr->origin.x + spr->frame_size.x * frame_num,
spr->origin.y,
spr->frame_size.x * (flip_x ? -1:1),
spr->frame_size.y
spr->frame_size.x * ((flip & 1) ? -1 : 1),
spr->frame_size.y * ((flip & 2) ? -1 : 1),
};
//DrawTextureRec(*spr->texture, rec, pos, WHITE);
Rectangle dest = {
.x = pos.x - spr->anchor.x,
.y = pos.y - spr->anchor.y,
.width = spr->frame_size.x,
.height = spr->frame_size.y
.x = pos.x,
.y = pos.y,
.width = spr->frame_size.x * scale.x,
.height = spr->frame_size.y * scale.y
};
Vector2 anchor = spr->anchor;
anchor.x *= scale.x;
anchor.y *= scale.y;
DrawTexturePro(
*spr->texture,
rec,
dest,
spr->anchor,
rotation, WHITE
anchor,
rotation, colour
);
}

View File

@ -5,6 +5,17 @@
#include "raylib.h"
#include "rres.h"
#include "particle_sys.h"
#define N_ASSETS_TYPE 6
typedef enum AssetType
{
AST_TEXTURE = 0,
AST_SPRITE,
AST_SOUND,
AST_FONT,
AST_LEVELPACK,
AST_EMITTER_CONF,
}AssetType_t;
typedef struct Assets
{
@ -49,6 +60,7 @@ void free_all_assets(Assets_t* assets);
void term_assets(Assets_t* assets);
Texture2D* add_texture(Assets_t* assets, const char* name, const char* path);
Texture2D* add_texture_from_img(Assets_t* assets, const char* name, Image img);
Sound* add_sound(Assets_t * assets, const char* name, const char* path);
Font* add_font(Assets_t* assets, const char* name, const char* path);
LevelPack_t* add_level_pack(Assets_t* assets, const char* name, const char* path);
@ -70,6 +82,7 @@ Font* get_font(Assets_t* assets, const char* name);
LevelPack_t* get_level_pack(Assets_t* assets, const char* name);
void draw_sprite(Sprite_t* spr, int frame_num, Vector2 pos, float rotation, bool flip_x);
void draw_sprite_pro(Sprite_t* spr, int frame_num, Vector2 pos, float rotation, uint8_t flip, Vector2 scale, Color colour);
typedef struct SFX
{

View File

@ -65,9 +65,8 @@ uint8_t check_collision(const CollideEntity_t* ent, TileGrid_t* grid, bool check
{
if (ent->p_ent->m_id == p_other_ent->m_id) continue;
if (!ent->p_ent->m_alive) continue;
CTransform_t *p_ctransform = get_component(p_other_ent, CTRANSFORM_COMP_T);
CBBox_t *p_bbox = get_component(p_other_ent, CBBOX_COMP_T);
if (p_bbox == NULL || p_ctransform == NULL) continue;
if (p_bbox == NULL) continue;
//if (p_bbox->solid && !p_bbox->fragile)
if (p_bbox->solid)
{
@ -75,7 +74,7 @@ uint8_t check_collision(const CollideEntity_t* ent, TileGrid_t* grid, bool check
find_AABB_overlap(
(Vector2){ent->bbox.x, ent->bbox.y},
(Vector2){ent->bbox.width, ent->bbox.height},
p_ctransform->position, p_bbox->size, &overlap
p_other_ent->position, p_bbox->size, &overlap
)
)
{
@ -134,14 +133,13 @@ uint8_t check_collision_line(const CollideEntity_t* ent, TileGrid_t* grid, bool
{
if (ent->p_ent->m_id == p_other_ent->m_id) continue;
if (!ent->p_ent->m_alive) continue;
CTransform_t *p_ctransform = get_component(p_other_ent, CTRANSFORM_COMP_T);
CBBox_t *p_bbox = get_component(p_other_ent, CBBOX_COMP_T);
if (p_bbox == NULL || p_ctransform == NULL) continue;
if (p_bbox == NULL) continue;
if (p_bbox->solid)
{
Rectangle box = {
.x = p_ctransform->position.x,
.y = p_ctransform->position.y,
.x = p_other_ent->position.x,
.y = p_other_ent->position.y,
.width = p_bbox->size.x,
.height = p_bbox->size.y,
};
@ -157,27 +155,26 @@ uint8_t check_collision_line(const CollideEntity_t* ent, TileGrid_t* grid, bool
}
// TODO: This should be a point collision check, not an AABB check
uint8_t check_collision_offset(Entity_t* p_ent, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, Vector2 offset)
uint8_t check_collision_at(Entity_t* p_ent, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid)
{
Vector2 new_pos = Vector2Add(pos, offset);
CollideEntity_t ent = {
.p_ent = p_ent,
.bbox = (Rectangle){new_pos.x, new_pos.y, bbox_sz.x, bbox_sz.y},
.bbox = (Rectangle){pos.x, pos.y, bbox_sz.x, bbox_sz.y},
.prev_bbox = (Rectangle){pos.x, pos.y, bbox_sz.x, bbox_sz.y},
.area = (TileArea_t){
.tile_x1 = (new_pos.x) / grid->tile_size,
.tile_y1 = (new_pos.y) / grid->tile_size,
.tile_x2 = (new_pos.x + bbox_sz.x - 1) / grid->tile_size,
.tile_y2 = (new_pos.y + bbox_sz.y - 1) / grid->tile_size
.tile_x1 = (pos.x) / grid->tile_size,
.tile_y1 = (pos.y) / grid->tile_size,
.tile_x2 = (pos.x + bbox_sz.x - 1) / grid->tile_size,
.tile_y2 = (pos.y + bbox_sz.y - 1) / grid->tile_size
}
};
return check_collision(&ent, grid, false);
}
bool check_on_ground(Entity_t* p_ent, Vector2 pos, Vector2 prev_pos, Vector2 bbox_sz, TileGrid_t* grid)
bool check_on_ground(Entity_t* p_ent, Vector2 prev_pos, Vector2 bbox_sz, TileGrid_t* grid)
{
Vector2 new_pos = Vector2Add(pos, (Vector2){0, 1});
Vector2 new_pos = Vector2Add(p_ent->position, (Vector2){0, 1});
CollideEntity_t ent = {
.p_ent = p_ent,
.bbox = (Rectangle){new_pos.x, new_pos.y + bbox_sz.y, bbox_sz.x, 1},
@ -195,12 +192,13 @@ bool check_on_ground(Entity_t* p_ent, Vector2 pos, Vector2 prev_pos, Vector2 bbo
uint8_t check_bbox_edges(
TileGrid_t* tilemap,
Entity_t* p_ent, Vector2 pos, Vector2 bbox,
Entity_t* p_ent, Vector2 bbox,
bool ignore_fragile
)
{
uint8_t detected = 0;
Vector2 pos = p_ent->position;
// Too lazy to adjust the tile area to check, so just make a big one
CollideEntity_t ent =
{

View File

@ -59,7 +59,7 @@ typedef struct CollideEntity {
void remove_entity_from_tilemap(EntityManager_t *p_manager, TileGrid_t* tilemap, Entity_t* p_ent);
uint8_t check_collision(const CollideEntity_t* ent, TileGrid_t* grid, bool check_oneway);
uint8_t check_collision_line(const CollideEntity_t* ent, TileGrid_t* grid, bool check_oneway);
uint8_t check_collision_offset(Entity_t* p_ent, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, Vector2 offset);
bool check_on_ground(Entity_t* p_ent, Vector2 pos, Vector2 prev_pos, Vector2 bbox_sz, TileGrid_t* grid);
uint8_t check_bbox_edges(TileGrid_t* tilemap, Entity_t* p_ent, Vector2 pos, Vector2 bbox, bool ignore_fragile);
uint8_t check_collision_at(Entity_t* p_ent, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid);
bool check_on_ground(Entity_t* p_ent, Vector2 prev_pos, Vector2 bbox_sz, TileGrid_t* grid);
uint8_t check_bbox_edges(TileGrid_t* tilemap, Entity_t* p_ent, Vector2 bbox, bool ignore_fragile);
#endif // __COLLISION_FUNCS_H

View File

@ -21,6 +21,9 @@ void deinit_engine(GameEngine_t* engine)
void process_inputs(GameEngine_t* engine, Scene_t* scene)
{
Vector2 raw_mouse_pos = GetMousePosition();
scene->mouse_pos = raw_mouse_pos;
unsigned int sz = sc_queue_size(&engine->key_buffer);
// Process any existing pressed key
for (size_t i = 0; i < sz; i++)
@ -48,6 +51,33 @@ void process_inputs(GameEngine_t* engine, Scene_t* scene)
do_action(scene, action, true);
sc_queue_add_last(&engine->key_buffer, button);
}
// Mouse button handling
ActionType_t action = sc_map_get_64(&scene->action_map, MOUSE_BUTTON_RIGHT);
if (sc_map_found(&scene->action_map))
{
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT))
{
do_action(scene, action, true);
}
else if (IsMouseButtonReleased(MOUSE_BUTTON_RIGHT))
{
do_action(scene, action, false);
}
}
action = sc_map_get_64(&scene->action_map, MOUSE_BUTTON_LEFT);
if (sc_map_found(&scene->action_map))
{
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT))
{
do_action(scene, action, true);
}
else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
{
do_action(scene, action, false);
}
}
}
void change_scene(GameEngine_t* engine, unsigned int idx)
@ -68,30 +98,52 @@ bool load_sfx(GameEngine_t* engine, const char* snd_name, uint32_t tag_idx)
return true;
}
void play_sfx(GameEngine_t* engine, unsigned int tag_idx)
void play_sfx_pitched(GameEngine_t* engine, unsigned int tag_idx, float pitch)
{
if (tag_idx >= engine->sfx_list.n_sfx) return;
SFX_t* sfx = engine->sfx_list.sfx + tag_idx;
if (sfx->plays == 0 && sfx->snd != NULL)
if (sfx->snd != NULL)
{
PlaySound(*sfx->snd);
sfx->plays++;
engine->sfx_list.sfx_queue[engine->sfx_list.played_sfx++] = tag_idx;
SetSoundPitch(*sfx->snd, pitch);
//if (sfx->snd != NULL)
{
PlaySound(*sfx->snd);
sfx->plays++;
}
//SetSoundPitch(*sfx->snd, 0.0f);
}
}
void play_sfx(GameEngine_t* engine, unsigned int tag_idx)
{
play_sfx_pitched(engine, tag_idx, 0.0f);
}
void stop_sfx(GameEngine_t* engine, unsigned int tag_idx)
{
if (tag_idx >= engine->sfx_list.n_sfx) return;
SFX_t* sfx = engine->sfx_list.sfx + tag_idx;
if (sfx->snd != NULL && IsSoundPlaying(*sfx->snd))
{
StopSound(*sfx->snd);
//sfx->plays--;
}
}
void update_sfx_list(GameEngine_t* engine)
{
for (uint32_t i = 0; i< engine->sfx_list.played_sfx; ++i)
for (uint32_t i = 0; i< engine->sfx_list.n_sfx; ++i)
{
uint32_t tag_idx = engine->sfx_list.sfx_queue[i];
engine->sfx_list.sfx[tag_idx].plays = 0;
if (!IsSoundPlaying(*engine->sfx_list.sfx->snd))
{
engine->sfx_list.sfx[i].plays = 0;
}
}
engine->sfx_list.played_sfx = 0;
}
//void init_scene(Scene_t* scene, SceneType_t scene_type, system_func_t render_func, action_func_t action_func)
void init_scene(Scene_t* scene, system_func_t render_func, action_func_t action_func)
void init_scene(Scene_t* scene, render_func_t render_func, action_func_t action_func)
{
sc_map_init_64(&scene->action_map, 32, 0);
sc_array_init(&scene->systems);
@ -102,6 +154,7 @@ void init_scene(Scene_t* scene, system_func_t render_func, action_func_t action_
scene->render_function = render_func;
scene->action_function = action_func;
scene->state = SCENE_ENDED;
scene->time_scale = 1.0f;
}
void free_scene(Scene_t* scene)
@ -112,21 +165,23 @@ void free_scene(Scene_t* scene)
deinit_particle_system(&scene->part_sys);
}
inline void update_scene(Scene_t* scene)
inline void update_scene(Scene_t* scene, float delta_time)
{
scene->delta_time = delta_time * scene->time_scale;
system_func_t sys;
sc_array_foreach(&scene->systems, sys)
{
sys(scene);
}
update_particle_system(&scene->part_sys);
update_particle_system(&scene->part_sys, scene->delta_time);
}
inline void render_scene(Scene_t* scene)
{
BeginDrawing();
scene->render_function(scene);
EndDrawing();
if (scene->render_function != NULL)
{
scene->render_function(scene);
}
}
inline void do_action(Scene_t* scene, ActionType_t action, bool pressed)

View File

@ -37,6 +37,7 @@ typedef enum SceneState {
SCENE_ENDED,
}SceneState_t;
typedef void(*render_func_t)(Scene_t*);
typedef void(*system_func_t)(Scene_t*);
typedef void(*action_func_t)(Scene_t*, ActionType_t, bool);
sc_array_def(system_func_t, systems);
@ -44,9 +45,12 @@ sc_array_def(system_func_t, systems);
struct Scene {
struct sc_map_64 action_map; // key -> actions
struct sc_array_systems systems;
system_func_t render_function;
render_func_t render_function;
action_func_t action_function;
EntityManager_t ent_manager;
float delta_time;
float time_scale;
Vector2 mouse_pos;
//SceneType_t scene_type;
SceneState_t state;
ParticleSystem_t part_sys;
@ -60,15 +64,16 @@ void process_inputs(GameEngine_t* engine, Scene_t* scene);
void change_scene(GameEngine_t* engine, unsigned int idx);
bool load_sfx(GameEngine_t* engine, const char* snd_name, uint32_t tag_idx);
void play_sfx(GameEngine_t* engine, unsigned int tag_idx);
void play_sfx_pitched(GameEngine_t* engine, unsigned int tag_idx, float pitch);
void update_sfx_list(GameEngine_t* engine);
// Inline functions, for convenience
extern void update_scene(Scene_t* scene);
extern void update_scene(Scene_t* scene, float delta_time);
extern void render_scene(Scene_t* scene);
extern void do_action(Scene_t* scene, ActionType_t action, bool pressed);
//void init_scene(Scene_t* scene, SceneType_t scene_type, system_func_t render_func, action_func_t action_func);
void init_scene(Scene_t* scene, system_func_t render_func, action_func_t action_func);
void init_scene(Scene_t* scene, render_func_t render_func, action_func_t action_func);
void free_scene(Scene_t* scene);
#endif // __ENGINE_H

View File

@ -1,6 +1,7 @@
#ifndef _ENGINE_CONF_H
#define _ENGINE_CONF_H
#define MAX_ENTITIES 2048
#define MAX_TEXTURES 16
#define MAX_SPRITES 64
#define MAX_SOUNDS 32
@ -11,12 +12,12 @@
#define N_SFX 32
#define MAX_EMITTER_CONF 8
//#define MAX_PARTICLE_EMITTER 8
#define MAX_ACTIVE_PARTICLE_EMITTER 128
#define MAX_PARTICLES 32
#define MAX_ACTIVE_PARTICLE_EMITTER 512
#define MAX_PARTICLES 64
#define MAX_TILE_TYPES 16
#define N_TAGS 10
#define N_COMPONENTS 15
#define MAX_COMP_POOL_SIZE 4096
#define N_COMPONENTS 20
#define MAX_COMP_POOL_SIZE MAX_ENTITIES
#endif // _ENGINE_CONF_H

View File

@ -230,3 +230,8 @@ void print_mempool_stats(char* buffer)
);
}
}
uint32_t get_num_of_free_entities(void)
{
return ent_mempool.free_list.count;
}

View File

@ -13,4 +13,5 @@ void* get_component_wtih_id(ComponentEnum_t comp_type, unsigned long idx);
void free_component_to_mempool(ComponentEnum_t comp_type, unsigned long idx);
void print_mempool_stats(char* buffer);
uint32_t get_num_of_free_entities(void);
#endif //__MEMPOOL_H

View File

@ -1,8 +1,8 @@
#include "particle_sys.h"
#include "assets.h"
#include "raymath.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
void init_particle_system(ParticleSystem_t* system)
{
@ -30,9 +30,9 @@ static inline float generate_randrange(float lo, float hi)
static inline void spawn_particle(ParticleEmitter_t* emitter, uint32_t idx)
{
uint32_t lifetime = (emitter->config->particle_lifetime[1] - emitter->config->particle_lifetime[0]);
float lifetime = (emitter->config->particle_lifetime[1] - emitter->config->particle_lifetime[0]);
emitter->particles[idx].timer = emitter->config->particle_lifetime[0];
emitter->particles[idx].timer += rand() % lifetime;
emitter->particles[idx].timer += lifetime * rand()/ (float)RAND_MAX;
emitter->particles[idx].alive = true;
float angle = generate_randrange(emitter->config->launch_range[0], emitter->config->launch_range[1]);
@ -92,7 +92,7 @@ void play_emitter_handle(ParticleSystem_t* system, uint16_t handle)
{
// TODO: deal with stream type
//spawn_particle(emitter, 0);
uint32_t incr = 0;
float incr = 0;
for (uint32_t i = 0; i < emitter->n_particles; ++i)
{
emitter->particles[i].timer = incr;
@ -151,7 +151,7 @@ EmitterHandle play_particle_emitter(ParticleSystem_t* system, const ParticleEmit
return idx;
}
void update_particle_system(ParticleSystem_t* system)
void update_particle_system(ParticleSystem_t* system, float delta_time)
{
uint32_t emitter_idx = system->emitter_list[0].next;
uint32_t prev_idx = 0;
@ -163,7 +163,7 @@ void update_particle_system(ParticleSystem_t* system)
if (emitter->emitter_update_func != NULL && emitter->active)
{
emitter->active = emitter->emitter_update_func(emitter);
emitter->active = emitter->emitter_update_func(emitter, delta_time);
}
for (uint32_t i = 0; i < emitter->n_particles; ++i)
@ -175,13 +175,13 @@ void update_particle_system(ParticleSystem_t* system)
{
if (emitter->update_func != NULL)
{
emitter->update_func(emitter->particles + i, emitter->user_data);
emitter->update_func(emitter->particles + i, emitter->user_data, delta_time);
}
}
// Lifetime update
if (emitter->particles[i].timer > 0) emitter->particles[i].timer--;
if (emitter->particles[i].timer == 0)
emitter->particles[i].timer -= delta_time;
if (emitter->particles[i].timer <= 0.0f)
{
if (emitter->particles[i].spawned)
{
@ -222,6 +222,10 @@ void update_particle_system(ParticleSystem_t* system)
{
emitter->finished = true;
}
}
if (emitter->finished)
{
system->emitter_list[prev_idx].next = system->emitter_list[emitter_idx].next;
system->emitter_list[emitter_idx].next = 0;
system->emitter_list[emitter_idx].playing = false;

View File

@ -22,15 +22,15 @@ typedef struct Particle
float rotation;
float angular_vel;
float size;
uint32_t timer;
float timer;
bool alive;
bool spawned;
}Particle_t;
typedef struct ParticleEmitter ParticleEmitter_t;
typedef void (*particle_update_func_t)(Particle_t* part, void* user_data);
typedef bool (*emitter_check_func_t)(const ParticleEmitter_t* emitter);
typedef void (*particle_update_func_t)(Particle_t* part, void* user_data, float delta_time);
typedef bool (*emitter_check_func_t)(const ParticleEmitter_t* emitter, float delta_time);
typedef struct EmitterConfig
{
@ -38,8 +38,8 @@ typedef struct EmitterConfig
float speed_range[2];
float angle_range[2];
float rotation_range[2];
uint32_t particle_lifetime[2];
uint32_t initial_spawn_delay;
float particle_lifetime[2];
float initial_spawn_delay;
PartEmitterType_t type;
bool one_shot;
}EmitterConfig_t;
@ -51,7 +51,7 @@ struct ParticleEmitter
Vector2 position;
Particle_t particles[MAX_PARTICLES];
uint32_t n_particles;
uint32_t timer;
float timer;
bool finished;
bool active;
void* user_data;
@ -88,7 +88,7 @@ void update_emitter_handle_position(ParticleSystem_t* system, EmitterHandle hand
void unload_emitter_handle(ParticleSystem_t* system, EmitterHandle handle);
bool is_emitter_handle_alive(ParticleSystem_t* system, EmitterHandle handle);
void update_particle_system(ParticleSystem_t* system);
void update_particle_system(ParticleSystem_t* system, float delta_time);
void draw_particle_system(ParticleSystem_t* system);
void deinit_particle_system(ParticleSystem_t* system);
#endif // _PARTICLE_SYSTEM_H

View File

@ -6,6 +6,7 @@
#include "assets_loader.h"
#include <stdio.h>
#include <unistd.h>
#include <math.h>
Scene_t* scenes[1];
static GameEngine_t engine =
@ -39,10 +40,14 @@ int main(void)
scenes[0] = &scene.scene;
change_scene(&engine, 0);
const float DT = 1.0f/60.0f;
while(true)
{
float frame_time = GetFrameTime();
float delta_time = fminf(frame_time, DT);
process_inputs(&engine, &scene.scene);
update_scene(&scene.scene);
update_scene(&scene.scene, delta_time);
update_entity_manager(&scene.scene.ent_manager);
// This is needed to advance time delta
render_scene(&scene.scene);

8
main.c
View File

@ -4,6 +4,7 @@
#include "ent_impl.h"
#include "mempool.h"
#include <stdio.h>
#include <math.h>
#define N_SCENES 4
Scene_t *scenes[N_SCENES];
@ -79,6 +80,7 @@ int main(void)
scenes[2] = &sandbox_scene.scene;
change_scene(&engine, 0);
const float DT = 1.0f/60.0f;
while (!WindowShouldClose())
{
// This entire key processing relies on the assumption that a pressed key will
@ -92,7 +94,11 @@ int main(void)
process_inputs(&engine, curr_scene);
update_scene(curr_scene);
float frame_time = GetFrameTime();
float delta_time = fminf(frame_time, DT);
update_scene(curr_scene, delta_time);
update_entity_manager(&curr_scene->ent_manager);
// This is needed to advance time delta
render_scene(curr_scene);

View File

@ -2,10 +2,12 @@
#include "scene_impl.h"
#include <stdio.h>
#include <unistd.h>
#include <math.h>
// Maintain own queue to handle key presses
struct sc_queue_32 key_buffer;
const float DT = 1.0f/60.0f;
int main(void)
{
sc_queue_init(&key_buffer);
@ -48,7 +50,9 @@ int main(void)
sc_queue_add_last(&key_buffer, button);
}
update_scene(&scene.scene);
float frame_time = GetFrameTime();
float delta_time = fminf(frame_time, DT);
update_scene(&scene.scene, delta_time);
update_entity_manager(&scene.scene.ent_manager);
// This is needed to advance time delta
BeginDrawing();

View File

@ -6,11 +6,9 @@
#include "constants.h"
static const Vector2 GRAVITY = {0, GRAV_ACCEL};
void simple_particle_system_update(Particle_t* part, void* user_data)
void simple_particle_system_update(Particle_t* part, void* user_data, float delta_time)
{
(void)user_data;
float delta_time = DELTA_T; // TODO: Will need to think about delta time handling
part->rotation += part->angular_vel;
part->velocity =
@ -46,7 +44,7 @@ void simple_particle_system_update(Particle_t* part, void* user_data)
}
}
static bool check_mouse_click(const ParticleEmitter_t* emitter)
static bool check_mouse_click(const ParticleEmitter_t* emitter, float delta_time)
{
return IsMouseButtonDown(MOUSE_RIGHT_BUTTON);
}
@ -65,11 +63,13 @@ int main(void)
.origin = (Vector2){0, 0},
.anchor = (Vector2){tex.width / 2, tex.height / 2},
.frame_count = 0,
.elapsed = 0,
.speed = 0,
.name = "test_spr"
};
const float DT = 1.0f/60.0f;
float delta_time = 0.0f;
EmitterConfig_t conf ={
.one_shot = true,
.launch_range = {0, 360},
@ -86,6 +86,7 @@ int main(void)
.update_func = &simple_particle_system_update,
.emitter_update_func = NULL,
.spr = (tex.width == 0) ? NULL : &spr,
.user_data = &delta_time,
};
EmitterConfig_t conf2 ={
@ -106,6 +107,7 @@ int main(void)
.update_func = &simple_particle_system_update,
.emitter_update_func = &check_mouse_click,
.spr = (tex.width == 0) ? NULL : &spr,
.user_data = NULL,
};
bool key_press = false;
@ -114,6 +116,8 @@ int main(void)
EmitterHandle han = 0;
while(!WindowShouldClose())
{
float frame_time = GetFrameTime();
delta_time = fminf(frame_time, DT);
Vector2 mouse_pos = GetMousePosition();
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
@ -145,7 +149,7 @@ int main(void)
han = 0;
}
update_particle_system(&part_sys);
update_particle_system(&part_sys, delta_time);
sprintf(text_buffer, "free: %u", get_number_of_free_emitter(&part_sys));
BeginDrawing();
ClearBackground(RAYWHITE);

2
run.sh
View File

@ -1,3 +1,3 @@
#!/bin/sh
LSAN_OPTIONS=suppressions=./lsan_supp.txt ./build/$1
./build.sh && LSAN_OPTIONS=suppressions=./lsan_supp.txt ./build/$1

View File

@ -3,6 +3,7 @@
#include "assets_loader.h"
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
@ -10,6 +11,7 @@
return true; // Just preventDefault everything lol
}
#endif
const float DT = 1.0f/60.0f;
Scene_t* scenes[1];
static GameEngine_t engine =
@ -26,7 +28,9 @@ void update_loop(void)
Scene_t* scene = engine.scenes[engine.curr_scene];
process_inputs(&engine, scene);
update_scene(scene);
float frame_time = GetFrameTime();
float delta_time = fminf(frame_time, DT);
update_scene(scene, delta_time);
update_entity_manager(&scene->ent_manager);
// This is needed to advance time delta
render_scene(scene);
@ -75,6 +79,7 @@ int main(void)
emscripten_set_main_loop(update_loop, 0, 1);
#else
puts("Regular main loop");
const float DT = 1.0f/60.0f;
while(true)
{
@ -82,7 +87,10 @@ int main(void)
// appear in the polling of raylib
process_inputs(&engine, &scene.scene);
update_scene(&scene.scene);
float frame_time = GetFrameTime();
float delta_time = fminf(frame_time, DT);
update_scene(&scene.scene, delta_time);
update_entity_manager(&scene.scene.ent_manager);
// This is needed to advance time delta
render_scene(&scene.scene);

View File

@ -41,7 +41,7 @@ static bool parse_emitter_info(char* emitter_info_str, EmitterConfig_t* conf)
char emitter_type;
uint8_t one_shot;
int data_count = sscanf(
emitter_info_str, "%c,%f-%f,%f-%f,%f-%f,%f-%f,%u-%u,%u,%c",
emitter_info_str, "%c,%f-%f,%f-%f,%f-%f,%f-%f,%f-%f,%f,%c",
&emitter_type,
conf->launch_range, conf->launch_range + 1,
conf->speed_range, conf->speed_range + 1,

View File

@ -21,9 +21,9 @@
#define MOVE_ACCEL 1300
#ifndef TILE16_SIZE
#define PLAYER_WIDTH 30
#define PLAYER_WIDTH 28
#define PLAYER_HEIGHT 42
#define PLAYER_C_WIDTH 30
#define PLAYER_C_WIDTH 28
#define PLAYER_C_HEIGHT 26
#else
#define PLAYER_WIDTH 14

View File

@ -92,6 +92,7 @@ static void level_scene_render_func(Scene_t* scene)
draw_rec.y = 0;
draw_rec.height *= -1;
static char buffer[512];
BeginDrawing();
ClearBackground(LIGHTGRAY);
DrawTextureRec(
data->game_viewport.texture,
@ -123,6 +124,9 @@ static void level_scene_render_func(Scene_t* scene)
draw_pos.y += SELECTION_TILE_SIZE + 5;
sprintf(buffer, "Crate %s on spawn", crate_activation? "active" : "inactive");
DrawText(buffer, draw_pos.x, draw_pos.y, 20, BLACK);
draw_pos.y += SELECTION_TILE_SIZE + 5;
sprintf(buffer, "Time scale: %.2f", scene->time_scale);
DrawText(buffer, draw_pos.x, draw_pos.y, 20, BLACK);
// For DEBUG
const int gui_x = data->game_rec.x + data->game_rec.width + 10;
@ -136,7 +140,7 @@ static void level_scene_render_func(Scene_t* scene)
CPlayerState_t* p_pstate = get_component(p_ent, CPLAYERSTATE_T);
CMovementState_t* p_mstate = get_component(p_ent, CMOVEMENTSTATE_T);
sprintf(buffer, "Pos: %.3f\n %.3f", p_ct->position.x, p_ct->position.y);
sprintf(buffer, "Pos: %.3f\n %.3f", p_ent->position.x, p_ent->position.y);
DrawText(buffer, gui_x, gui_y, 12, BLACK);
sprintf(buffer, "Vel: %.3f\n %.3f", p_ct->velocity.x, p_ct->velocity.y);
DrawText(buffer, gui_x + 80, gui_y, 12, BLACK);
@ -184,6 +188,7 @@ static void level_scene_render_func(Scene_t* scene)
gui_y += 300;
sprintf(buffer, "Chests: %u / %u", data->coins.current, data->coins.total);
DrawText(buffer, gui_x, gui_y, 24, BLACK);
EndDrawing();
}
static void render_editor_game_scene(Scene_t* scene)
@ -290,7 +295,6 @@ static void render_editor_game_scene(Scene_t* scene)
char buffer[64] = {0};
sc_map_foreach_value(&scene->ent_manager.entities, p_ent)
{
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
// Draw the spawn point
@ -303,10 +307,10 @@ static void render_editor_game_scene(Scene_t* scene)
Vector2 box_size = {0};
if (p_bbox != NULL) box_size = p_bbox->size;
if (
p_ct->position.x + box_size.x < min.x * tilemap.tile_size
|| p_ct->position.x > max.x * tilemap.tile_size
|| p_ct->position.y + box_size.y < min.y * tilemap.tile_size
|| p_ct->position.y > max.y * tilemap.tile_size
p_ent->position.x + box_size.x < min.x * tilemap.tile_size
|| p_ent->position.x > max.x * tilemap.tile_size
|| p_ent->position.y + box_size.y < min.y * tilemap.tile_size
|| p_ent->position.y > max.y * tilemap.tile_size
) continue;
Color colour;
@ -336,11 +340,11 @@ static void render_editor_game_scene(Scene_t* scene)
{
if (p_ent->m_tag == BOULDER_ENT_TAG)
{
DrawCircleV(Vector2Add(p_ct->position, p_bbox->half_size), p_bbox->half_size.x, colour);
DrawCircleV(Vector2Add(p_ent->position, p_bbox->half_size), p_bbox->half_size.x, colour);
}
else
{
DrawRectangle(p_ct->position.x, p_ct->position.y, p_bbox->size.x, p_bbox->size.y, colour);
DrawRectangle(p_ent->position.x, p_ent->position.y, p_bbox->size.x, p_bbox->size.y, colour);
}
if (p_ent->m_tag == CRATES_ENT_TAG)
@ -352,42 +356,42 @@ static void render_editor_game_scene(Scene_t* scene)
{
case CONTAINER_LEFT_ARROW:
DrawLine(
p_ct->position.x,
p_ct->position.y + p_bbox->half_size.y,
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ent->position.x,
p_ent->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->half_size.y,
BLACK
);
break;
case CONTAINER_RIGHT_ARROW:
DrawLine(
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ct->position.x + p_bbox->size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->size.x,
p_ent->position.y + p_bbox->half_size.y,
BLACK
);
break;
case CONTAINER_UP_ARROW:
DrawLine(
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y,
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->half_size.y,
BLACK
);
break;
case CONTAINER_DOWN_ARROW:
DrawLine(
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->size.y,
BLACK
);
break;
case CONTAINER_BOMB:
DrawCircleV(Vector2Add(p_ct->position, p_bbox->half_size), p_bbox->half_size.x, BLACK);
DrawCircleV(Vector2Add(p_ent->position, p_bbox->half_size), p_bbox->half_size.x, BLACK);
break;
default:
break;
@ -403,8 +407,8 @@ static void render_editor_game_scene(Scene_t* scene)
for (uint8_t i = 0;i < p_hitbox->n_boxes; ++i)
{
Rectangle rec = {
.x = p_ct->position.x + p_hitbox->boxes[i].x,
.y = p_ct->position.y + p_hitbox->boxes[i].y,
.x = p_ent->position.x + p_hitbox->boxes[i].x,
.y = p_ent->position.y + p_hitbox->boxes[i].y,
.width = p_hitbox->boxes[i].width,
.height = p_hitbox->boxes[i].height,
};
@ -414,8 +418,8 @@ static void render_editor_game_scene(Scene_t* scene)
if (p_hurtbox != NULL)
{
Rectangle rec = {
.x = p_ct->position.x + p_hurtbox->offset.x,
.y = p_ct->position.y + p_hurtbox->offset.y,
.x = p_ent->position.x + p_hurtbox->offset.x,
.y = p_ent->position.y + p_hurtbox->offset.y,
.width = p_hurtbox->size.x,
.height = p_hurtbox->size.y,
};
@ -427,7 +431,7 @@ static void render_editor_game_scene(Scene_t* scene)
const SpriteRenderInfo_t spr = p_cspr->sprites[p_cspr->current_idx];
if (spr.sprite != NULL)
{
Vector2 pos = Vector2Add(p_ct->position, spr.offset);
Vector2 pos = Vector2Add(p_ent->position, spr.offset);
draw_sprite(spr.sprite, p_cspr->current_frame, pos, 0.0f, p_cspr->flip_x);
}
}
@ -435,8 +439,7 @@ static void render_editor_game_scene(Scene_t* scene)
sc_map_foreach_value(&scene->ent_manager.entities_map[LEVEL_END_TAG], p_ent)
{
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
DrawCircleV(p_ct->position, tilemap.tile_size >> 1, (data->coins.current < data->coins.total)? RED : GREEN);
DrawCircleV(p_ent->position, tilemap.tile_size >> 1, (data->coins.current < data->coins.total)? RED : GREEN);
}
draw_particle_system(&scene->part_sys);
@ -518,9 +521,10 @@ static void spawn_chest(Scene_t* scene, unsigned int tile_idx)
Entity_t* p_crate = create_chest(&scene->ent_manager);
if (p_crate == NULL) return;
p_crate->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE;
p_crate->position.y = (tile_idx / data->tilemap.width) * TILE_SIZE;
CTransform_t* p_ctransform = get_component(p_crate, CTRANSFORM_COMP_T);
p_ctransform->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE;
p_ctransform->position.y = (tile_idx / data->tilemap.width) * TILE_SIZE;
p_ctransform->active = true;
}
@ -529,10 +533,10 @@ static void spawn_crate(Scene_t* scene, unsigned int tile_idx, bool metal, Conta
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
Entity_t* p_crate = create_crate(&scene->ent_manager, metal, item);
if (p_crate == NULL) return;
p_crate->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE;
p_crate->position.y = (tile_idx / data->tilemap.width) * TILE_SIZE;
CTransform_t* p_ctransform = get_component(p_crate, CTRANSFORM_COMP_T);
p_ctransform->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE;
p_ctransform->position.y = (tile_idx / data->tilemap.width) * TILE_SIZE;
p_ctransform->active = active;
}
@ -542,21 +546,18 @@ static void spawn_boulder(Scene_t* scene, unsigned int tile_idx)
Entity_t* p_boulder = create_boulder(&scene->ent_manager);
if (p_boulder == NULL) return;
CTransform_t* p_ctransform = get_component(p_boulder, CTRANSFORM_COMP_T);
p_ctransform->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE;
p_ctransform->position.y = (tile_idx / data->tilemap.width) * TILE_SIZE;
p_boulder->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE;
p_boulder->position.y = (tile_idx / data->tilemap.width) * TILE_SIZE;
}
static void toggle_block_system(Scene_t* scene)
static void toggle_block_system(Scene_t* scene, ActionType_t action, bool pressed)
{
// TODO: This system is not good as the interface between raw input and actions is broken
static unsigned int last_tile_idx = MAX_N_TILES;
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
TileGrid_t tilemap = data->tilemap;
Vector2 raw_mouse_pos = {GetMouseX(), GetMouseY()};
raw_mouse_pos = Vector2Subtract(raw_mouse_pos, (Vector2){data->game_rec.x, data->game_rec.y});
Vector2 raw_mouse_pos = Vector2Subtract(scene->mouse_pos, (Vector2){data->game_rec.x, data->game_rec.y});
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
if (action == ACTION_SPAWN_TILE && !pressed)
{
last_tile_idx = MAX_N_TILES;
}
@ -571,7 +572,7 @@ static void toggle_block_system(Scene_t* scene)
if (tile_idx >= (tilemap.n_tiles - tilemap.width)) return;
if (tile_idx == last_tile_idx) return;
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
if (action == ACTION_SPAWN_TILE && pressed)
{
enum EntitySpawnSelection sel = (enum EntitySpawnSelection)current_spawn_selection;
TileType_t new_type = EMPTY_TILE;
@ -642,9 +643,8 @@ static void toggle_block_system(Scene_t* scene)
Entity_t* p_ent = create_water_runner(&scene->ent_manager, DEFAULT_MAP_WIDTH, DEFAULT_MAP_HEIGHT, tile_idx);
if (p_ent != NULL)
{
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
p_ct->position.x = (tile_idx % tilemap.width) * tilemap.tile_size;
p_ct->position.y = (tile_idx / tilemap.width) * tilemap.tile_size;
p_ent->position.x = (tile_idx % tilemap.width) * tilemap.tile_size;
p_ent->position.y = (tile_idx / tilemap.width) * tilemap.tile_size;
}
}
break;
@ -653,9 +653,8 @@ static void toggle_block_system(Scene_t* scene)
Entity_t* p_ent = create_level_end(&scene->ent_manager);
if (p_ent != NULL)
{
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
p_ct->position.x = (tile_idx % tilemap.width) * tilemap.tile_size + (tilemap.tile_size >> 1);
p_ct->position.y = (tile_idx / tilemap.width) * tilemap.tile_size + (tilemap.tile_size >> 1);;
p_ent->position.x = (tile_idx % tilemap.width) * tilemap.tile_size + (tilemap.tile_size >> 1);
p_ent->position.y = (tile_idx / tilemap.width) * tilemap.tile_size + (tilemap.tile_size >> 1);;
}
}
break;
@ -675,7 +674,7 @@ static void toggle_block_system(Scene_t* scene)
p_crunner->state = BFS_RESET;
}
}
else if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON))
else if (action == ACTION_REMOVE_TILE && pressed)
{
change_a_tile(&tilemap, tile_idx, EMPTY_TILE);
tilemap.tiles[tile_idx].water_level = 0;
@ -728,7 +727,7 @@ static void toggle_block_system(Scene_t* scene)
&& raw_mouse_pos.y < SELECTION_REGION_HEIGHT
)
{
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
if (action == ACTION_SPAWN_TILE && !pressed)
{
current_spawn_selection = ((int)raw_mouse_pos.x / SELECTION_TILE_SIZE);
}
@ -965,11 +964,25 @@ static void level_do_action(Scene_t* scene, ActionType_t action, bool pressed)
}
break;
case ACTION_SET_SPAWNPOINT:
{
CTransform_t* p_ct = get_component(p_player, CTRANSFORM_COMP_T);
p_player->spawn_pos = p_ct->position;
}
p_player->spawn_pos = p_player->position;
break;
case ACTION_TOGGLE_TIMESLOW:
if (!pressed)
{
if (scene->time_scale < 1.0f)
{
scene->time_scale = 1.0f;
}
else
{
scene->time_scale = 0.25f;
}
}
break;
case ACTION_SPAWN_TILE:
case ACTION_REMOVE_TILE:
toggle_block_system(scene, action, pressed);
update_entity_manager(&scene->ent_manager);
default:
break;
}
@ -1214,7 +1227,6 @@ void init_sandbox_scene(LevelScene_t* scene)
sc_array_add(&scene->scene.systems, &update_water_runner_system);
sc_array_add(&scene->scene.systems, &player_respawn_system);
sc_array_add(&scene->scene.systems, &level_end_detection_system);
sc_array_add(&scene->scene.systems, &toggle_block_system);
sc_array_add(&scene->scene.systems, &render_editor_game_scene);
// This avoid graphical glitch, not essential
@ -1238,6 +1250,9 @@ void init_sandbox_scene(LevelScene_t* scene)
sc_map_put_64(&scene->scene.action_map, KEY_R, ACTION_RESTART);
sc_map_put_64(&scene->scene.action_map, KEY_B, ACTION_TOGGLE_GRID);
sc_map_put_64(&scene->scene.action_map, KEY_V, ACTION_SET_SPAWNPOINT);
sc_map_put_64(&scene->scene.action_map, KEY_U, ACTION_TOGGLE_TIMESLOW);
sc_map_put_64(&scene->scene.action_map, MOUSE_LEFT_BUTTON, ACTION_SPAWN_TILE);
sc_map_put_64(&scene->scene.action_map, MOUSE_RIGHT_BUTTON, ACTION_REMOVE_TILE);
}

View File

@ -20,6 +20,7 @@ static void level_scene_render_func(Scene_t* scene)
draw_rec.height *= -1;
static char buffer[512];
BeginDrawing();
ClearBackground(LIGHTGRAY);
DrawTextureRec(
data->game_viewport.texture,
@ -50,6 +51,7 @@ static void level_scene_render_func(Scene_t* scene)
print_mempool_stats(buffer);
DrawText(buffer, gui_x, 350, 12, BLACK);
EndDrawing();
}
static void level_do_action(Scene_t* scene, ActionType_t action, bool pressed)
@ -202,17 +204,16 @@ static void render_regular_game_scene(Scene_t* scene)
sc_map_foreach_value(&scene->ent_manager.entities, p_ent)
{
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
// Entity culling
Vector2 box_size = {0};
if (p_bbox != NULL) box_size = p_bbox->size;
if (
p_ct->position.x + box_size.x < min.x * tilemap.tile_size
|| p_ct->position.x > max.x * tilemap.tile_size
|| p_ct->position.y + box_size.y < min.y * tilemap.tile_size
|| p_ct->position.y > max.y * tilemap.tile_size
p_ent->position.x + box_size.x < min.x * tilemap.tile_size
|| p_ent->position.x > max.x * tilemap.tile_size
|| p_ent->position.y + box_size.y < min.y * tilemap.tile_size
|| p_ent->position.y > max.y * tilemap.tile_size
) continue;
// Render Sprite only
@ -222,7 +223,7 @@ static void render_regular_game_scene(Scene_t* scene)
const SpriteRenderInfo_t spr = p_cspr->sprites[p_cspr->current_idx];
if (spr.sprite != NULL)
{
Vector2 pos = Vector2Add(p_ct->position, spr.offset);
Vector2 pos = Vector2Add(p_ent->position, spr.offset);
draw_sprite(spr.sprite, p_cspr->current_frame, pos, 0.0f, p_cspr->flip_x);
}
continue;
@ -250,11 +251,11 @@ static void render_regular_game_scene(Scene_t* scene)
{
if (p_ent->m_tag == BOULDER_ENT_TAG)
{
DrawCircleV(Vector2Add(p_ct->position, p_bbox->half_size), p_bbox->half_size.x, colour);
DrawCircleV(Vector2Add(p_ent->position, p_bbox->half_size), p_bbox->half_size.x, colour);
}
else
{
DrawRectangle(p_ct->position.x, p_ct->position.y, p_bbox->size.x, p_bbox->size.y, colour);
DrawRectangle(p_ent->position.x, p_ent->position.y, p_bbox->size.x, p_bbox->size.y, colour);
}
if (p_ent->m_tag == CRATES_ENT_TAG)
@ -266,42 +267,42 @@ static void render_regular_game_scene(Scene_t* scene)
{
case CONTAINER_LEFT_ARROW:
DrawLine(
p_ct->position.x,
p_ct->position.y + p_bbox->half_size.y,
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ent->position.x,
p_ent->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->half_size.y,
BLACK
);
break;
case CONTAINER_RIGHT_ARROW:
DrawLine(
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ct->position.x + p_bbox->size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->size.x,
p_ent->position.y + p_bbox->half_size.y,
BLACK
);
break;
case CONTAINER_UP_ARROW:
DrawLine(
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y,
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->half_size.y,
BLACK
);
break;
case CONTAINER_DOWN_ARROW:
DrawLine(
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->half_size.y,
p_ct->position.x + p_bbox->half_size.x,
p_ct->position.y + p_bbox->size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->half_size.y,
p_ent->position.x + p_bbox->half_size.x,
p_ent->position.y + p_bbox->size.y,
BLACK
);
break;
case CONTAINER_BOMB:
DrawCircleV(Vector2Add(p_ct->position, p_bbox->half_size), p_bbox->half_size.x, BLACK);
DrawCircleV(Vector2Add(p_ent->position, p_bbox->half_size), p_bbox->half_size.x, BLACK);
break;
default:
break;

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@ Entity_t* create_crate(EntityManager_t* ent_manager, bool metal, ContainerItem_t
p_bbox->fragile = false;
CTransform_t* p_ctransform = add_component(p_crate, CTRANSFORM_COMP_T);
p_ctransform->grav_delay = 7;
p_ctransform->grav_delay = 0.20f;
p_ctransform->shape_factor = metal ? (Vector2){0.7,0.7} : (Vector2){0.8,0.8} ;
add_component(p_crate, CMOVEMENTSTATE_T);
@ -87,7 +87,7 @@ Entity_t* create_boulder(EntityManager_t* ent_manager)
p_bbox->fragile = false;
CTransform_t* p_ctransform = add_component(p_boulder, CTRANSFORM_COMP_T);
p_ctransform->grav_delay = 5;
p_ctransform->grav_delay = 1.0f/12;
p_ctransform->active = true;
p_ctransform->shape_factor = (Vector2){0.6, 0.6};
CMovementState_t* p_move = add_component(p_boulder, CMOVEMENTSTATE_T);
@ -95,7 +95,7 @@ Entity_t* create_boulder(EntityManager_t* ent_manager)
add_component(p_boulder, CTILECOORD_COMP_T);
CMoveable_t* p_cmove = add_component(p_boulder, CMOVEABLE_T);
p_cmove->move_speed = 8;
p_cmove->move_speed = 480;
CHurtbox_t* p_hurtbox = add_component(p_boulder, CHURTBOX_T);
p_hurtbox->size = p_bbox->size;
p_hurtbox->def = 2;
@ -159,6 +159,17 @@ Entity_t* create_bomb(EntityManager_t* ent_manager, Vector2 launch_dir)
Entity_t* p_bomb = add_entity(ent_manager, DESTRUCTABLE_ENT_TAG);
if (p_bomb == NULL) return NULL;
p_bomb->position.x += (TILE_SIZE - 25) / 2;
p_bomb->position.y += (TILE_SIZE - 25) / 2;
if (launch_dir.x > 0)
{
p_bomb->position.x += TILE_SIZE/ 2;
}
else if (launch_dir.x < 0)
{
p_bomb->position.x -= TILE_SIZE / 2;
}
add_component(p_bomb, CTILECOORD_COMP_T);
add_component(p_bomb, CMOVEMENTSTATE_T);
CHitBoxes_t* p_hitbox = add_component(p_bomb, CHITBOXES_T);
@ -179,19 +190,9 @@ Entity_t* create_bomb(EntityManager_t* ent_manager, Vector2 launch_dir)
p_ctransform->active = true;
p_ctransform->shape_factor = (Vector2){0.1, 0.1};
p_ctransform->movement_mode = REGULAR_MOVEMENT;
p_ctransform->position.x += (TILE_SIZE - 25) / 2;
p_ctransform->position.y += (TILE_SIZE - 25) / 2;
p_ctransform->velocity = Vector2Scale(Vector2Normalize(launch_dir), 500);
if (launch_dir.x > 0)
{
p_ctransform->position.x += TILE_SIZE/ 2;
}
else if (launch_dir.x < 0)
{
p_ctransform->position.x -= TILE_SIZE / 2;
}
return p_bomb;
}
@ -200,6 +201,8 @@ Entity_t* create_explosion(EntityManager_t* ent_manager)
Entity_t* p_explosion = add_entity(ent_manager, DESTRUCTABLE_ENT_TAG);
if (p_explosion == NULL) return NULL;
p_explosion->position.x -= 16;
p_explosion->position.y -= 16;
add_component(p_explosion, CTILECOORD_COMP_T);
CHitBoxes_t* p_hitbox = add_component(p_explosion, CHITBOXES_T);
p_hitbox->n_boxes = 1;
@ -209,8 +212,6 @@ Entity_t* create_explosion(EntityManager_t* ent_manager)
CTransform_t* p_ctransform = add_component(p_explosion, CTRANSFORM_COMP_T);
p_ctransform->movement_mode = KINEMATIC_MOVEMENT;
p_ctransform->active = true;
p_ctransform->position.x -= 16;
p_ctransform->position.y -= 16;
p_hitbox->boxes[0] = (Rectangle){0, 0, TILE_SIZE + 32, TILE_SIZE + 32};
CSprite_t* p_cspr = add_component(p_explosion, CSPRITE_T);
@ -218,7 +219,7 @@ Entity_t* create_explosion(EntityManager_t* ent_manager)
p_cspr->current_idx = 17;
CLifeTimer_t* p_clifetimer = add_component(p_explosion, CLIFETIMER_T);
p_clifetimer->life_time = 3;
p_clifetimer->life_time = 0.05f;
return p_explosion;
}
@ -233,7 +234,7 @@ Entity_t* create_chest(EntityManager_t* ent_manager)
p_bbox->fragile = true;
CTransform_t* p_ctransform = add_component(p_chest, CTRANSFORM_COMP_T);
p_ctransform->grav_delay = 7;
p_ctransform->grav_delay = 0.3f;
p_ctransform->shape_factor = (Vector2){0.7,0.7};
add_component(p_chest, CMOVEMENTSTATE_T);
add_component(p_chest, CTILECOORD_COMP_T);

View File

@ -6,12 +6,14 @@
static void menu_scene_render_func(Scene_t* scene)
{
MenuSceneData_t* data = &(CONTAINER_OF(scene, MenuScene_t, scene)->data);
ClearBackground(RAYWHITE);
DrawText("This is a game", 25, 220, 12, BLACK);
UI_button(data->buttons, "Start");
UI_button(data->buttons + 1, "Sandbox");
UI_button(data->buttons + 2, "Continue");
UI_button(data->buttons + 3, "Exit");
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("This is a game", 25, 220, 12, BLACK);
UI_button(data->buttons, "Start");
UI_button(data->buttons + 1, "Sandbox");
UI_button(data->buttons + 2, "Continue");
UI_button(data->buttons + 3, "Exit");
EndDrawing();
}
static void exec_component_function(Scene_t* scene, int sel)

View File

@ -98,8 +98,8 @@ 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 = 300;
p_air->decay_rate = 5;
p_air->max_ftimer = 1.0f;
p_air->decay_rate = 1.0f;
CSprite_t* p_cspr = add_component(p_ent, CSPRITE_T);
p_cspr->sprites = player_sprite_map;

View File

@ -105,9 +105,8 @@ bool load_level_tilemap(LevelScene_t* scene, unsigned int level_num)
}
Entity_t* ent = create_crate(&scene->scene.ent_manager, tmp_idx > 5, item);
CTransform_t* p_ct = get_component(ent, CTRANSFORM_COMP_T);
p_ct->position.x = (i % scene->data.tilemap.width) * scene->data.tilemap.tile_size;
p_ct->position.y = (i / scene->data.tilemap.width) * scene->data.tilemap.tile_size;
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;
}
else
{
@ -129,9 +128,8 @@ bool load_level_tilemap(LevelScene_t* scene, unsigned int level_num)
case 20:
{
Entity_t* ent = create_boulder(&scene->scene.ent_manager);
CTransform_t* p_ct = get_component(ent, CTRANSFORM_COMP_T);
p_ct->position.x = (i % scene->data.tilemap.width) * scene->data.tilemap.tile_size;
p_ct->position.y = (i / scene->data.tilemap.width) * scene->data.tilemap.tile_size;
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;
}
break;
case 21:
@ -142,10 +140,9 @@ bool load_level_tilemap(LevelScene_t* scene, unsigned int level_num)
case 22:
{
Entity_t* ent = create_player(&scene->scene.ent_manager);
CTransform_t* p_ct = get_component(ent, CTRANSFORM_COMP_T);
p_ct->position.x = (i % scene->data.tilemap.width) * scene->data.tilemap.tile_size;
p_ct->position.y = (i / scene->data.tilemap.width) * scene->data.tilemap.tile_size;
ent->spawn_pos = p_ct->position;
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;
ent->spawn_pos = ent->position;
}
break;
default:

View File

@ -223,9 +223,8 @@ void update_water_runner_system(Scene_t* scene)
while (move_left)
{
p_crunner->current_tile = p_crunner->bfs_tilemap.tilemap[p_crunner->current_tile].to;
CTransform_t* p_ct = get_component(ent, CTRANSFORM_COMP_T);
p_ct->position.x = (p_crunner->current_tile % tilemap.width) * tilemap.tile_size;
p_ct->position.y = (p_crunner->current_tile / tilemap.width) * tilemap.tile_size;
ent->position.x = (p_crunner->current_tile % tilemap.width) * tilemap.tile_size;
ent->position.y = (p_crunner->current_tile / tilemap.width) * tilemap.tile_size;
Tile_t* tile = tilemap.tiles + p_crunner->current_tile;
tile->wet = true;
@ -290,6 +289,11 @@ void update_water_runner_system(Scene_t* scene)
break;
case SCANLINE_FILL:
{
const float FILL_RATE = 1.0f/24;
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;

View File

@ -108,7 +108,7 @@ static void level_scene_render_func(Scene_t* scene)
const SpriteRenderInfo_t spr = p_cspr->sprites[p_cspr->current_idx];
if (spr.sprite != NULL)
{
Vector2 pos = Vector2Add(p_ct->position, spr.offset);
Vector2 pos = Vector2Add(p_ent->position, spr.offset);
draw_sprite(spr.sprite, p_cspr->current_frame, pos, 0.0f, p_cspr->flip_x);
}
}
@ -318,8 +318,8 @@ static void toggle_block_system(Scene_t* scene)
if (p_ent == NULL) return;
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
p_ct->position.x = (tile_idx % tilemap.width) * tilemap.tile_size;
p_ct->position.y = (tile_idx / tilemap.width) * tilemap.tile_size;
p_ent->position.x = (tile_idx % tilemap.width) * tilemap.tile_size;
p_ent->position.y = (tile_idx / tilemap.width) * tilemap.tile_size;
}
else
{
@ -451,10 +451,14 @@ int main(void)
sc_map_put_64(&scene.scene.action_map, KEY_P, ACTION_METAL_TOGGLE);
const float DT = 1.0f/60.0f;
while(true)
{
float frame_time = GetFrameTime();
float delta_time = fminf(frame_time, DT);
process_inputs(&engine, &scene.scene);
update_scene(&scene.scene);
update_scene(&scene.scene, delta_time);
update_entity_manager(&scene.scene.ent_manager);
// This is needed to advance time delta
render_scene(&scene.scene);