function player_move_and_collide() { 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; } function player_state_update() { current_attacker = instance_place(x, y, oEnemyHitbox); if oInput._dash dash_buffer = dash_buffer_max; if oInput._attack attack_buffer = attack_buffer_max; _move_dir = oInput._right - oInput._left; _on_ground = place_meeting(x, y + 1, oParentSolid) _on_wall = place_meeting(x + 1, y, oBlockClimbable) - place_meeting(x - 1, y, oBlockClimbable); 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--; if dash_buffer > 0 dash_buffer--; if attack_buffer > 0 attack_buffer--; if move_lock_timer > 0 move_lock_timer--; if coyote_timer > 0 coyote_timer--; } function state_free() { y_spd += global.g; if _on_wall != 0 && y_spd > 0 y_spd = min(y_spd, 3); /*下面是动画与视觉*/ var _current_sprite = sprite_index; image_speed = 1; if _move_dir != 0 { facing = _move_dir; if _on_ground sprite_index = sPlayerWalk; } else sprite_index = sPlayerIdle; if !_on_ground { image_speed = 0; if _on_wall == facing sprite_index = sPlayerWall; else { sprite_index = sPlayerJump; image_index = (y_spd < 0) ? 0 : 1; } } if _current_sprite != sprite_index image_index = 0; /**/ player_check_dodge(); if state == player_dodge return; player_check_movement(); player_check_dash(); player_check_jump(); player_check_attack(); } function state_dash() { y_spd += 0.2 * global.g; icl(oPlayerAfterImage); if animation_end() { if !_on_ground jump_cnt = max(jump_cnt, 1); state = state_free; player_check_attack(); } player_check_dodge(); } function state_attack() { player_check_movement(); player_check_jump(); y_spd += global.g; if image_index == 1 { var _hb; if oInput._down && !_on_ground { _hb = icl(oPlayerHitboxVer, x, y + 64); _hb.y_offset = 64; } else if oInput._up { _hb = icl(oPlayerHitboxVer, x, y - 64); _hb.y_offset = -64; } else { _hb = icl(oPlayerHitboxHor, x + 72 * facing); _hb.x_offset += 72 * facing; _hb.kb_factor_x *= facing; } _hb.owner = id; } // 冲刺预输入 & 预读帧数 if image_index >= 2 player_check_dash(); // 攻击后摇结束 if animation_end() state = state_free; } function state_locked() { x_spd = 0; y_spd += global.g; } function player_check_dash() { if dash_buffer > 0 && dash_cooldown <= 0 && can_dash { dash_buffer = 0; state = state_dash; sprite_index = sPlayerDash; image_index = 0; image_speed = 1; 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 oInput.jump_buffer_timer > 0 { if coyote_timer > 0 { y_spd = jump_spd; jump_cnt = 1; oInput.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 = 12; oInput.jump_buffer_timer = 0; } else if jump_cnt < jump_max { icl(oDoubleJumpEffect); y_spd = jump_spd * 0.9; jump_cnt++; oInput.jump_buffer_timer = 0; } } if oInput._jump_r && y_spd < 0 y_spd *= 0.4; } function player_check_attack() { if attack_buffer > 0 { attack_buffer = 0; state = state_attack; sprite_index = sPlayerAttack; image_speed = 1; image_index = 0; } } function player_check_attacked() { if current_attacker == noone || is_invincible || state == player_dodge return; global.playerHP -= current_attacker.damage; is_invincible = true; alarm[0] = 80; var _dir = sign(x - current_attacker.x); if _dir == 0 _dir = facing; global.hitstop = 12; x_spd = _dir * 30; y_spd = -5; state = player_hitstun_attacked; sprite_index = sPlayerHitstunAttacked; image_speed = 1; image_index = 0; //effects } function player_check_hazard() { var _hazard = instance_place(x, y, oParentHazard); if _hazard != noone { global.playerHP -= _hazard.damage; is_invincible = true; alarm[0] = 150; var _dir = sign(x - _hazard.x); if _dir == 0 _dir = facing; global.hitstop = 18; x_spd = _dir * 10; y_spd = -10; state = player_hitstun_hazard; sprite_index = sPlayerHitstunHazard; image_speed = 1; image_index = 0; } } function player_perform_pogo() { y_spd = jump_spd * 0.8; jump_cnt = 1; can_dash = true; coyote_timer = 0; global.hitstop = 3; } function player_perform_recoil() { x_spd = - facing * 3; move_lock_timer = 6; global.hitstop = 2; } function player_hitstun_attacked() { x_spd = lerp(x_spd, 0, 0.1); y_spd += global.g; if animation_end() state = state_free; } function player_hitstun_hazard() { x_spd = lerp(x_spd, 0, 0.1); y_spd += global.g; if animation_end() { alarm[1] = 60; state = state_locked; var _fade = icl(oFade); _fade._callback = function() { oPlayer.x = 160;//oPlayer.last_safe_x; oPlayer.y = 2016;//oPlayer.last_safe_y; camera_snap(); }; } } function player_check_dodge() { if (oInput._down || oInput._up) && _on_ground && (oInput._dash || state == state_dash) { state = player_dodge; sprite_index = sPlayerDodgeWait; image_index = 0; image_speed = 1; 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_dodge() { if dodge_phase == "WAIT" { x_spd = 0; if current_attacker != noone || animation_end() { y_spd = jump_spd; dodge_phase = "DODGE"; sprite_index = sPlayerDodge; image_index = 0; if current_attacker != noone && is_marked { is_perfect = true; is_invincible = true; global.time_scale = 0.2; global.hitstop = 20; alarm[0] = 210; //之后实机测试计算 } } } 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 = player_arc_slash; sprite_index = sPlayerArcSlash; image_index = 0; image_speed = 1; } else { state = player_dodge_ending; sprite_index = sPlayerDodgeEnding; image_index = 0; } } } } function player_arc_slash() { if image_index == 7 { var _hb = icl(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 animation_end() { global.time_scale = 1.0; state = state_free; } } function player_dodge_ending() { if animation_end() state = state_free; } function player_check_mark() { /* var _width = 2 * (72 + 16); var _height = 64; var _x_offset = facing * (36 + 16); var _y_offset = 0; var x1 = x + _x_offset - (_width / 2); var y1 = y + _y_offset; var x2 = x + _x_offset + (_width / 2); var y2 = y + _y_offset + _height; debug_hitbox_x1 = x1; debug_hitbox_y1 = y1; debug_hitbox_x2 = x2; debug_hitbox_y2 = y2; var _target = collision_rectangle(x1, y1, x2, y2, oParentEnemy, false, true); if _target != noone { is_marked = true; marked_target = _target; // animation // instance_create_layer(_target.x, _target.y, "FX", oFx_Marked); } */ }