base:character_bullets
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | base:character_bullets [2018-03-03 12:08] (current) – created achim64 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Character bullets ====== | ||
+ | by Achim | ||
+ | |||
+ | |||
+ | Here' | ||
+ | Using character bullets is a bit annoying, but it's the easiest | ||
+ | way to save sprites. | ||
+ | |||
+ | ===== Preperation ===== | ||
+ | |||
+ | |||
+ | First thing to do is to set up a lookup table that holds the screen | ||
+ | addresses for each screen row. This will make the movements a lot easier. | ||
+ | |||
+ | < | ||
+ | ;create lookup table for screen rows | ||
+ | |||
+ | lda #$00 | ||
+ | sta tmp0 ;zp address | ||
+ | sta tmp0+1 ;zp address+1 | ||
+ | |||
+ | sta rowlow ; | ||
+ | sta rowhi | ||
+ | |||
+ | tax | ||
+ | lookup: lda tmp0 | ||
+ | clc | ||
+ | adc #40 | ||
+ | sta rowlow+1,x | ||
+ | sta tmp0 | ||
+ | bcc + | ||
+ | inc tmp0+1 | ||
+ | + lda tmp0+1 | ||
+ | sta rowhi+1,x | ||
+ | inx | ||
+ | cpx # | ||
+ | bne lookup | ||
+ | |||
+ | rowlow: | ||
+ | rowhi: | ||
+ | </ | ||
+ | |||
+ | ' | ||
+ | A simple 'ora # | ||
+ | |||
+ | Now you can allocate x/ | ||
+ | |||
+ | bullet_column = x, bullet_row = y | ||
+ | |||
+ | Set up two tables for x and y (columns and rows): | ||
+ | |||
+ | < | ||
+ | bullet_row: | ||
+ | bullet_column: | ||
+ | </ | ||
+ | |||
+ | From now on you only have to manipulate the coordinates to move the bullets. | ||
+ | Everytime your game engine refreshes the screen data, use ' | ||
+ | required screen address: | ||
+ | |||
+ | < | ||
+ | ;x-reg pointing at current char bullet | ||
+ | |||
+ | ldy bullet_row, | ||
+ | lda rowlow,y | ||
+ | sta tmp0 ;zp address | ||
+ | lda rowhi,y | ||
+ | ora # | ||
+ | sta tmp0+1 | ||
+ | ldy bullet_column, | ||
+ | |||
+ | ;lda (tmp0), | ||
+ | ;sta (tmp0), | ||
+ | </ | ||
+ | |||
+ | ===== Examples ===== | ||
+ | |||
+ | |||
+ | |||
+ | 1. A simple example would be a game with following specs: | ||
+ | * one screen buffer | ||
+ | * no scrolling | ||
+ | * bullets moving only left or right | ||
+ | |||
+ | A procedure would look like this: | ||
+ | |||
+ | - check if bullet can be printed on screen | ||
+ | - save char underneath char-bullet | ||
+ | - save colorRAM of original char | ||
+ | - print char on screen and add color | ||
+ | - determine bullet direction | ||
+ | |||
+ | So we need five tables: | ||
+ | |||
+ | < | ||
+ | bullet_row: | ||
+ | bullet_column: | ||
+ | bullet_direction: | ||
+ | charactertmp: | ||
+ | colortmp: | ||
+ | </ | ||
+ | |||
+ | In this case bullet_row=$ff means char bullet is not active and slot can be used. | ||
+ | Each bullet is switched off by setting bullet_row to $ff. | ||
+ | |||
+ | print a new bullet on screen: | ||
+ | |||
+ | < | ||
+ | newbullet: | ||
+ | ldx # | ||
+ | - lda bullet_row, | ||
+ | bmi setbullet | ||
+ | dex | ||
+ | bpl - | ||
+ | rts | ||
+ | |||
+ | setbullet: | ||
+ | lda player_row ; | ||
+ | sta bullet_row, | ||
+ | lda player_column ; | ||
+ | sta bullet_column, | ||
+ | |||
+ | ldy bullet_row, | ||
+ | lda rowlow, | ||
+ | sta tmp0 ;zp address | ||
+ | lda rowhi,y | ||
+ | ora # | ||
+ | sta tmp0+1 | ||
+ | |||
+ | printbullet: | ||
+ | ldy bullet_column, | ||
+ | lda (tmp0), | ||
+ | sta chararctertmp, | ||
+ | lda # | ||
+ | sta (tmp0), | ||
+ | |||
+ | lda tmp0+1 ; | ||
+ | and #$03 | ||
+ | ora #$d8 | ||
+ | sta tmp0+1 | ||
+ | |||
+ | lda (tmp0), | ||
+ | sta colortmp, | ||
+ | lda # | ||
+ | sta (tmp0), | ||
+ | |||
+ | rts | ||
+ | </ | ||
+ | |||
+ | Moving the bullets: | ||
+ | |||
+ | < | ||
+ | ldx #7 | ||
+ | - lda bullet_row, | ||
+ | bmi skip | ||
+ | jsr move1bullet | ||
+ | skip dex | ||
+ | bpl - | ||
+ | rts | ||
+ | |||
+ | move1bullet: | ||
+ | |||
+ | ;restore char and color of orignal char first | ||
+ | |||
+ | ldy bullet_row, | ||
+ | lda rowlow, | ||
+ | sta tmp0 | ||
+ | lda rowhi,y | ||
+ | ora # | ||
+ | sta tmp0+1 | ||
+ | |||
+ | ldy bullet_column, | ||
+ | lda chararctertmp, | ||
+ | sta (tmp0),y | ||
+ | |||
+ | lda tmp0+1 ; | ||
+ | and #$03 | ||
+ | ora #$d8 | ||
+ | sta tmp0+1 | ||
+ | |||
+ | lda colortmp, | ||
+ | sta (tmp0),y | ||
+ | |||
+ | ;now move the bullet | ||
+ | |||
+ | lda bullet_direction, | ||
+ | beq movebullet2left ; | ||
+ | |||
+ | inc bullet_column, | ||
+ | lda bullet_column, | ||
+ | cmp # | ||
+ | bcc + | ||
+ | lda # | ||
+ | sta bullet_row, | ||
+ | rts | ||
+ | + jmp printbullet ; | ||
+ | |||
+ | movebullet2left: | ||
+ | dec bullet_column, | ||
+ | bpl + | ||
+ | lda # | ||
+ | sta bullet_row, | ||
+ | rts | ||
+ | + jmp printbullet ; | ||
+ | </ | ||
+ | |||
+ | ===== Multiple directions ===== | ||
+ | |||
+ | |||
+ | ' | ||
+ | lower four bits for up (bit 0), down (bit 1), left (bit 2) and right (bit 3), similar to the joystick values you get from $dc00. | ||
+ | |||
+ | Moving a bullet in 8 directions could look like this: | ||
+ | |||
+ | < | ||
+ | ;x-reg pointing at current bullet | ||
+ | |||
+ | movebulletup: | ||
+ | lda bullet_direction, | ||
+ | and #1 ;bit 0 set? | ||
+ | beq movebulletdown | ||
+ | |||
+ | dec bullet_row, | ||
+ | bpl movebulletleft ; | ||
+ | lda #$ff | ||
+ | sta bullet_row, | ||
+ | bmi movebulletleft ; | ||
+ | |||
+ | movebulletdown: | ||
+ | lda bullet_direction, | ||
+ | and #2 ;bit 1 set? | ||
+ | beq movebulletleft | ||
+ | |||
+ | inc bullet_row, | ||
+ | lda bullet_row, | ||
+ | cmp # | ||
+ | bcc movebulletleft | ||
+ | lda # | ||
+ | sta bullet_row, | ||
+ | |||
+ | movebulletleft: | ||
+ | lda bullet_direction, | ||
+ | and #4 ;bit 2 set? | ||
+ | beq movebulletright | ||
+ | |||
+ | dec bullet_column, | ||
+ | bpl + | ||
+ | lda # | ||
+ | sta bullet_row, | ||
+ | + rts | ||
+ | |||
+ | movebulletright: | ||
+ | lda bullet_direction, | ||
+ | and #8 ;bit 3 set? | ||
+ | beq + | ||
+ | |||
+ | inc bullet_column, | ||
+ | lda bullet_column, | ||
+ | cmp # | ||
+ | bcc + | ||
+ | lda # | ||
+ | sta bullet_row, | ||
+ | + rts | ||
+ | </ | ||
+ | |||
+ | Manipulate the coordinates like this and then again refresh the screen data (' | ||
+ | |||
+ | |||
+ | ===== Scrolling screen ===== | ||
+ | |||
+ | Scrolling the screen data automatically moves the char bullets as well, of course. | ||
+ | The effect will be a line of char bullets on screen. So the game engine has to delete the char bullets | ||
+ | left behind. This should be done when the hardscrolling is finished. Read the bullet tables to figue out | ||
+ | which bullet is on screen. Adjust the coordinates according to the scrolling direction | ||
+ | and restore the original char of the backdrop. |
base/character_bullets.txt · Last modified: 2018-03-03 12:08 by achim64