Compare commits

...

3 Commits

Author SHA1 Message Date
En Yi 9859854baa Add spawn entity selection via mouse
Changelog:
- Add row below game scene to select spawning entity
- Add mouse release logic to select spawning entity
- Update render order for tile
    - order: 'moveable' -> tile -> water level
2023-06-26 22:57:59 +08:00
En Yi f206d3c981 Update entity spawn + despawn function
Changelog:
- Check for mouse in game pos before mouse click check
- Right click will also remove entities now! Hooray!
2023-06-26 21:27:22 +08:00
En Yi dab8303cbe Update tile spawning
Changelog:
- Right click now removes tiles
- Water has its own spawn selection
2023-06-26 21:08:44 +08:00
1 changed files with 211 additions and 132 deletions

View File

@ -15,14 +15,22 @@ enum EntitySpawnSelection {
TOGGLE_ONEWAY,
TOGGLE_LADDER,
TOGGLE_SPIKE,
TOGGLE_WATER,
SPAWN_CRATE,
SPAWN_METAL_CRATE,
SPAWN_BOULDER,
};
#define MAX_SPAWN_TYPE 7
#define MAX_SPAWN_TYPE 8
static unsigned int current_spawn_selection = 0;
#define SELECTION_TILE_SIZE 32
#define SELECTION_TILE_HALFSIZE (SELECTION_TILE_SIZE >> 1)
#define SELECTION_GAP 5
#define SELECTION_REGION_WIDTH (SELECTION_TILE_SIZE * MAX_SPAWN_TYPE)
#define SELECTION_REGION_HEIGHT SELECTION_TILE_SIZE
static inline unsigned int get_tile_idx(int x, int y, const TileGrid_t* tilemap)
{
unsigned int tile_x = x / TILE_SIZE;
@ -44,6 +52,7 @@ static char* get_spawn_selection_string(enum EntitySpawnSelection sel)
case TOGGLE_ONEWAY: return "wooden tile";
case TOGGLE_LADDER: return "ladder";
case TOGGLE_SPIKE: return "spike";
case TOGGLE_WATER: return "water";
case SPAWN_CRATE: return "wooden crate";
case SPAWN_METAL_CRATE: return "metal crate";
case SPAWN_BOULDER: return "boulder";
@ -68,6 +77,13 @@ static void level_scene_render_func(Scene_t* scene)
int y = (i / tilemap.width) * TILE_SIZE;
sprintf(buffer, "%u", sc_map_size_64v(&tilemap.tiles[i].entities_set));
if (!tilemap.tiles[i].moveable)
{
// Draw water tile
Color water_colour = ColorAlpha(RED, 0.2);
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, water_colour);
}
if (data->tile_sprites[tilemap.tiles[i].tile_type] != NULL)
{
draw_sprite(data->tile_sprites[tilemap.tiles[i].tile_type], (Vector2){x,y}, false);
@ -98,12 +114,6 @@ static void level_scene_render_func(Scene_t* scene)
Color water_colour = ColorAlpha(BLUE, 0.5);
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, water_colour);
}
if (!tilemap.tiles[i].moveable)
{
// Draw water tile
Color water_colour = ColorAlpha(RED, 0.2);
DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, water_colour);
}
}
char buffer[64] = {0};
@ -216,6 +226,49 @@ static void level_scene_render_func(Scene_t* scene)
(Vector2){data->game_rec.x, data->game_rec.y},
WHITE
);
Vector2 draw_pos = {data->game_rec.x, data->game_rec.y + data->game_rec.height + SELECTION_GAP};
const Color draw_colour[MAX_SPAWN_TYPE] = {BLACK, MAROON, ORANGE, ColorAlpha(RAYWHITE, 0.5), ColorAlpha(BLUE, 0.5), BROWN, GRAY, ColorAlpha(RAYWHITE, 0.5)};
for (uint8_t i = 0; i < MAX_SPAWN_TYPE; ++i)
{
if (i != current_spawn_selection)
{
DrawRectangle(draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE, draw_colour[i]);
switch (i)
{
case 3:
DrawRectangle(draw_pos.x, draw_pos.y + SELECTION_TILE_HALFSIZE, SELECTION_TILE_SIZE, SELECTION_TILE_HALFSIZE, RED);
break;
case 7:
{
Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE};
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, GRAY);
}
break;
}
}
draw_pos.x += SELECTION_TILE_SIZE;
}
draw_pos.x = data->game_rec.x + current_spawn_selection * SELECTION_TILE_SIZE;
DrawRectangle(
draw_pos.x - 2, draw_pos.y - 2,
SELECTION_TILE_SIZE + 4, SELECTION_TILE_SIZE + 4, GREEN
);
DrawRectangle(draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE, draw_colour[current_spawn_selection]);
switch (current_spawn_selection)
{
case 3:
DrawRectangle(draw_pos.x, draw_pos.y + SELECTION_TILE_HALFSIZE, SELECTION_TILE_SIZE, SELECTION_TILE_HALFSIZE, RED);
break;
case 7:
{
const Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE};
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, GRAY);
}
break;
}
// For DEBUG
const int gui_x = data->game_rec.x + data->game_rec.width + 10;
sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_ent)
@ -281,125 +334,135 @@ static void toggle_block_system(Scene_t* scene)
Vector2 raw_mouse_pos = {GetMouseX(), GetMouseY()};
raw_mouse_pos = Vector2Subtract(raw_mouse_pos, (Vector2){data->game_rec.x, data->game_rec.y});
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
if (
raw_mouse_pos.x < data->game_rec.width
&& raw_mouse_pos.y < data->game_rec.height
)
{
if (
raw_mouse_pos.x > data->game_rec.width
|| raw_mouse_pos.y > data->game_rec.height
) return;
Vector2 mouse_pos = GetScreenToWorld2D(raw_mouse_pos, data->cam);
unsigned int tile_idx = get_tile_idx(mouse_pos.x, mouse_pos.y, &tilemap);
if (tile_idx >= MAX_N_TILES) return;
enum EntitySpawnSelection sel = (enum EntitySpawnSelection)current_spawn_selection;
if (tile_idx != last_tile_idx)
if (tile_idx == last_tile_idx) return;
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
enum EntitySpawnSelection sel = (enum EntitySpawnSelection)current_spawn_selection;
switch (sel)
{
case TOGGLE_TILE:
if (tilemap.tiles[tile_idx].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
tilemap.tiles[tile_idx].solid = NOT_SOLID;
}
else
{
tilemap.tiles[tile_idx].tile_type = SOLID_TILE;
tilemap.tiles[tile_idx].solid = SOLID;
}
tilemap.tiles[tile_idx].water_level = 0;
break;
case TOGGLE_ONEWAY:
if (tilemap.tiles[tile_idx].tile_type == ONEWAY_TILE)
{
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
tilemap.tiles[tile_idx].solid = NOT_SOLID;
}
else
{
tilemap.tiles[tile_idx].tile_type = ONEWAY_TILE;
tilemap.tiles[tile_idx].solid = ONE_WAY;
}
break;
case TOGGLE_LADDER:
if (tilemap.tiles[tile_idx].tile_type == LADDER)
{
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
tilemap.tiles[tile_idx].solid = NOT_SOLID;
}
else
{
tilemap.tiles[tile_idx].tile_type = LADDER;
int up_tile = tile_idx - tilemap.width;
if (up_tile > 0 && tilemap.tiles[up_tile].tile_type != LADDER)
{
tilemap.tiles[tile_idx].solid = ONE_WAY;
}
else
{
tilemap.tiles[tile_idx].solid = NOT_SOLID;
}
}
int down_tile = tile_idx + tilemap.width;
if (down_tile < MAX_N_TILES && tilemap.tiles[down_tile].tile_type == LADDER)
{
tilemap.tiles[down_tile].solid = (tilemap.tiles[tile_idx].tile_type != LADDER)? ONE_WAY : NOT_SOLID;
}
break;
case TOGGLE_SPIKE:
if (tilemap.tiles[tile_idx].tile_type == SPIKES)
{
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
}
else
{
tilemap.tiles[tile_idx].tile_type = SPIKES;
}
case TOGGLE_TILE:
if (tilemap.tiles[tile_idx].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
tilemap.tiles[tile_idx].solid = NOT_SOLID;
break;
case SPAWN_CRATE:
spawn_crate(scene, tile_idx, false);
break;
case SPAWN_METAL_CRATE:
spawn_crate(scene, tile_idx, true);
break;
case SPAWN_BOULDER:
spawn_boulder(scene, tile_idx);
break;
}
if (tilemap.tiles[tile_idx].tile_type == SPIKES)
{
// Priority: Down, Up, Left, Right
if (tile_idx + tilemap.width < MAX_N_TILES && tilemap.tiles[tile_idx + tilemap.width].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].offset = (Vector2){0,16};
tilemap.tiles[tile_idx].size = (Vector2){32,16};
}
else if (tile_idx - tilemap.width >= 0 && tilemap.tiles[tile_idx - tilemap.width].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].offset = (Vector2){0,0};
tilemap.tiles[tile_idx].size = (Vector2){32,16};
}
else if (tile_idx % tilemap.width != 0 && tilemap.tiles[tile_idx - 1].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].offset = (Vector2){0,0};
tilemap.tiles[tile_idx].size = (Vector2){16,32};
}
else if ((tile_idx + 1) % tilemap.width != 0 && tilemap.tiles[tile_idx + 1].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].offset = (Vector2){16,0};
tilemap.tiles[tile_idx].size = (Vector2){16,32};
}
else
{
tilemap.tiles[tile_idx].offset = (Vector2){0,16};
tilemap.tiles[tile_idx].size = (Vector2){32,16};
tilemap.tiles[tile_idx].tile_type = SOLID_TILE;
tilemap.tiles[tile_idx].solid = SOLID;
}
tilemap.tiles[tile_idx].water_level = 0;
break;
case TOGGLE_ONEWAY:
if (tilemap.tiles[tile_idx].tile_type == ONEWAY_TILE)
{
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
tilemap.tiles[tile_idx].solid = NOT_SOLID;
}
else
{
tilemap.tiles[tile_idx].tile_type = ONEWAY_TILE;
tilemap.tiles[tile_idx].solid = ONE_WAY;
}
break;
case TOGGLE_LADDER:
if (tilemap.tiles[tile_idx].tile_type == LADDER)
{
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
tilemap.tiles[tile_idx].solid = NOT_SOLID;
}
else
{
tilemap.tiles[tile_idx].tile_type = LADDER;
int up_tile = tile_idx - tilemap.width;
if (up_tile > 0 && tilemap.tiles[up_tile].tile_type != LADDER)
{
tilemap.tiles[tile_idx].solid = ONE_WAY;
}
else
{
tilemap.tiles[tile_idx].solid = NOT_SOLID;
}
}
int down_tile = tile_idx + tilemap.width;
if (down_tile < MAX_N_TILES && tilemap.tiles[down_tile].tile_type == LADDER)
{
tilemap.tiles[down_tile].solid = (tilemap.tiles[tile_idx].tile_type != LADDER)? ONE_WAY : NOT_SOLID;
}
break;
case TOGGLE_SPIKE:
if (tilemap.tiles[tile_idx].tile_type == SPIKES)
{
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
}
else
{
tilemap.tiles[tile_idx].tile_type = SPIKES;
}
tilemap.tiles[tile_idx].solid = NOT_SOLID;
break;
case TOGGLE_WATER:
if (tilemap.tiles[tile_idx].water_level == 0)
{
tilemap.tiles[tile_idx].water_level = MAX_WATER_LEVEL;
}
else
{
tilemap.tiles[tile_idx].water_level = 0;
}
break;
case SPAWN_CRATE:
spawn_crate(scene, tile_idx, false);
break;
case SPAWN_METAL_CRATE:
spawn_crate(scene, tile_idx, true);
break;
case SPAWN_BOULDER:
spawn_boulder(scene, tile_idx);
break;
}
if (tilemap.tiles[tile_idx].tile_type == SPIKES)
{
// Priority: Down, Up, Left, Right
if (tile_idx + tilemap.width < MAX_N_TILES && tilemap.tiles[tile_idx + tilemap.width].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].offset = (Vector2){0,16};
tilemap.tiles[tile_idx].size = (Vector2){32,16};
}
else if (tile_idx - tilemap.width >= 0 && tilemap.tiles[tile_idx - tilemap.width].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].offset = (Vector2){0,0};
tilemap.tiles[tile_idx].size = (Vector2){32,16};
}
else if (tile_idx % tilemap.width != 0 && tilemap.tiles[tile_idx - 1].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].offset = (Vector2){0,0};
tilemap.tiles[tile_idx].size = (Vector2){16,32};
}
else if ((tile_idx + 1) % tilemap.width != 0 && tilemap.tiles[tile_idx + 1].tile_type == SOLID_TILE)
{
tilemap.tiles[tile_idx].offset = (Vector2){16,0};
tilemap.tiles[tile_idx].size = (Vector2){16,32};
}
else
{
tilemap.tiles[tile_idx].offset = (Vector2){0,0};
tilemap.tiles[tile_idx].size = (Vector2){32,32};
tilemap.tiles[tile_idx].offset = (Vector2){0,16};
tilemap.tiles[tile_idx].size = (Vector2){32,16};
}
}
else
{
tilemap.tiles[tile_idx].offset = (Vector2){0,0};
tilemap.tiles[tile_idx].size = (Vector2){32,32};
}
last_tile_idx = tile_idx;
tilemap.tiles[tile_idx].moveable = (
@ -407,33 +470,49 @@ static void toggle_block_system(Scene_t* scene)
|| tilemap.tiles[tile_idx].tile_type == SPIKES
);
}
}
else if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON))
{
if (
raw_mouse_pos.x > data->game_rec.width
|| raw_mouse_pos.y > data->game_rec.height
) return;
Vector2 mouse_pos = GetScreenToWorld2D(raw_mouse_pos, data->cam);
unsigned int tile_idx = get_tile_idx(mouse_pos.x, mouse_pos.y, &tilemap);
if (tile_idx >= MAX_N_TILES) return;
if (tile_idx != last_tile_idx)
else if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON))
{
if (tilemap.tiles[tile_idx].water_level == 0)
tilemap.tiles[tile_idx].tile_type = EMPTY_TILE;
tilemap.tiles[tile_idx].solid = NOT_SOLID;
tilemap.tiles[tile_idx].water_level = 0;
tilemap.tiles[tile_idx].moveable = true;
Entity_t* ent;
unsigned int m_id;
sc_map_foreach(&tilemap.tiles[tile_idx].entities_set, m_id, ent)
{
tilemap.tiles[tile_idx].water_level = MAX_WATER_LEVEL;
if (ent->m_tag == PLAYER_ENT_TAG) continue;
CTileCoord_t* p_tilecoord = get_component(
ent, CTILECOORD_COMP_T
);
for (size_t i = 0;i < p_tilecoord->n_tiles; ++i)
{
// Use previously store tile position
// Clear from those positions
unsigned int tile_idx = p_tilecoord->tiles[i];
sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), m_id);
}
remove_entity(&scene->ent_manager, m_id);
}
else
{
tilemap.tiles[tile_idx].water_level = 0;
}
last_tile_idx = tile_idx;
}
else
{
last_tile_idx = MAX_N_TILES;
}
return;
}
else
raw_mouse_pos = Vector2Subtract(raw_mouse_pos, (Vector2){0, data->game_rec.height});
if (
raw_mouse_pos.x < SELECTION_REGION_WIDTH
&& raw_mouse_pos.y < SELECTION_REGION_HEIGHT
)
{
last_tile_idx = MAX_N_TILES;
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
{
current_spawn_selection = ((int)raw_mouse_pos.x / SELECTION_TILE_SIZE);
}
}
}