You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

369 lines
6.2 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. INCLUDE "game.inc"
  2. INCLUDE "hardware.inc"
  3. INCLUDE "oam.inc"
  4. INCLUDE "util.inc"
  5. Section "Player Data", WRAM0
  6. DEF PLAYER_INV_SIZE EQU 32
  7. PLAYER_X:: db
  8. PLAYER_Y:: dw
  9. PLAYER_DIR:: db
  10. PLAYER_STATE:: db
  11. PLAYER_VY:: dw
  12. PLAYER_INV:: ds (2 * PLAYER_INV_SIZE)
  13. Section "Player Code", ROM0
  14. spriteData:
  15. INCBIN "png/sprite/player.2bpp"
  16. DEF SPRITE_OAM_IDX EQU 0
  17. DEF SPRITE_WIDTH EQU 2
  18. DEF SPRITE_HEIGHT EQU 2
  19. DEF PLAYER_SPEED EQU 2
  20. DEF GRAVITY EQU (0 << 8) | $2e ; 0.18
  21. DEF INIT_VY EQU (3 << 8) | $99 ; 3.60
  22. DEF INIT_FALL_VY EQU ($ff << 8) | $1a ; -1.1015625
  23. DEF MAX_VY EQU ($f9 << 8) | $00 ; -7.0
  24. Player_Init::
  25. ; Clear player data (X/Y initialized by map engine)
  26. ld hl, PLAYER_DIR
  27. xor a
  28. REPT (7 + 2 * PLAYER_INV_SIZE)
  29. ld [hl+], a
  30. ENDR
  31. ; Copy sprite to VRAM
  32. ld bc, _VRAM8000 + TILE_INDEX_PLAYER * TILE_SIZE
  33. ld hl, spriteData
  34. ld d, TILE_SIZE * (SPRITE_WIDTH * SPRITE_HEIGHT)
  35. call memcpy
  36. ; Initialize OAM entries with player state
  37. call Player_UpdateOAM
  38. ret
  39. Player_Update::
  40. ; check for jump
  41. ld a, [keys]
  42. and PADF_UP
  43. jr z, .jump_update_check
  44. ; initialize jump state if not already jumping
  45. ld a, [PLAYER_STATE]
  46. and PLAYER_STATEF_JUMP
  47. jr nz, .jump_update
  48. ld a, PLAYER_STATEF_JUMP
  49. ld [PLAYER_STATE], a
  50. ld hl, PLAYER_VY
  51. STORE16 INIT_VY
  52. ; todo: deduplicate
  53. .jump_update_check:
  54. ld a, [PLAYER_STATE]
  55. and PLAYER_STATEF_JUMP
  56. jr z, .right
  57. .jump_update:
  58. ; load y velocity into bc
  59. ld hl, PLAYER_VY
  60. ld b, [hl]
  61. inc hl
  62. ld c, [hl]
  63. ; adjust velocity by gravity
  64. ld a, c
  65. sub LOW(GRAVITY)
  66. ld c, a
  67. ld a, b
  68. sbc HIGH(GRAVITY)
  69. ld b, a
  70. ; ; we only need to clamp when moving down
  71. ; bit 7, b
  72. ; jr z, .no_clamp
  73. ; ; vy = MIN(MAX_VY, vy)
  74. ; ld a, b
  75. ; cp HIGH(MAX_VY)
  76. ; jr c, .no_clamp
  77. ; ld b, HIGH(MAX_VY)
  78. ; ld c, LOW(MAX_VY)
  79. .no_clamp:
  80. ld hl, PLAYER_VY
  81. STORE16 bc
  82. ; y -= floor(vy)
  83. ld hl, PLAYER_Y + 1
  84. ld a, [hl]
  85. sub c
  86. ld [hl-], a
  87. ld a, [hl]
  88. sbc b
  89. ld [hl], a
  90. ; roll back jump if there was a collision
  91. call player_bg_collides
  92. jr nz, .jump_Player_UpdateOAM
  93. ; TODO: Enable once scroll zones are implemented
  94. ; ld a, [PLAYER_VY]
  95. ; check if VY < 0 and call Map_ScrollUp / Map_ScrollDown
  96. .jump_rollback:
  97. ld hl, PLAYER_VY
  98. bit 7, [hl]
  99. ld hl, PLAYER_Y
  100. jr z, .jump_rollback_down
  101. dec [hl]
  102. jr .jump_rollback_check
  103. .jump_rollback_down:
  104. inc [hl]
  105. .jump_rollback_check:
  106. call player_bg_collides
  107. jr z, .jump_rollback
  108. ; set PLAYER_STATE = PLAYER_STATEF_WALK if VY < 0 (fell into ground)
  109. ld hl, PLAYER_VY
  110. bit 7, [hl]
  111. ; either way, set VY = 0.
  112. ; NOTE: MUST USE LD HERE TO KEEP FLAGS FROM BIT TEST
  113. ld [hl], 0
  114. ld hl, PLAYER_VY + 1
  115. ld [hl], 0
  116. jr z, .jump_Player_UpdateOAM
  117. ld a, PLAYER_STATEF_WALK
  118. ld [PLAYER_STATE], a
  119. .jump_Player_UpdateOAM:
  120. call Player_UpdateOAM
  121. ; check for move right
  122. .right:
  123. ld a, [keys]
  124. and PADF_RIGHT
  125. jr z, .left
  126. ; check for right boundary
  127. ld a, [PLAYER_X]
  128. add 16
  129. cp SCRN_X
  130. jr nc, .left
  131. .move_right:
  132. ld a, [PLAYER_X]
  133. add PLAYER_SPEED
  134. ld [PLAYER_X], a
  135. call player_bg_collides
  136. jr z, .right_rollback
  137. ; TODO: Enable once scroll zones are implemented
  138. ; ld d, PLAYER_SPEED
  139. ; call Map_ScrollRight
  140. xor a
  141. ld [PLAYER_DIR], a
  142. call Player_UpdateOAM
  143. ret
  144. .right_rollback:
  145. ld a, [PLAYER_X]
  146. sub PLAYER_SPEED
  147. ld [PLAYER_X], a
  148. ret
  149. .left:
  150. ; check for left button
  151. ld hl, keys
  152. ld a, [hl]
  153. and PADF_LEFT
  154. jr z, .fall
  155. ; check for left boundary
  156. ld a, [PLAYER_X]
  157. or a
  158. jr z, .fall
  159. sub PLAYER_SPEED
  160. ld [PLAYER_X], a
  161. call player_bg_collides
  162. jr z, .left_rollback
  163. ; TODO: Enable once scroll zones are implemented
  164. ; ld d, PLAYER_SPEED
  165. ; call Map_ScrollLeft
  166. ld a, $ff
  167. ld [PLAYER_DIR], a
  168. call Player_UpdateOAM
  169. jr .fall
  170. .left_rollback:
  171. ld hl, PLAYER_X
  172. inc [hl]
  173. inc [hl]
  174. .fall:
  175. call player_in_air
  176. ret z
  177. ; only set jump state if not already jumping
  178. ld hl, PLAYER_STATE
  179. ld a, [hl]
  180. and PLAYER_STATEF_JUMP
  181. ret nz
  182. ld [hl], PLAYER_STATEF_JUMP
  183. ld hl, PLAYER_VY
  184. STORE16 INIT_FALL_VY
  185. ret
  186. ; Update player metasprite with positional data
  187. Player_UpdateOAM::
  188. ld hl, PLAYER_DIR
  189. ld a, [hl-] ; dir (0 = right , $ff = left)
  190. and OAMF_XFLIP
  191. ld c, a
  192. dec hl ; skip fractional part
  193. ld a, [hl-] ; y
  194. add 16
  195. ld d, a
  196. ld a, [hl] ; x
  197. add 8
  198. ld b, a
  199. ld a, d
  200. ld_OAM_y hl, SPRITE_OAM_IDX
  201. ; top left sprite
  202. ld [hli], a
  203. ld [hl], b
  204. inc hl
  205. ld [hl], TILE_INDEX_PLAYER
  206. inc hl
  207. ld [hl], c
  208. inc hl
  209. ; top right
  210. ld d, a
  211. ld a, b
  212. add 8
  213. ld b, a
  214. ld a, d
  215. ld [hli], a
  216. ld [hl], b
  217. inc hl
  218. ld [hl], TILE_INDEX_PLAYER + 1
  219. inc hl
  220. ld [hl], c
  221. inc hl
  222. ; bottom left
  223. add 8
  224. ld d, a
  225. ld a, b
  226. sub 8
  227. ld b, a
  228. ld a, d
  229. ld [hli], a
  230. ld [hl], b
  231. inc hl
  232. ld [hl], TILE_INDEX_PLAYER + 2
  233. inc hl
  234. ld [hl], c
  235. inc hl
  236. ; bottom right
  237. ld d, a
  238. ld a, b
  239. add 8
  240. ld b, a
  241. ld a, d
  242. ld [hli], a
  243. ld [hl], b
  244. inc hl
  245. ld [hl], TILE_INDEX_PLAYER + 3
  246. inc hl
  247. ld [hl], c
  248. ; flip tile indices if necessary
  249. ld a, c
  250. or c
  251. jr z, .done
  252. ; TODO: Can be sped up by using LD A, [NN]
  253. ld_OAM_tile hl, SPRITE_OAM_IDX
  254. ld [hl], TILE_INDEX_PLAYER + 1
  255. ld_OAM_tile hl, SPRITE_OAM_IDX + 1
  256. ld [hl], TILE_INDEX_PLAYER
  257. ld_OAM_tile hl, SPRITE_OAM_IDX + 2
  258. ld [hl], TILE_INDEX_PLAYER + 3
  259. ld_OAM_tile hl, SPRITE_OAM_IDX + 3
  260. ld [hl], TILE_INDEX_PLAYER + 2
  261. .done:
  262. ret
  263. ; Add item(s) to the player's inventory
  264. ; @param b Item ID
  265. ; @param c Item quantity
  266. Player_AddInvItem::
  267. push de
  268. ld hl, PLAYER_INV
  269. ld e, PLAYER_INV_SIZE
  270. .find_inv_slot:
  271. ld a, [hl]
  272. cp b
  273. jr z, .update_item
  274. inc hl
  275. dec e
  276. jr nz, .find_inv_slot
  277. .update_item:
  278. ; set item id
  279. ld a, b
  280. ld [hl+], a
  281. ; update item qty
  282. ld a, [hl]
  283. add c
  284. ld [hl], a
  285. pop de
  286. ret
  287. ; Remove item(s) from the player's inventory
  288. ; @param b Item ID
  289. ; @param c Item quantity