From 2fbdf974338bde8576efdae40a819a76b2391033 Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Sun, 5 Nov 2023 11:22:55 +0000 Subject: Initial import of the open source release --- src/et_player.c | 551 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 551 insertions(+) create mode 100644 src/et_player.c (limited to 'src/et_player.c') diff --git a/src/et_player.c b/src/et_player.c new file mode 100644 index 0000000..d58d656 --- /dev/null +++ b/src/et_player.c @@ -0,0 +1,551 @@ +/* + Kitsune's Curse + Copyright (C) 2020-2023 Juan J. Martinez + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include + +#include "cpcrslib/cpcrslib.h" +#include "splib.h" +#include "plw.h" +#include "sound.h" +#include "main.h" + +#include "maps.h" +#include "stage.h" + +// generated +#include "player.h" +#include "explo.h" + +#include "entities.h" +#include "et_effect.h" + +#define LOCAL +#include "et_player.h" + +void player_checkpoint() +{ +#ifdef DEBUG + char b[4]; +#endif + + // don't do it if not solid or platform + if (is_map_blocked(px + 3, py + 24) == 1) + { + smap = cmap; + spx = px; + spy = py; + sdir = dir; + +#ifdef DEBUG + set_text_ink(15, 15, 15); + put_text("C", 10, 192); + pad_numbers(b, 3, px); + put_text(b, 13, 192); + pad_numbers(b, 3, py); + put_text(b, 20, 192); +#endif + } +} + +void player_hit(uint8_t h) +{ + life = life > h ? life - h : 0; + if (!life) + { + // dead + + // instant death cases control the frame + // otherwise set it here + if (h != MAX_LIFE) + frame = WALK + 1; + + erase_sprite(px, py, 3); + was_hit = 0; + respawn_delay = RESPAWN_DELAY; + + // not water + if (last_deadly != DEADLY_TILE_BASE) + PLW_PlaySoundEffectP(EFX_DEATH); + + if (lives == 1) + PLW_Init(songs, SONG_SILENCE); + } + else + { + // only hit + was_hit = WAS_HIT; + + if (*it_x > px) + dir = DIR_RIGHT; + else + dir = DIR_LEFT; + + PLW_PlaySoundEffectP(EFX_DAMAGE); + } + + draw_hud(); +} + +void draw_player() +{ + if ((!was_hit || was_hit & 2) && !magic && life) + put_sprite4(player[player_frames[frame]], px, py, 3, dir); + else if (magic) + put_sprite4(explo[2], px, py + 6, 2, magic & 1); + + if (!life && frame && respawn_delay > 2 && respawn_delay & 2) + put_sprite4(player[player_frames[frame]], px, py, 3, dir); + + erase_sprite(opx, opy, 3); + + opx = px; + opy = py; +} + +void update_player() +{ + // help is_map_blocked + sp_it = NULL; + moved = 0; + + if (respawn_delay) + { + if (--respawn_delay) + return; + + --lives; + life = lives ? MAX_LIFE : 0; + draw_hud(); + + if (!lives) + { + gameover_delay = GAMEOVER_DELAY; + return; + } + + if (cmap != smap) + init_map(smap); + px = spx; + py = spy; + dir = sdir; + frame = WALK; + player_h = 0; + was_hit = RESPAWN_DELAY; + return; + } + + if (!lives) + return; + + if (was_hit) + { + --was_hit; + + // jump after being hit + if (was_hit == WAS_HIT - 1) + { + jump_flag = 1; + player_h = 2; + } + + // jump back after being hit + if (was_hit > RESPAWN_DELAY) + { + moved = 1; + frame = WALK + 1; + + if (dir) + { + if (px < TW * TMW - 8 + && !is_map_blocked(px + 8, py + 23) + && !is_map_blocked(px + 8, py + (player_h ? 6 : 0))) + px += 2; + + if (px == TW * TMW - 8 && exit_map_right()) + return; + } + else + { + if (px > 0 + && !is_map_blocked(px - 1, py + 23) + && !is_map_blocked(px - 1, py + (player_h ? 6 : 0))) + px -= 2; + + if (!px && exit_map_left()) + return; + } + } + } + + // check for gravity + if (!player_h + && !is_map_blocked(px + 1, py + 24) + && !is_map_blocked(px + 6, py + 24)) + { + // start falling + player_h = JUMP_SEQ - 2; + frame = JUMP; + moved = 1; + } + + if (cpc_TestKeyF(KEY_DOWN) && frame != JUMP) + { + if (frame != CROUCH) + frame = CROUCH; + } + else + { + // wake up + if (frame == CROUCH) + frame = WALK; + } + + if (cpc_TestKeyF(KEY_UP)) + { + if (!player_h && !jump_flag + // no magic or magic just started + && (!magic || magic > COOL_DOWN - 2)) + { + jump_flag = 1; + player_h = 1; + frame = JUMP; + } + } + else + { + // faster than always set to 0 + if (jump_flag) + jump_flag = 0; + } + + if (cpc_TestKeyF(KEY_RIGHT) && !cpc_TestKeyF(KEY_LEFT)) + { + if (dir) + dir = DIR_RIGHT; + + if (frame != CROUCH) + { + moved = 1; + + if (px < TW * TMW - 8 + && !is_map_blocked(px + 8, py + 23) + && !is_map_blocked(px + 8, py + (player_h ? 6 : 0))) + px += 2; + + if (magic && px < TW * TMW - 8 + && !is_map_blocked(px + 8, py + 23) + && !is_map_blocked(px + 8, py + (player_h ? 6 : 0))) + px += 2; + + if (px == TW * TMW - 8 && exit_map_right()) + return; + } + } + + if (cpc_TestKeyF(KEY_LEFT) && !cpc_TestKeyF(KEY_RIGHT)) + { + if (!dir) + dir = DIR_LEFT; + + if (frame != CROUCH) + { + moved = 1; + + if (px > 0 + && !is_map_blocked(px - 1, py + 23) + && !is_map_blocked(px - 1, py + (player_h ? 6 : 0))) + px -= 2; + + if (magic && px > 0 + && !is_map_blocked(px - 1, py + 23) + && !is_map_blocked(px - 1, py + (player_h ? 6 : 0))) + px -= 2; + + if (!px && exit_map_left()) + return; + } + } + + if (magic) + { + if (magic-- == 2) + new_explo(); + + if (!magic + && (is_map_deadly(px + 3, py + 24) + || is_map_deadly(px + 3, py + (frame == CROUCH ? 6 : 0)) + )) + { + if (last_deadly == DEADLY_TILE_BASE) + { + frame = 0; + new_splash(); + } + else + frame = WALK + 1; + player_hit(MAX_LIFE); + return; + } + } + else + { + if (cool_down) + --cool_down; + + if (cpc_TestKeyF(KEY_FIRE) && !cool_down) + { + magic = COOL_DOWN; + cool_down = COOL_DOWN + 2; + new_explo(); + } + } + + if (player_h) + { + // jumping + it_k = jump_seq[player_h - 1]; + + if (IS_GOING_DOWN(player_h)) + { + // down + while (it_k && py < TH * TMH - 24) + { + // potentially hit floor + if ((is_map_blocked(px + 1, py + 24) + || is_map_blocked(px + 6, py + 24))) + { + // process deadly first + if (is_map_deadly(px + 1, py + 24) + || is_map_deadly(px + 6, py + 24)) + { + if (!magic) + { + if (last_deadly == DEADLY_TILE_BASE) + { + frame = 0; + new_splash(); + } + else + frame = WALK + 1; + player_hit(MAX_LIFE); + } + break; + } + + // avoid getting *inside* the platform + if (!is_map_blocked(px + 1, py + 22) + && !is_map_blocked(px + 6, py + 22)) + { + // hit floor + player_h = 0; + frame = WALK; + + player_checkpoint(); + + if (!magic) + PLW_PlaySoundEffectP(EFX_HIT); + break; + } + } + + py += 2; + it_k -= 2; + } + + if (py == TH * TMH - 24 && exit_map_down()) + return; + } + else + { + // up + while (it_k && py) + { + // jumping back after being hit + if (was_hit > RESPAWN_DELAY) + { + if (is_map_blocked(px + 1, py) + || is_map_blocked(px + 6, py)) + break; + } + + if (is_map_blocked(px + 1, py + 4) + || is_map_blocked(px + 6, py + 4)) + { + if (!magic) + { + if (is_map_deadly(px + 3, py + 4)) + { + frame = WALK + 1; + player_hit(MAX_LIFE); + } + else if (jump_flag == 1) + { + jump_flag = 2; + PLW_PlaySoundEffectP(EFX_HIT); + } + } + break; + } + + py -= 2; + it_k -= 2; + } + + if (py == 0 && exit_map_up()) + return; + } + + if (player_h && player_h < JUMP_SEQ + // extra boost with magic but not first step + && (!(magic & 1) || player_h == 1)) + player_h++; + } + else + { + // not jumping + if (moved) + { + if (!magic && (is_map_deadly(px + 3, py + 24) + || is_map_deadly(px + 3, py))) + { + if (last_deadly == DEADLY_TILE_BASE) + { + frame = 0; + new_splash(); + } + else + frame = WALK + 1; + player_hit(MAX_LIFE); + return; + } + + if (wdelay++) + { + wdelay = 0; + // frame increase + if (frame != JUMP && ++frame > WALK_CYCLE) + frame = WALK; + } + } + else + { + // frame stopped + if (frame > WALK && frame < CROUCH) + { + frame = WALK; + wdelay = 0; + } + } + } +} + +#pragma save +#pragma disable_warning 85 +#pragma disable_warning 59 +uint8_t check_for_player(uint8_t h) __z88dk_fastcall +{ + /* + if (magic || was_hit || !life) + return 0; + + if (frame == CROUCH) + { + if (py + 8 < sp_it->y + h && sp_it->y < py + 24 + && px + 2 < sp_it->x + w && sp_it->x < px + 6) + return 1; + } + else + { + if (py < sp_it->y + h && sp_it->y < py + 24 + && px + 2 < sp_it->x + w && sp_it->x < px + 6) + return 1; + } + + return 0; + */ + + // *INDENT-OFF* + __asm; + ld e, #8 ; w + ld d, l ; h + + ld a, (_magic) + or a + jr nz, check_for_player_false + ld a, (_was_hit) + or a + jr nz, check_for_player_false + ld a, (_life) + or a + jr z, check_for_player_false + + ld hl, (_sp_it) + ld bc, #6 + add hl, bc + ld a, (hl) ; y + add d + ld c, a + + ; b is 0 + ld a, (_frame) + cp #CROUCH + jr nz, not_crouching + + ld b, #8 + + not_crouching: + ld a, (_py) + add a, b + cp c + jr nc, check_for_player_false + + ld a, (_py) + add #24 + ld c, a + + ld a, (hl) ; y + cp c + jr nc, check_for_player_false + + dec hl + dec hl + ld a, (hl) ; x + add e + ld c, a + + ld a, (_px) + add #2 + cp c + jr nc, check_for_player_false + + ld a, (_px) + add #6 + ld c, a + + ld a, (hl) ; x + cp c + jr nc, check_for_player_false + + ld l, #1 + ret + + check_for_player_false: + ld l, #0 + __endasm; +// *INDENT-ON* +} +#pragma restore -- cgit v1.2.3