/* SPDX-License-Identifier: GPL-3.0-or-later */ /* Copyright (C) 2021 KikooDX */ #include "conf.h" #include "level.h" #include "particles.h" #include "player.h" #include "tiles.h" #include extern struct Level level; extern img_t img_coin_particle; extern img_t img_switch_particle; extern img_t img_switch_activated_particle; extern img_t img_exit_active_particle; extern img_t img_exit_unlock_particle; static Tile collide_single(int x, int y); static int collide_sub_single(int x, int y, Tile sub, Tile rep); void player_collide(Tile collisions[COLLIDE_POINTS], int x, int y, int margin) { const int lx = x + margin; const int rx = x + PLAYER_WIDTH - 1 - margin; const int ty = y + margin; const int dy = y + PLAYER_HEIGHT - 1 - margin; collisions[UP_LEFT] = collide_single(lx, ty); collisions[UP_RIGHT] = collide_single(rx, ty); collisions[DOWN_LEFT] = collide_single(lx, dy); collisions[DOWN_RIGHT] = collide_single(rx, dy); } int player_collide_tile(Tile collisions[COLLIDE_POINTS], int x, int y, Tile tile, int margin, int update) { if (update) player_collide(collisions, x, y, margin); int i = COLLIDE_POINTS; while (i-- > 0) if (collisions[i] == tile) return 1; return 0; } /* collide and replace tiles, return the number of tiles affecter */ int player_collide_sub(int x, int y, Tile sub, Tile rep, int margin) { const int lx = x + margin; const int rx = x + PLAYER_WIDTH - 1 - margin; const int ty = y + margin; const int dy = y + PLAYER_HEIGHT - 1 - margin; return collide_sub_single(lx, ty, sub, rep) + collide_sub_single(rx, ty, sub, rep) + collide_sub_single(lx, dy, sub, rep) + collide_sub_single(rx, dy, sub, rep); } int player_collide_solid(int x, int y) { Tile collisions[COLLIDE_POINTS]; return player_collide_tile(collisions, x, y, TILE_SOLID, 0, 1); } static Tile collide_single(int x, int y) { const int tx = x / TILE_WIDTH; const int ty = y / TILE_WIDTH; return level_get_tile(tx, ty); } /* try collide and replace tile at pixel position, return 1 if tile * replaced */ static int collide_sub_single(int x, int y, Tile sub, Tile rep) { if (collide_single(x, y) == sub) { const int tile_index = (int)(x / TILE_WIDTH) + (int)(y / TILE_WIDTH) * level.width; const int px = (int)(x / TILE_WIDTH) * TILE_WIDTH; const int py = (int)(y / TILE_HEIGHT) * TILE_HEIGHT; /* replace tile */ level.data[tile_index] = rep; if (rep == TILE_VOID) level.visual_data[tile_index].visible = 0; /* spawn animations */ switch (sub) { case TILE_GOLD: particle_create(&img_coin_particle, px, py, TILE_WIDTH, 2, 0, 0); break; case TILE_SWITCH: /* still image */ particle_create(&img_switch_activated_particle, px, py, TILE_WIDTH, 1, 1, 0); /* activation animation */ particle_create(&img_switch_particle, px, py, TILE_WIDTH, 8, 0, 0); /* exit unlock animation */ { int ty = level.height; int tx = 0; while (ty-- > 0) { tx = level.width; while (tx-- > 0) { if (level.data [tx + ty * level.width] == TILE_EXIT) goto found; } } found: tx *= TILE_WIDTH; ty *= TILE_HEIGHT; particle_create(&img_exit_active_particle, tx, ty, TILE_WIDTH, 2, 1, 0); particle_create(&img_exit_unlock_particle, tx, ty, TILE_WIDTH, 4, 0, 0); } break; default: break; } return 1; } return 0; }