For some while, I've been trying to find the background tile number of the tile based on the location of my sprite.
I've been reading (and learning) in these threads:
8x16 sprite is really a 16x32 pixel image?
Object collision
But I still have some trouble figuring it out and fitting it all together. Maybe someone can give me some pointers ?
Here are the things I think I understand (feel free to correct if somethings wrong):
- Background tiles are stored in an 1D array ==> one after the other
- Sprite location is in 2D (x,y coordinates)
- So we have to use a conversion, depending on the height and width of the background sprites
- For this we can use the formula: (y / MetatilesWidth) * NumberOfMetatilesPerRow + (x / MetatileHeight)
- I have 8x8 tiles as background (so the above formula should say: "tiles" instead of "Metatiles", correct ?)
- So if my sprite location is for example (x,y) = (15,31) it would give: (31/8) * 32 + (15/8) = 3*32 + 1 = 97
- The background tile (at location x,y) is then the 97th one in my 1D array of background tiles
- I may not multiply by 4 instead of 32/8 because the division is used to round the y value of my sprite to a multiple of 8
- I can however do an AND #%11111000 and multiply by 4
- because our 1D-array has values bigger then 255 => we need a 16 bit variable to be able to get it out of the array.
And that's where I'm stuck. I know that all I have to do is load the 97th tile in my background array.
But I'm stuck with converting the (x,y) position to a 16 bit number and then extracting the tile number out of my array with that 16 bit number.
1) The 16 bit variable:
- Do I need to reserve 2 variables ? For example: TempLow and TempHigh.
- I first need to reserve the Low variable (little endian thing ? )
- Or is it allowed to create 1 variable and reserve 2 bytes of space (just Temp) ? Is there then a method to load/store from the high part of this variable ? Or will I run into problem later on by not creating 2 seperate variables ?
- Getting the x-value into the TempLow (or just Temp) will be no problem (I think):
Code: Select all
LDA Sprite_position_X ; Load A with the X position of my sprite
LSR A ; divide by 2 ==> X/2
LSR A ; divide by 2 ==> X/4
LSR A ; divide by 2 ==> X/8
STA TempLow ; store A now into the TempLow variable (or lower part of Temp)
Code: Select all
; we need to divide by 8 (to know the amounts of rows we have)
; and then multiply by 32 (32 tiles a row)
LDA Sprite_position_Y ; Load A with the Y position of my sprite
AND #%11111000 ; this is the same as dividing by 8 and multiplying by 8. But still necessary to get rid of the last 3 digit's. Only have to multiply by 4
ASL A ; multiply by 2 ==> if we started above with 1111 1111 ==> AND would give 1111 1000 ==> ASL would give 1111 0000
ASL A ; multiply by 2 ==> Next ASL would give 1110 0000
CLC ; clear the carry
ADC TempLow ; add the value we got from out of sprite X to A.
STA TempLow; Store back into TempLow
; In case the carry is set in the addition ==> add one to the High part of the variable, do not clear carry ?
LDA Sprite_position_Y ; Load A with the Y position of my sprite
; 1111 1111 ==> the interesting bits are the 2 most left ones (6 other ones are already added in the low byte part)
LSR A ==> 1111 1111 ==> becomes 0111 1111
LSR A ==> 1111 1111 ==> becomes 0011 1111
LSR A ==> 1111 1111 ==> becomes 0001 1111
LSR A ==> 1111 1111 ==> becomes 0000 1111
LSR A ==> 1111 1111 ==> becomes 0000 0111
LSR A ==> 1111 1111 ==> becomes 0000 0011
; do not clear the carry here !
ADC $00 ; add the carry to A
STA TempHigh; Store into TempHigh
2) To get the Tile number with the 16 variable ?
To get my background tile I have seen other people use these:
LDA background, x ==> this will load A with the value at background and add x ==> for example 8 + 2
LDA [background], x ==> this will load A with the value at x places beyond background
Do I now need to Load X with the 16 bit variable ? This isn't possible ? x is only 8 bit ?
PS/ Why does ASM 6502 has no LSL and/or ASR opcode ? I assume there is no difference between a Logical Shift and an Arithmetic Shift ?
Why then, haven't they used either LSR+LSL or ASR+ASL ? Instead of a combo of the two ?