Hello everybody,
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):
But converting the Y-value into the TempLow/High part.....
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 ?
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:
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)
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)
But converting the Y-value into the TempLow/High part.....
Code:
; 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
; 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 ?