291 lines
7.1 KiB
C
291 lines
7.1 KiB
C
|
#include "player.h"
|
||
|
#include "attack.h"
|
||
|
#include "level.h"
|
||
|
#include "conf.h"
|
||
|
#include "tools.h"
|
||
|
#include "lzy.h"
|
||
|
#include "particle.h"
|
||
|
|
||
|
static struct Player player;
|
||
|
static void player_move(struct Vec2 spd);
|
||
|
static struct Vec2 player_update_rem();
|
||
|
static int player_collide_pixel(int x, int y, tile_t id);
|
||
|
static int player_collide(int x, int y, tile_t id, int h);
|
||
|
static void player_attack(int x, int y, int type);
|
||
|
static void player_cooldown_update();
|
||
|
static int jump_pressed;
|
||
|
|
||
|
void
|
||
|
player_init(int chara)
|
||
|
{
|
||
|
player.pos = (struct Vec2){84, 96};
|
||
|
player.spd = (struct FVec2){0.0f, 0.0f};
|
||
|
player.rem = (struct FVec2){0.0f, 0.0f};
|
||
|
player.dir = (struct Vec2){1, 0};
|
||
|
player.cooldown = (struct Cooldown){0, 0, 0, 0};
|
||
|
player.attack = 0;
|
||
|
player.last_attack = 0;
|
||
|
player.life = 0;
|
||
|
player.id = chara;
|
||
|
player.djump = 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
player_update(void)
|
||
|
{
|
||
|
const int on_ground = player_collide(player.pos.x, player.pos.y + 5, 1, 4);
|
||
|
if(on_ground) player.djump = 1;
|
||
|
|
||
|
const struct Vec2 level_dim = level_get_dim();
|
||
|
|
||
|
const struct Vec2 dir = {LZY_KeyDown(LZYK_RIGHT) - LZY_KeyDown(LZYK_LEFT),
|
||
|
LZY_KeyDown(LZYK_DOWN) - LZY_KeyDown(LZYK_UP)};
|
||
|
|
||
|
player.spd.x *= (1 - PLAYER_FRIC);
|
||
|
player.spd.x += dir.x * PLAYER_ACC;
|
||
|
player.spd.y += GRAVITY * (player.last_attack == 4 && player.id == 1 ? -1 : 1);
|
||
|
|
||
|
/* direction */
|
||
|
if (dir.y) {
|
||
|
player.dir.y = dir.y;
|
||
|
}
|
||
|
if (dir.x) {
|
||
|
player.dir.x = dir.x;
|
||
|
}
|
||
|
|
||
|
if (LZY_KeyDown(LZYK_O)) {
|
||
|
if(on_ground) {
|
||
|
player.spd.y = -JUMP_H;
|
||
|
jump_pressed = 1;
|
||
|
}
|
||
|
else if(player.djump && !jump_pressed) {
|
||
|
player.spd.y = -JUMP_H;
|
||
|
player.djump = 0;
|
||
|
particle_new(player.pos.x + PLAYER_W / 2, player.pos.y + PLAYER_H, 10, 5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (jump_pressed && !LZY_KeyDown(LZYK_O)) {
|
||
|
jump_pressed = 0;
|
||
|
}
|
||
|
|
||
|
if (player_collide(player.pos.x, player.pos.y + 5, 176, 4)) {
|
||
|
player.spd.y = -16;
|
||
|
}
|
||
|
|
||
|
if (player_collide(player.pos.x, player.pos.y + 5, 153, 4)) {
|
||
|
player.spd.y = -3 * 5 * (player.life > 50 ? (float)player.life / 100 + 0.5 : 1);
|
||
|
player.spd.x = -player.dir.x * 5 * (player.life > 50 ? (float)player.life / 100 + 0.5 : 1);
|
||
|
player.life += 10;
|
||
|
}
|
||
|
|
||
|
player_move(player_update_rem());
|
||
|
|
||
|
/* defining the direction of the shoot */
|
||
|
const struct Vec2 shoot = {
|
||
|
(dir.x || dir.y) ? dir.x : player.dir.x,
|
||
|
(dir.x || dir.y) ? dir.y : player.dir.y
|
||
|
};
|
||
|
|
||
|
if (LZY_KeyDown(LZYK_X) && !player.last_attack) {
|
||
|
player_attack(player.pos.x, player.pos.y, 1);
|
||
|
}
|
||
|
|
||
|
if (!LZY_KeyDown(LZYK_X)) {
|
||
|
player.last_attack = 0;
|
||
|
}
|
||
|
|
||
|
player_cooldown_update();
|
||
|
|
||
|
if(player.pos.x > level_dim.x * TILE_S + 48 || player.pos.x < -72 ||
|
||
|
player.pos.y > level_dim.y * TILE_S + 48 || player.pos.y < -96) {
|
||
|
player_init(player.id);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void player_attack(int x, int y, int type) {
|
||
|
const int up = LZY_KeyDown(LZYK_UP);
|
||
|
const int down = LZY_KeyDown(LZYK_DOWN);
|
||
|
const int left = LZY_KeyDown(LZYK_LEFT);
|
||
|
const int right = LZY_KeyDown(LZYK_RIGHT);
|
||
|
if(down && !player.cooldown.down) {
|
||
|
player.cooldown.down = attack(x + PLAYER_W / 2,
|
||
|
y + PLAYER_H / 2 + 12, player.dir.x, 1, 2 + player.id * 4);
|
||
|
player.attack = 2;
|
||
|
player.last_attack = 2;
|
||
|
return;
|
||
|
}
|
||
|
if(up && !player.cooldown.up) {
|
||
|
player.cooldown.up = attack(x + PLAYER_W / 2,
|
||
|
y + PLAYER_H / 2 - 12, player.dir.x, 1, 3 + player.id * 4);
|
||
|
player.attack = 3;
|
||
|
player.last_attack = 3;
|
||
|
return;
|
||
|
}
|
||
|
if((left || right) && !player.cooldown.side) {
|
||
|
player.cooldown.side = attack(x + PLAYER_W / 2 + player.dir.x * 12,
|
||
|
y + PLAYER_H / 2, player.dir.x, 1, 1 + player.id * 4);
|
||
|
player.attack = 1;
|
||
|
player.last_attack = 1;
|
||
|
return;
|
||
|
}
|
||
|
if(!(up || down || left || right) && !player.cooldown.neutral) {
|
||
|
player.cooldown.neutral = attack(x + PLAYER_W / 2,
|
||
|
y + PLAYER_H / 2, player.dir.x, 1, 4 + player.id * 4);
|
||
|
player.attack = 4;
|
||
|
player.last_attack = 4;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static struct Vec2
|
||
|
player_update_rem(void)
|
||
|
{
|
||
|
struct FVec2 spdrem = (struct FVec2){player.spd.x + player.rem.x,
|
||
|
player.spd.y + player.rem.y};
|
||
|
struct Vec2 ispd = (struct Vec2){spdrem.x, spdrem.y};
|
||
|
|
||
|
player.rem.x = spdrem.x - (float)ispd.x;
|
||
|
player.rem.y = spdrem.y - (float)ispd.y;
|
||
|
return ispd;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
player_move(struct Vec2 spd)
|
||
|
{
|
||
|
if (player_collide(player.pos.x, player.pos.y, 1, 4)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int coll_shift = 0;
|
||
|
|
||
|
const int sign_x = sign(spd.x);
|
||
|
if (sign_x) {player.dir.x = sign_x;}
|
||
|
|
||
|
if (spd.x) {
|
||
|
player.pos.x += spd.x;
|
||
|
|
||
|
if (player_collide(player.pos.x, player.pos.y, 1, 1)) {
|
||
|
for(float i = 0.1f; i < 4; i+= 0.1) {
|
||
|
if(!player_collide(player.pos.x, player.pos.y + i, 1, 1)) {
|
||
|
player.pos.y += i;
|
||
|
coll_shift = 1;
|
||
|
break;
|
||
|
}
|
||
|
if(!player_collide(player.pos.x, player.pos.y - i, 1, 1)) {
|
||
|
player.pos.y -= i;
|
||
|
coll_shift = 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(player_collide(player.pos.x, player.pos.y, 1, 1)) {
|
||
|
player.spd.x = 0.0f;
|
||
|
player.rem.x = 0.0f;
|
||
|
while (player_collide(player.pos.x, player.pos.y, 1, 1)) {
|
||
|
player.pos.x -= sign_x;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const int sign_y = sign(spd.y);
|
||
|
if (sign_y) {player.dir.y = sign_y;}
|
||
|
|
||
|
if (spd.y && !coll_shift) {
|
||
|
player.pos.y += spd.y;
|
||
|
|
||
|
if (player_collide(player.pos.x, player.pos.y, 1, 1)) {
|
||
|
for(float i = 0.1f; i < 4; i += 0.1) {
|
||
|
if(!player_collide(player.pos.x + i, player.pos.y, 1, 1)) {
|
||
|
player.pos.x += i;
|
||
|
break;
|
||
|
}
|
||
|
if(!player_collide(player.pos.x - i, player.pos.y, 1, 1)) {
|
||
|
player.pos.x -= i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(player_collide(player.pos.x, player.pos.y, 1, 1)) {
|
||
|
player.spd.y = 0.0f;
|
||
|
player.rem.y = 0.0f;
|
||
|
while (player_collide(player.pos.x, player.pos.y, 1, 1)) {
|
||
|
player.pos.y -= sign_y;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
player_draw(int frame)
|
||
|
{
|
||
|
if(player.attack) {
|
||
|
LZY_DrawTile(24 + TILESET_W * player.id + player.attack + (player.dir.x > 0 ? 0 : 1) * 6,
|
||
|
player.pos.x, player.pos.y);
|
||
|
} else {
|
||
|
if(LZY_KeyDown(LZYK_X)) {
|
||
|
LZY_DrawTile(24 + player.last_attack + TILESET_W * player.id
|
||
|
+ (player.dir.x > 0 ? 0 : 1) * 6,
|
||
|
player.pos.x, player.pos.y);
|
||
|
} else {
|
||
|
LZY_DrawTile((frame % 30 > 15 ? 23 : 24) + TILESET_W * player.id
|
||
|
+ (player.dir.x > 0 ? 0 : 1) * 6,
|
||
|
player.pos.x, player.pos.y);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
player_collide_pixel(int x, int y, tile_t id)
|
||
|
{
|
||
|
const tile_t tile = level_get_px(x, y);
|
||
|
|
||
|
if (!tile) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (id == 1) {
|
||
|
return (tile) % TILESET_W;
|
||
|
}
|
||
|
|
||
|
return tile == id;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
player_collide(int x, int y, tile_t id, int h)
|
||
|
{
|
||
|
|
||
|
const struct Vec2 pos_tl = (struct Vec2){x + h, y + h};
|
||
|
const struct Vec2 pos_br =
|
||
|
(struct Vec2){x + PLAYER_S - h - 1, y + PLAYER_S - h - 1};
|
||
|
const struct Vec2 middle =
|
||
|
(struct Vec2){x + PLAYER_S / 2, y + PLAYER_S / 2};
|
||
|
|
||
|
if (player_collide_pixel(pos_tl.x, pos_tl.y, id) ||
|
||
|
player_collide_pixel(pos_br.x, pos_br.y, id) ||
|
||
|
player_collide_pixel(pos_tl.x, pos_br.y, id) ||
|
||
|
player_collide_pixel(pos_br.x, pos_tl.y, id)) {
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
player_reset_attack() {
|
||
|
player.attack = 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
player_cooldown_update() {
|
||
|
if (player.cooldown.up > 0) player.cooldown.up -= 1;
|
||
|
if (player.cooldown.down > 0) player.cooldown.down -= 1;
|
||
|
if (player.cooldown.side > 0) player.cooldown.side -= 1;
|
||
|
if (player.cooldown.neutral > 0) player.cooldown.neutral -= 1;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
player_get_life(void) {
|
||
|
return player.life;
|
||
|
}
|