Advertisement
mhughson

6502 Particle System

May 8th, 2024
486
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
6502 TASM/64TASS 8.59 KB | Source Code | 0 0
  1. .include "macro_math.s"
  2.  
  3. .export _reset_all_particles, _update_particles, _spawn_particle
  4. .export _spawn_brick_smash_particle_system, _spawn_coin_particle_system
  5.  
  6. ; ca65 helper routines
  7. .import decsp3, shlax4, shrax4, shlaxy
  8.  
  9. ; variables defined in C but needed in this code.
  10. .import _cam
  11.  
  12. ; CONSTANTS
  13.  
  14. NUM_PARTICLES = 16
  15. PART_GRAVITY_DEFAULT = 56 ;((255*22)/100)
  16. INDEX_NONE = $ff
  17. COIN_VEL = ((4 << 8) + 128) ; based on C version
  18.  
  19. PART_TYPE_NONE = 0
  20. PART_TYPE_ROCK = 1
  21. PART_TYPE_COIN = 2
  22.  
  23. ; NOTE: this doesn't need to be saved, but that's where the spare memory is.
  24. .segment "XRAM"
  25.  
  26. part_x_scr:         .res NUM_PARTICLES
  27. part_x_pix:         .res NUM_PARTICLES
  28. part_x_sub:         .res NUM_PARTICLES
  29. part_x_vel_pix:     .res NUM_PARTICLES
  30. part_x_vel_sub:     .res NUM_PARTICLES
  31. part_y_pix:         .res NUM_PARTICLES
  32. part_y_sub:         .res NUM_PARTICLES
  33. part_y_vel_pix:     .res NUM_PARTICLES
  34. part_y_vel_sub:     .res NUM_PARTICLES
  35. part_tile:          .res NUM_PARTICLES
  36. part_counter:       .res NUM_PARTICLES
  37. part_type:          .res NUM_PARTICLES
  38. part_state:         .res NUM_PARTICLES
  39. part_x_reg_temp:    .res 1
  40.  
  41. ; routine params
  42.  
  43. in_part_x_h:    .res 1
  44. _in_part_x_h = in_part_x_h ; alias with a _
  45. .export _in_part_x_h
  46.  
  47. in_part_x_l:    .res 1
  48. _in_part_x_l = in_part_x_l
  49. .export _in_part_x_l
  50.  
  51. in_part_y_h:    .res 1
  52. _in_part_y_h = in_part_y_h
  53. .export _in_part_y_h
  54.  
  55. .segment "BANK3"
  56.  
  57. ;;-----------------------------------------------------------------------
  58.  
  59. .proc _reset_all_particles
  60.  
  61.     ldx #(NUM_PARTICLES-1)
  62.     lda #0
  63.  
  64. loop:
  65.     jsr _clear_particle
  66.     dex
  67.     bpl loop
  68.  
  69.     rts
  70.  
  71. .endproc
  72.  
  73. ;;-----------------------------------------------------------------------
  74.  
  75. .proc _update_particles
  76.  
  77.     ldx #(NUM_PARTICLES-1)
  78.  
  79. loop:
  80.  
  81.     ; is the particle alive?
  82.     lda part_state, x
  83.     bne :+
  84.         jmp next_particle
  85. :
  86.  
  87.     ;
  88.     ; move
  89.     ;
  90.  
  91.     ; add x velocity to x position
  92.     add24xs16    part_x_sub, part_x_pix, part_x_scr, part_x_vel_sub, part_x_vel_pix
  93.  
  94.     ; y velocity
  95.     add16x8const    part_y_vel_sub, part_y_vel_pix, #PART_GRAVITY_DEFAULT
  96.  
  97.     ; add y velocity to y position
  98.     add16x16    part_y_sub, part_y_pix, part_y_vel_sub, part_y_vel_pix
  99.  
  100.     ; custom update
  101.     lda part_type,x
  102.  
  103.     ; ROCK
  104.     cmp #PART_TYPE_ROCK
  105.     bne :+
  106.         ; custom rock logic
  107.         clc
  108.         lda part_counter,x
  109.         cmp #30
  110.         bne end_custom_update
  111.         ; change tile half way
  112.         inc part_tile,x
  113.         jmp end_custom_update
  114.  
  115.     ; COIN
  116. :   cmp #PART_TYPE_COIN
  117.     bne :+
  118.         ; custom coin logic
  119.         ; 0xf0 + ((tick_count >> 2) % 4)
  120.         lda part_counter,x
  121.         lsr
  122.         lsr
  123.         and #%00000011 ; %4
  124.         clc
  125.         adc #$f0
  126.         sta part_tile,x
  127.         jmp end_custom_update
  128. :
  129.  
  130. end_custom_update:
  131.  
  132.     ; did the particle fall off the bottom?
  133.     lda part_y_pix,x
  134.     clc
  135.     cmp #208
  136.     bcc :+
  137.         ; off the bottom
  138.         lda #0
  139.         sta part_state,x
  140.         jmp next_particle
  141. :
  142.  
  143.     dec part_counter,x
  144.     bne :+
  145.         ; counter has expired. Disable particle.
  146.         lda #0
  147.         sta part_state,x
  148.         jmp next_particle        
  149. :
  150.  
  151.     ;
  152.     ; draw
  153.     ;
  154.  
  155.     jsr _clip_and_draw_particle
  156.  
  157. next_particle:
  158.     dex
  159.     bmi :+
  160.         jmp loop
  161. :
  162.  
  163.     rts
  164.  
  165. .endproc ; _update_particles
  166.  
  167. ;;-----------------------------------------------------------------------
  168.  
  169. ; params:   x - particle index
  170. ;
  171. .proc _clear_particle
  172.  
  173.     lda #0
  174.     sta part_x_scr, x
  175.     sta part_x_pix, x
  176.     sta part_x_sub, x
  177.     sta part_x_vel_pix, x
  178.     sta part_x_vel_sub, x
  179.     sta part_y_pix, x
  180.     sta part_y_sub, x
  181.     sta part_y_vel_pix, x
  182.     sta part_y_vel_sub, x
  183.     sta part_tile, x
  184.     sta part_counter, x
  185.     sta part_type, x
  186.     sta part_state, x
  187.     rts
  188.  
  189. .endproc ; _clear_partcile
  190.  
  191. ;;-----------------------------------------------------------------------
  192.  
  193. ; params:   x reg - offset into particles
  194. ; output:   x reg - the index of the next free particle.
  195. .proc _find_next_free_particle
  196.  
  197. loop:
  198.  
  199.     ; is the particle alive?
  200.     lda part_state, x
  201.     bne next_particle
  202.  
  203.     ; particle is alive, so just return with X pointing
  204.     ; to this index
  205.     rts
  206.  
  207. next_particle:
  208.     dex
  209.     bpl loop
  210.    
  211.     ; if we reach this point X will be $ff, which is INDEX_NONE
  212.     rts
  213.  
  214. .endproc ;_find_next_free_particle
  215.  
  216. ;;-----------------------------------------------------------------------
  217.  
  218. brick_smash_y_vel_pix:
  219.     .byte $fc, $fc, $fe, $fe ; -4, -4, -2, -2
  220.  
  221. ; both are 128, but one is negative and the other is positive.
  222. brick_smash_x_vel_h:
  223.     .byte $ff, 0, $ff, 0 ; -128, 128, -128, 128
  224.  
  225. brick_smash_x_offset:
  226.     .byte 0, 8, 0, 8
  227. brick_smash_y_offset:
  228.     .byte 0, 0, 8, 8
  229.  
  230. ; params:   in_part_x_l - x position in pixels
  231. ;           in_part_x_h - x position in sreen pages
  232. ;           in_part_y_h - y position in pixels
  233. .proc _spawn_brick_smash_particle_system
  234.  
  235.     ldx #(NUM_PARTICLES-1)
  236.  
  237. .repeat 4, I
  238.     jsr _find_next_free_particle
  239.     cpx #INDEX_NONE
  240.     bne :+
  241.         rts
  242. :   jsr _clear_particle
  243.  
  244.     ; bring the particle to life
  245.     lda #1
  246.     sta part_state, x
  247.  
  248.     clc
  249.     lda in_part_x_l
  250.     adc brick_smash_x_offset+I
  251.     sta part_x_pix, x
  252.     lda in_part_x_h
  253.     sta part_x_scr, x
  254.     clc
  255.     lda in_part_y_h
  256.     adc brick_smash_y_offset+I
  257.     sta part_y_pix, x
  258.  
  259.     ; always 128 sub pixel, but the pix value will
  260.     ; determine if it is negative or positive.
  261.     lda #128
  262.     sta part_x_vel_sub,x
  263.     lda brick_smash_x_vel_h+I
  264.     sta part_x_vel_pix,x
  265.  
  266.     lda brick_smash_y_vel_pix+I
  267.     sta part_y_vel_pix,x
  268.  
  269.     lda #$e0
  270.     sta part_tile,x
  271.  
  272.     ; live for about 1 second
  273.     lda #60
  274.     sta part_counter,x
  275.  
  276.     lda #PART_TYPE_ROCK
  277.     sta part_type,x
  278. .endrepeat
  279.  
  280.     rts
  281.  
  282. .endproc ;_spawn_brick_smash_particle_system
  283.  
  284. ;;-----------------------------------------------------------------------
  285.  
  286. ; params:   in_part_x_l - x position in pixels
  287. ;           in_part_x_h - x position in sreen pages
  288. ;           in_part_y_h - y position in pixels
  289. .proc _spawn_coin_particle_system
  290.  
  291.     ldx #(NUM_PARTICLES-1)
  292.  
  293.     jsr _find_next_free_particle
  294.     cpx #INDEX_NONE
  295.     bne :+
  296.         rts
  297. :   jsr _clear_particle
  298.  
  299.     ; bring the particle to life
  300.     lda #1
  301.     sta part_state, x
  302.  
  303.     lda in_part_x_l
  304.     sta part_x_pix, x
  305.     lda in_part_x_h
  306.     sta part_x_scr, x
  307.     lda in_part_y_h
  308.     sta part_y_pix, x
  309.  
  310.     lda #<(-COIN_VEL)
  311.     sta part_y_vel_sub,x
  312.     lda #>(-COIN_VEL)
  313.     sta part_y_vel_pix,x
  314.  
  315.     lda #$f0
  316.     sta part_tile,x
  317.  
  318.     ; live for about 1/2 second
  319.     lda #32
  320.     sta part_counter,x
  321.  
  322.     lda #PART_TYPE_COIN
  323.     sta part_type,x
  324.  
  325.     rts
  326.  
  327. .endproc ;_spawn_coin_particle_system
  328.  
  329. ;;-----------------------------------------------------------------------
  330.  
  331. ;unused
  332. .proc _spawn_particle
  333.  
  334.     ldx #(NUM_PARTICLES-1)
  335.  
  336. loop:
  337.  
  338.     ; is the particle alive?
  339.     lda part_state, x
  340.     bne next_particle
  341.  
  342.     ; particle is alive
  343.  
  344.     ; start with a blank slate so that we only need to update
  345.     ; the values that change.
  346.     jsr _clear_particle
  347.  
  348.     ; bring the particle to life
  349.     lda #1
  350.     sta part_state, x
  351.  
  352.     lda #128
  353.     sta part_x_pix, x
  354.     sta part_y_pix, x
  355.  
  356.     lda #128
  357.     sta part_x_vel_pix,x
  358.  
  359.     jmp done
  360.  
  361. next_particle:
  362.     dex
  363.     bpl loop
  364.  
  365.  
  366. done:
  367.     rts
  368.  
  369. .endproc ;_spawn_particle
  370.  
  371. ;;-----------------------------------------------------------------------
  372.  
  373. ; params:   x - particle index
  374. ;
  375. .proc _clip_and_draw_particle
  376.  
  377.     stx part_x_reg_temp
  378.  
  379.     ; offscreen left clipping
  380.     lda part_x_scr,x
  381.     cmp _cam+1
  382.     beq :+ ; equal, continue check
  383.         bcc remove ; a < cam
  384.         jmp test_right_clip
  385. :   lda part_x_pix,x
  386.     cmp _cam
  387.     bcc remove ; a < cam
  388.  
  389. test_right_clip:
  390.     ; offscreen right clipping
  391.     lda _cam+1
  392.     clc
  393.     adc #1
  394.     cmp part_x_scr,x
  395.     beq :+ ; equal, continue check
  396.         bcc done ; cam < obj
  397.         jmp @draw_sprite
  398. :   lda part_x_pix,x
  399.     cmp _cam
  400.     bcs done
  401.  
  402. @draw_sprite:
  403.     ; oam_spr(64, 64, 0, 0);
  404.     jsr decsp3
  405.  
  406.     ; camera shift
  407.     sec
  408.     lda part_x_pix,x
  409.     sbc _cam ; pos_x low
  410.     ldy #$02 ; number of stack params
  411.     sta (sp),y
  412.     lda part_y_pix,x ; param 2 - y
  413.     sec
  414.     sbc #1 ; pixel offset    
  415.     dey
  416.     sta (sp),y
  417.     lda part_tile,x ; param 3 - chr
  418.     dey
  419.     sta (sp),y
  420.     lda #02 ; 03 param 4 goes into a reg - attr
  421. ; stomp x
  422.     jsr _oam_spr
  423.  
  424.     ; restore the x reg
  425.     ldx part_x_reg_temp
  426.  
  427. done:
  428.     rts
  429.  
  430. remove:
  431.     lda #0
  432.     sta part_state, x
  433.     rts
  434.  
  435. .endproc ; _clip_and_draw_particle
Tags: nesdev
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement