mirror of https://git.sr.ht/~kikoodx/momento
138 lines
3.5 KiB
C
138 lines
3.5 KiB
C
/* 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 <gint/display.h>
|
|
|
|
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;
|
|
}
|