PlayerStates.gml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. function player_move_and_collide()
  2. {
  3. if global.hitstop > 0
  4. return;
  5. y_spd = min(y_spd, 16);
  6. y_spd *= global.time_scale;
  7. x_spd *= global.time_scale;
  8. if place_meeting(x, y + y_spd, oParentSolid)
  9. {
  10. while !place_meeting(x, y + sign(y_spd), oParentSolid)
  11. y += sign(y_spd);
  12. y_spd = 0;
  13. }
  14. y += y_spd;
  15. if place_meeting(x + x_spd, y, oParentSolid)
  16. {
  17. var _max_step = (y_spd == 0) ? 16 : 8; //前者地面容错,后者空中容错
  18. var _stepped = false;
  19. for(var i = 0; i < _max_step; i++)
  20. if !place_meeting(x + x_spd, y - i, oParentSolid)
  21. {
  22. y -= i;
  23. _stepped = true;
  24. break;
  25. }
  26. if !_stepped
  27. {
  28. while !place_meeting(x + sign(x_spd), y, oParentSolid)
  29. x += sign(x_spd);
  30. x_spd = 0;
  31. }
  32. }
  33. x += x_spd;
  34. y_spd /= global.time_scale;
  35. x_spd /= global.time_scale;
  36. }
  37. function player_status_update()
  38. {
  39. global.playerHP = clamp(global.playerHP, 0, global.save_data.player.maxHP);
  40. global.playerINK = clamp(global.playerINK, 0, global.save_data.player.maxINK);
  41. current_attacker = instance_place(x, y, oEnemyHitbox);
  42. current_hazard = instance_place(x, y, oParentHazard);
  43. current_door = instance_place(x, y, oDoor);
  44. if state != state_attack && instance_exists(current_hb)
  45. instance_destroy(current_hb);
  46. if !instance_exists(current_hb)
  47. current_hb = noone;
  48. if state != state_focus
  49. INK_blend = 0;
  50. image_index += animation_spd * global.time_scale;
  51. if oMain._dash
  52. dash_buffer = dash_buffer_max;
  53. if oMain._attack
  54. attack_buffer = attack_buffer_max;
  55. if oMain._jump_p
  56. jump_buffer_timer = jump_buffer_max;
  57. _move_dir = oMain._right - oMain._left;
  58. _on_ground = place_meeting(x, y + 1, oParentSolid)
  59. _on_wall = (place_meeting(x + 1, y, oBlockClimbable)
  60. - place_meeting(x - 1, y, oBlockClimbable))
  61. && global.save_data.player.abilities.wall_climb;
  62. var _no_cliff = place_meeting(x - sprite_width, y + 1, oParentSolid)
  63. && place_meeting(x + sprite_width, y + 1, oParentSolid)
  64. var _no_hazard = !(place_meeting(x - sprite_width, y, oParentHazard)
  65. || place_meeting(x + sprite_width, y, oParentHazard))
  66. if _on_ground && _no_cliff && _no_hazard
  67. {
  68. last_safe_x = x;
  69. last_safe_y = y;
  70. }
  71. if _on_ground || (_on_wall != 0)
  72. can_dash = true;
  73. if _on_ground
  74. {
  75. jump_cnt = 0;
  76. coyote_timer = coyote_max;
  77. }
  78. else if coyote_timer <= 0 && jump_cnt == 0
  79. jump_cnt = 1;
  80. if dash_cooldown > 0
  81. dash_cooldown -= global.time_scale;
  82. if dash_buffer > 0
  83. dash_buffer -= global.time_scale;
  84. if attack_buffer > 0
  85. attack_buffer -= global.time_scale;
  86. if move_lock_timer > 0
  87. move_lock_timer -= global.time_scale;
  88. if coyote_timer > 0
  89. coyote_timer -= global.time_scale;
  90. if invincible_timer > 0
  91. invincible_timer -= global.time_scale;
  92. if enter_room_timer > 0
  93. enter_room_timer -= global.time_scale;
  94. if jump_buffer_timer > 0
  95. jump_buffer_timer -= global.time_scale;
  96. if flash_timer > 0
  97. flash_timer -= global.time_scale;
  98. }
  99. function player_check_dash()
  100. {
  101. if dash_buffer > 0 && dash_cooldown <= 0 && can_dash
  102. && global.save_data.player.abilities.dash
  103. {
  104. dash_buffer = 0;
  105. state = state_dash;
  106. set_sprite(sPlayerDash);
  107. dash_cooldown = 36;
  108. x_spd = image_xscale * walk_spd * 3;
  109. y_spd = 0;
  110. can_dash = false;
  111. }
  112. }
  113. function player_check_movement()
  114. {
  115. if move_lock_timer <= 0
  116. x_spd = _move_dir * walk_spd;
  117. }
  118. function player_check_jump()
  119. {
  120. if jump_buffer_timer > 0
  121. {
  122. if coyote_timer > 0
  123. {
  124. y_spd = jump_spd;
  125. jump_cnt = 1;
  126. jump_buffer_timer = 0;
  127. coyote_timer = 0;
  128. }
  129. else if _on_wall != 0
  130. {
  131. y_spd = jump_spd;
  132. x_spd = -_on_wall * walk_spd * 1.5;
  133. jump_cnt = 1;
  134. move_lock_timer = 10;
  135. jump_buffer_timer = 0;
  136. }
  137. else if jump_cnt < jump_max
  138. {
  139. icl(oDoubleJumpEffect);
  140. y_spd = jump_spd * 0.9;
  141. jump_cnt++;
  142. jump_buffer_timer = 0;
  143. }
  144. }
  145. if oMain._jump_r && y_spd < 0
  146. y_spd *= 0.4;
  147. }
  148. function player_check_attack()
  149. {
  150. if attack_buffer > 0 && global.save_data.player.abilities.attack
  151. {
  152. attack_buffer = 0;
  153. state = state_attack;
  154. set_sprite(sPlayerAttack);
  155. }
  156. }
  157. function player_check_dodge()
  158. {
  159. if (oMain._down || oMain._up) && _on_ground
  160. && (oMain._dash || state == state_dash)
  161. {
  162. state = state_dodge;
  163. set_sprite(sPlayerDodgeWait);
  164. dodge_phase = "WAIT";
  165. dodge_timer = 0;
  166. marked_target = noone;
  167. is_marked = false;
  168. is_perfect = false;
  169. var _hb = icl(oPlayerHitboxMark, x + facing * 60, y + 40);
  170. _hb.owner = id;
  171. _hb.x_offset = 60 * facing;
  172. _hb.y_offset = 40;
  173. }
  174. }
  175. function player_check_death()
  176. {
  177. if state == state_death || state == state_locked
  178. return;
  179. if global.playerHP <= 0
  180. {
  181. /*
  182. var _drop = round(random_range(0.4 * global.save_data.player.Credit,
  183. 0.6 * global.save_data.player.Credit));
  184. global.save_data.player.Credit -= _drop;
  185. global.save_data.player.corpse.droppedCredit = _drop;
  186. global.save_data.player.corpse.targetRoom = room;
  187. global.save_data.player.corpse.xPos = x; //lastsafe
  188. global.save_data.player.corpse.yPos = y; //lastsafe
  189. */
  190. save_game_to_disk();
  191. state = state_death;
  192. set_sprite(sPlayerDeath);
  193. screen_shake(30);
  194. var _cam = view_camera[0];
  195. var _cam_x = camera_get_view_x(_cam);
  196. var _cam_y = camera_get_view_y(_cam);
  197. var _ripple = icl(oRippleDeath);
  198. _ripple.x = (x - _cam_x);
  199. _ripple.y = (y - _cam_y);
  200. }
  201. }
  202. function player_check_focus()
  203. {
  204. if oMain._focus && global.playerINK >= 9
  205. {
  206. set_sprite(sPlayerFocus);
  207. state = state_focus;
  208. repeat(40)
  209. icl(oFocusingEffect);
  210. }
  211. }
  212. function player_check_door()
  213. {
  214. if current_door == noone
  215. || state == state_enter_door
  216. || state == state_exit_door
  217. return;
  218. global.target_door_id = current_door.target_door_id;
  219. global.target_room = current_door.target_room;
  220. global.door_direction = current_door.door_direction;
  221. var _fade = icl(oFade);
  222. _fade._callback = function()
  223. {
  224. room_goto(global.target_room);
  225. camera_snap();
  226. };
  227. switch(global.door_direction)
  228. {
  229. case "LEFT":
  230. facing = 1;
  231. x_spd = facing * walk_spd;
  232. set_sprite(sPlayerWalk);
  233. break;
  234. case "RIGHT":
  235. facing = -1;
  236. x_spd = facing * walk_spd;
  237. set_sprite(sPlayerWalk);
  238. break;
  239. }
  240. state = state_enter_door;
  241. }
  242. function state_enter_door()
  243. {
  244. switch(global.door_direction)
  245. {
  246. case "UP":
  247. y_spd += player_calc_gravity();
  248. set_sprite(sPlayerJump);
  249. image_index = 1;
  250. break;
  251. case "DOWN":
  252. y_spd = min(-6, y_spd);
  253. set_sprite(sPlayerJump);
  254. image_index = 0;
  255. break;
  256. default:
  257. y_spd += player_calc_gravity();
  258. }
  259. }
  260. function state_exit_door()
  261. {
  262. y_spd += 0.3 * player_calc_gravity();
  263. if enter_room_timer <= 0
  264. {
  265. state = state_free;
  266. global.target_door_id = -1;
  267. global.target_room = noone;
  268. global.door_direction = undefined;
  269. }
  270. }
  271. function player_check_attacked()
  272. {
  273. if current_attacker == noone || invincible_timer > 0
  274. || state == state_death
  275. //|| (state == state_dodge && dodge_phase == "WAIT")
  276. return;
  277. if state == state_focus
  278. {
  279. global.playerINK -= 9;
  280. global.hitstop = 24;
  281. INK_blend = 0;
  282. flash_duration = 24;
  283. flash_timer = 24;
  284. screen_shake(20);
  285. }
  286. else
  287. {
  288. global.hitstop = 12;
  289. screen_shake(10);
  290. }
  291. var _dir = sign(x - current_attacker.x);
  292. if _dir == 0
  293. _dir = facing;
  294. repeat(10)
  295. {
  296. var _pe = icl(oPlayerAttackedEffect, x, y - sprite_height / 2);
  297. _pe.x_spd *= _dir;
  298. }
  299. global.playerHP -= current_attacker.damage;
  300. invincible_timer = 80;
  301. x_spd = _dir * 30;
  302. y_spd = -5;
  303. state = state_hitstun_attacked;
  304. set_sprite(sPlayerHitstunAttacked);
  305. }
  306. function player_check_hazard()
  307. {
  308. if current_hazard == noone ||
  309. state == state_hitstun_hazard || state == state_death || state == state_locked
  310. return;
  311. global.playerHP -= current_hazard.damage;
  312. invincible_timer = 150;
  313. var _dir = sign(x - current_hazard.x);
  314. if _dir == 0
  315. _dir = facing;
  316. global.hitstop = 18;
  317. screen_shake(10);
  318. x_spd = _dir * 10;
  319. y_spd = -10;
  320. state = state_hitstun_hazard;
  321. set_sprite(sPlayerHitstunHazard);
  322. }
  323. function state_hitstun_attacked()
  324. {
  325. x_spd = lerp(x_spd, 0, 0.1);
  326. y_spd += player_calc_gravity();
  327. if animation_end()
  328. state = state_free;
  329. player_check_death();
  330. }
  331. function state_hitstun_hazard()
  332. {
  333. x_spd = lerp(x_spd, 0, 0.1);
  334. y_spd += player_calc_gravity();
  335. if animation_end()
  336. {
  337. state = state_locked;
  338. locked_timer = 60;
  339. var _fade = icl(oFade);
  340. _fade._callback = function()
  341. {
  342. oPlayer.x = oPlayer.last_safe_x;
  343. oPlayer.y = oPlayer.last_safe_y;
  344. camera_snap();
  345. };
  346. }
  347. player_check_death();
  348. }
  349. function state_free()
  350. {
  351. y_spd += player_calc_gravity();
  352. if _on_wall != 0 && y_spd > 0
  353. y_spd = min(y_spd, 3);
  354. /*下面是动画与视觉*/
  355. animation_spd = 0.25;
  356. if _move_dir != 0 //有输入
  357. {
  358. facing = _move_dir;
  359. if _on_ground
  360. set_sprite(sPlayerWalk); //走路
  361. }
  362. else set_sprite(sPlayerIdle); //待机
  363. if !_on_ground
  364. {
  365. if _on_wall == facing
  366. set_sprite(sPlayerWall);
  367. else
  368. {
  369. set_sprite(sPlayerJump);
  370. image_index = (y_spd < 0) ? 0 : 1;
  371. }
  372. }
  373. /*
  374. player_check_dodge();
  375. if state == state_dodge return;
  376. */
  377. player_check_movement();
  378. player_check_dash();
  379. player_check_jump();
  380. player_check_attack();
  381. player_check_focus();
  382. }
  383. function state_dash()
  384. {
  385. y_spd += 0.2 * player_calc_gravity();
  386. var _inst = icl(oPlayerAfterImage);
  387. _inst.image_xscale = facing;
  388. if animation_end()
  389. {
  390. if !_on_ground
  391. jump_cnt = max(jump_cnt, 1);
  392. state = state_free;
  393. player_check_attack();
  394. }
  395. //player_check_dodge();
  396. player_check_focus();
  397. }
  398. function state_attack()
  399. {
  400. player_check_movement();
  401. player_check_jump();
  402. player_check_dash();
  403. player_check_focus();
  404. y_spd += player_calc_gravity();
  405. if image_index == 1
  406. {
  407. if oMain._down && !_on_ground
  408. current_hb = icl(oPlayerHitboxDown);
  409. else if oMain._up
  410. {
  411. current_hb = icl(oPlayerHitboxUp, x, y - 128);
  412. current_hb.y_offset = -128;
  413. }
  414. else
  415. {
  416. current_hb = icl(oPlayerHitboxHor, x, y - 64);
  417. current_hb.image_xscale = facing;
  418. current_hb.y_offset = -64;
  419. current_hb.hit_info.kbFactorX *= facing;
  420. }
  421. current_hb.owner = id;
  422. }
  423. // 攻击后摇结束
  424. if current_hb != noone
  425. if _on_ground && current_hb.object_index == oPlayerHitboxDown
  426. state = state_free;
  427. if facing = -_move_dir
  428. state = state_free;
  429. if animation_end()
  430. state = state_free;
  431. }
  432. function state_locked()
  433. {
  434. locked_timer -= global.time_scale;
  435. x_spd = 0;
  436. y_spd = 0;
  437. if locked_timer <= 0
  438. {
  439. state = state_free;
  440. jump_buffer_timer = 0;
  441. attack_buffer = 0;
  442. dash_buffer = 0;
  443. }
  444. }
  445. function state_death()
  446. {
  447. x_spd = 0;
  448. y_spd = 0;
  449. invincible_timer = 150;
  450. if animation_end()
  451. {
  452. state = state_locked;
  453. invincible_timer = 150;
  454. locked_timer = 90;
  455. var _fade = icl(oFade);
  456. _fade._callback = function()
  457. {
  458. room_goto(asset_get_index(global.save_data.world.spRoom));
  459. global.playerHP = global.save_data.player.maxHP;
  460. global.playerINK = 0;
  461. }
  462. }
  463. }
  464. function state_focus()
  465. {
  466. x_spd = 0;
  467. y_spd = 0;
  468. if animation_end()
  469. {
  470. player_add_INK(-9);
  471. global.playerHP += 3;
  472. global.playerHP = clamp(global.playerHP, 0, global.save_data.player.maxHP);
  473. state = state_free;
  474. flash_timer = 15;
  475. flash_duration = 15;
  476. INK_blend = 0;
  477. repeat(30)
  478. icl(oFocusEndEffect, x, y - sprite_height);
  479. }
  480. }
  481. /// @desc 返回基于玩家当前状态的重力值,注意不会自动赋值
  482. function player_calc_gravity()
  483. {
  484. var _g = global.g;
  485. if y_spd > 0
  486. _g *= 1.2; // 下坠
  487. if abs(y_spd) < 0.5
  488. _g *= 0.75; //滞空
  489. return _g; // * global.time_scale;
  490. }
  491. /* 暂时不使用的闪避能力
  492. function state_dodge()
  493. {
  494. if dodge_phase == "WAIT"
  495. {
  496. x_spd = 0;
  497. if current_attacker != noone || animation_end()
  498. {
  499. y_spd = jump_spd;
  500. dodge_phase = "DODGE";
  501. set_sprite(sPlayerDodge);
  502. if current_attacker != noone && is_marked
  503. {
  504. is_perfect = true;
  505. invincible_timer = 150;
  506. global.time_scale = 0.2;
  507. global.hitstop = 20;
  508. }
  509. }
  510. }
  511. else if dodge_phase == "DODGE"
  512. {
  513. y_spd += global.g;
  514. if is_perfect icl(oPlayerAfterImage);
  515. if y_spd > 0
  516. {
  517. timer = 0;
  518. y_spd = 0;
  519. if is_perfect
  520. {
  521. state = state_arc_slash;
  522. set_sprite(sPlayerArcSlash);
  523. }
  524. else
  525. {
  526. state = state_dodge_ending;
  527. set_sprite(sPlayerDodgeEnding);
  528. }
  529. }
  530. }
  531. }
  532. function state_arc_slash()
  533. {
  534. if image_index == 12
  535. {
  536. var _hb = icd(oPlayerHitboxArc);
  537. _hb.owner = id;
  538. if facing == 1
  539. {
  540. _hb.image_xscale = 1;
  541. _hb.image_angle = 30;
  542. _hb.kb_factor_x *= 1;
  543. }
  544. else
  545. {
  546. _hb.image_xscale = -1;
  547. _hb.image_angle = -30;
  548. _hb.kb_factor_x *= -1;
  549. }
  550. }
  551. else if image_index > 12
  552. y_spd += global.g;
  553. if animation_end()
  554. {
  555. global.time_scale = 1.0;
  556. state = state_free;
  557. }
  558. }
  559. function state_dodge_ending()
  560. {
  561. if animation_end()
  562. state = state_free;
  563. }
  564. */