function player_move_and_collide() { if global.hitstop > 0 return; y_spd *= global.time_scale; x_spd *= global.time_scale; if place_meeting(x, y + y_spd, oParentSolid) { while !place_meeting(x, y + sign(y_spd), oParentSolid) y += sign(y_spd); y_spd = 0; } y += y_spd; if place_meeting(x + x_spd, y, oParentSolid) { var _max_step = (y_spd == 0) ? 16 : 8; //前者地面容错,后者空中容错 var _stepped = false; for(var i = 0; i < _max_step; i++) if !place_meeting(x + x_spd, y - i, oParentSolid) { y -= i; _stepped = true; break; } if !_stepped { while !place_meeting(x + sign(x_spd), y, oParentSolid) x += sign(x_spd); x_spd = 0; } } x += x_spd; y_spd /= global.time_scale; x_spd /= global.time_scale; } function player_status_update() { global.playerHP = clamp(global.playerHP, 0, global.save_data.player.maxHP); global.playerINK = clamp(global.playerINK, 0, global.save_data.player.maxINK); current_attacker = instance_place(x, y, oEnemyHitbox); current_hazard = instance_place(x, y, oParentHazard); current_door = instance_place(x, y, oDoor); if state != state_attack && instance_exists(current_hb) instance_destroy(current_hb); if !instance_exists(current_hb) current_hb = noone; if state != state_focus INK_blend = 0; image_index += animation_spd; if oMain._dash dash_buffer = dash_buffer_max; if oMain._attack attack_buffer = attack_buffer_max; if oMain._jump_p jump_buffer_timer = jump_buffer_max; _move_dir = oMain._right - oMain._left; _on_ground = place_meeting(x, y + 1, oParentSolid) _on_wall = place_meeting(x + 1, y, oBlockClimbable) - place_meeting(x - 1, y, oBlockClimbable); var _no_cliff = place_meeting(x - sprite_width, y + 1, oParentSolid) && place_meeting(x + sprite_width, y + 1, oParentSolid) var _no_hazard = !(place_meeting(x - sprite_width, y, oParentHazard) || place_meeting(x + sprite_width, y, oParentHazard)) if _on_ground && _no_cliff && _no_hazard { last_safe_x = x; last_safe_y = y; } if _on_ground || (_on_wall != 0) can_dash = true; if _on_ground { jump_cnt = 0; coyote_timer = coyote_max; } else if coyote_timer <= 0 && jump_cnt == 0 jump_cnt = 1; if dash_cooldown > 0 dash_cooldown -= global.time_scale; if dash_buffer > 0 dash_buffer -= global.time_scale; if attack_buffer > 0 attack_buffer -= global.time_scale; if move_lock_timer > 0 move_lock_timer -= global.time_scale; if coyote_timer > 0 coyote_timer -= global.time_scale; if invincible_timer > 0 invincible_timer -= global.time_scale; if enter_room_timer > 0 enter_room_timer -= global.time_scale; if jump_buffer_timer > 0 jump_buffer_timer -= global.time_scale; if flash_timer > 0 flash_timer -= global.time_scale; } function player_check_dash() { if dash_buffer > 0 && dash_cooldown <= 0 && can_dash { dash_buffer = 0; state = state_dash; set_sprite(sPlayerDash); dash_cooldown = 36; x_spd = image_xscale * walk_spd * 3; y_spd = 0; can_dash = false; } } function player_check_movement() { if move_lock_timer <= 0 x_spd = _move_dir * walk_spd; } function player_check_jump() { if jump_buffer_timer > 0 { if coyote_timer > 0 { y_spd = jump_spd; jump_cnt = 1; jump_buffer_timer = 0; coyote_timer = 0; } else if _on_wall != 0 { y_spd = jump_spd; x_spd = -_on_wall * walk_spd * 1.5; jump_cnt = 1; move_lock_timer = 10; jump_buffer_timer = 0; } else if jump_cnt < jump_max { icl(oDoubleJumpEffect); y_spd = jump_spd * 0.9; jump_cnt++; jump_buffer_timer = 0; } } if oMain._jump_r && y_spd < 0 y_spd *= 0.4; } function player_check_attack() { if attack_buffer > 0 { attack_buffer = 0; state = state_attack; set_sprite(sPlayerAttack); } } function player_check_dodge() { if (oMain._down || oMain._up) && _on_ground && (oMain._dash || state == state_dash) { state = state_dodge; set_sprite(sPlayerDodgeWait); dodge_phase = "WAIT"; dodge_timer = 0; marked_target = noone; is_marked = false; is_perfect = false; var _hb = icl(oPlayerHitboxMark, x + facing * 60, y + 40); _hb.owner = id; _hb.x_offset = 60 * facing; _hb.y_offset = 40; } } function player_check_death() { if state == state_death || state == state_locked return; if global.playerHP <= 0 { /* var _drop = round(random_range(0.4 * global.save_data.player.Credit, 0.6 * global.save_data.player.Credit)); global.save_data.player.Credit -= _drop; global.save_data.player.corpse.droppedCredit = _drop; global.save_data.player.corpse.targetRoom = room; global.save_data.player.corpse.xPos = x; //lastsafe global.save_data.player.corpse.yPos = y; //lastsafe */ save_game_to_disk(); state = state_death; set_sprite(sPlayerDeath); screen_shake(30); var _cam = view_camera[0]; var _cam_x = camera_get_view_x(_cam); var _cam_y = camera_get_view_y(_cam); var _ripple = icl(oRippleDeath); _ripple.x = (x - _cam_x); _ripple.y = (y - _cam_y); } } function player_check_focus() { if oMain._focus && global.playerINK >= 9 { set_sprite(sPlayerFocus); state = state_focus; repeat(40) icl(oFocusingEffect); } } function player_check_door() { if current_door == noone || state == state_enter_door || state == state_exit_door return; global.target_door_id = current_door.target_door_id; global.target_room = current_door.target_room; global.door_direction = current_door.door_direction; var _fade = icl(oFade); _fade._callback = function() { room_goto(global.target_room); camera_snap(); }; state = state_enter_door; x_spd = 0; y_spd = 0; } function state_enter_door() { switch(global.door_direction) { case "UP": y_spd += player_calc_gravity(); set_sprite(sPlayerJump); image_index = 1; break; case "DOWN": y_spd = min(-3, y_spd); set_sprite(sPlayerJump); image_index = 0; break; case "LEFT": facing = 1; x_spd = facing * walk_spd; set_sprite(sPlayerWalk); break; case "RIGHT": facing = -1; x_spd = facing * walk_spd; set_sprite(sPlayerWalk); break; } } function state_exit_door() { y_spd += 0.5 * player_calc_gravity(); switch(global.door_direction) { case "LEFT": facing = -1; x_spd = facing * walk_spd; set_sprite(sPlayerWalk); break; case "RIGHT": facing = 1; x_spd = facing * walk_spd; set_sprite(sPlayerWalk); break; } if enter_room_timer <= 0 { state = state_free; global.target_door_id = -1; global.target_room = noone; global.door_direction = undefined; } } function player_check_attacked() { if current_attacker == noone || invincible_timer > 0 || state == state_death //|| (state == state_dodge && dodge_phase == "WAIT") return; if state == state_focus { global.playerINK -= 9; global.hitstop = 24; INK_blend = 0; flash_duration = 24; flash_timer = 24; } else global.hitstop = 12; global.playerHP -= current_attacker.damage; invincible_timer = 80; var _dir = sign(x - current_attacker.x); if _dir == 0 _dir = facing; screen_shake(10); x_spd = _dir * 30; y_spd = -5; state = state_hitstun_attacked; set_sprite(sPlayerHitstunAttacked); //effects } function player_check_hazard() { if current_hazard == noone || state == state_hitstun_hazard || state == state_death || state == state_locked return; global.playerHP -= current_hazard.damage; invincible_timer = 150; var _dir = sign(x - current_hazard.x); if _dir == 0 _dir = facing; global.hitstop = 18; screen_shake(10); x_spd = _dir * 10; y_spd = -10; state = state_hitstun_hazard; set_sprite(sPlayerHitstunHazard); } function state_hitstun_attacked() { x_spd = lerp(x_spd, 0, 0.1); y_spd += player_calc_gravity(); if animation_end() state = state_free; player_check_death(); } function state_hitstun_hazard() { x_spd = lerp(x_spd, 0, 0.1); y_spd += player_calc_gravity(); if animation_end() { state = state_locked; locked_timer = 60; var _fade = icl(oFade); _fade._callback = function() { oPlayer.x = oPlayer.last_safe_x; oPlayer.y = oPlayer.last_safe_y; //camera_snap(); }; } player_check_death(); } function state_free() { y_spd += player_calc_gravity(); if _on_wall != 0 && y_spd > 0 y_spd = min(y_spd, 3); /*下面是动画与视觉*/ animation_spd = 0.25; if _move_dir != 0 //有输入 { facing = _move_dir; if _on_ground set_sprite(sPlayerWalk); //走路 } else set_sprite(sPlayerIdle); //待机 if !_on_ground { if _on_wall == facing set_sprite(sPlayerWall); else { set_sprite(sPlayerJump); image_index = (y_spd < 0) ? 0 : 1; } } /* player_check_dodge(); if state == state_dodge return; */ player_check_movement(); player_check_dash(); player_check_jump(); player_check_attack(); player_check_focus(); } function state_dash() { y_spd += 0.2 * player_calc_gravity(); icl(oPlayerAfterImage); if animation_end() { if !_on_ground jump_cnt = max(jump_cnt, 1); state = state_free; player_check_attack(); } //player_check_dodge(); player_check_focus(); } function state_attack() { player_check_movement(); player_check_jump(); player_check_dash(); player_check_focus(); y_spd += player_calc_gravity(); if image_index == 1 { if oMain._down && !_on_ground current_hb = icl(oPlayerHitboxDown); else if oMain._up { current_hb = icl(oPlayerHitboxUp, x, y - 128); current_hb.y_offset = -128; } else { current_hb = icl(oPlayerHitboxHor, x, y - 64); current_hb.image_xscale = facing; current_hb.y_offset = -64; current_hb.hit_info.kbFactorX *= facing; } current_hb.owner = id; } // 攻击后摇结束 if current_hb != noone if _on_ground && current_hb.object_index == oPlayerHitboxDown state = state_free; if facing = -_move_dir state = state_free; if animation_end() state = state_free; } function state_locked() { locked_timer -= global.time_scale; x_spd = 0; y_spd += player_calc_gravity(); if locked_timer <= 0 state = state_free; } function state_death() { x_spd = 0; y_spd = 0; invincible_timer = 150; if animation_end() { state = state_locked; invincible_timer = 150; locked_timer = 90; var _fade = icl(oFade); _fade._callback = function() { room_goto(asset_get_index(global.save_data.world.current_room)); global.playerHP = global.save_data.player.maxHP; global.playerINK = 0; } } } function state_focus() { x_spd = 0; y_spd = 0; if animation_end() { player_add_INK(-9); global.playerHP += 3; global.playerHP = clamp(global.playerHP, 0, global.save_data.player.maxHP); state = state_free; flash_timer = 15; flash_duration = 15; INK_blend = 0; repeat(30) icl(oFocusEndEffect, x, y - sprite_height); } } /// @desc 返回基于玩家当前状态的重力值,注意不会自动赋值 function player_calc_gravity() { var _g = global.g; if y_spd > 0 _g *= 1.2; // 下坠 if abs(y_spd) < 0.5 _g *= 0.75; //滞空 return _g; // * global.time_scale; } /* function state_dodge() { if dodge_phase == "WAIT" { x_spd = 0; if current_attacker != noone || animation_end() { y_spd = jump_spd; dodge_phase = "DODGE"; set_sprite(sPlayerDodge); if current_attacker != noone && is_marked { is_perfect = true; invincible_timer = 150; global.time_scale = 0.2; global.hitstop = 20; } } } else if dodge_phase == "DODGE" { y_spd += global.g; if is_perfect icl(oPlayerAfterImage); if y_spd > 0 { timer = 0; y_spd = 0; if is_perfect { state = state_arc_slash; set_sprite(sPlayerArcSlash); } else { state = state_dodge_ending; set_sprite(sPlayerDodgeEnding); } } } } function state_arc_slash() { if image_index == 12 { var _hb = icd(oPlayerHitboxArc); _hb.owner = id; if facing == 1 { _hb.image_xscale = 1; _hb.image_angle = 30; _hb.kb_factor_x *= 1; } else { _hb.image_xscale = -1; _hb.image_angle = -30; _hb.kb_factor_x *= -1; } } else if image_index > 12 y_spd += global.g; if animation_end() { global.time_scale = 1.0; state = state_free; } } function state_dodge_ending() { if animation_end() state = state_free; } */