PCBrawl/src/player.c

280 lines
7.6 KiB
C

#include "player.h"
#include "attack.h"
#include "conf.h"
#include "level.h"
#include "lzy.h"
#include "particle.h"
#include "tools.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; }