Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Stopping a sprite when hitting background
2004-07-27 08:49
Richard

Registered: Dec 2001
Posts: 621
Stopping a sprite when hitting background

How do I stop a sprite from hitting the background, and let the sprite move around the screen, avoiding contact. This is mainly because my games usually make the player die when it touches the background, which I think gets too repetitive. Reason: I don't know how to stop the player from walking when touching a wall - without the player freezing when you try to move it away from the wall.

The collision routine, which I usually use is (As on Lemon64):

BGRCOL LDA $D01F
LSR A
BCC NOBGCOL
DEC STATUS
LDA STATUS
CMP #$00
BNE NOBGCOL
JMP GAMEOVER
NOBGCOL RTS

Please help.
2004-07-27 10:40
Krill

Registered: Apr 2002
Posts: 2980
using the hw collision detection on the c64 not a very good idea.

first, you can detect collisions only once every frame (afair), thus you'll get problems when having multiplexers.

then, you can only detect which sprites collided, if you have for example 3 bits set in the collision detection register, you dont know which sprite collided with which of the two other ones, or both.

generally i would always recommend to do complete software collision detection, even the most naive approaches with rectangular bounding boxes give sufficient results in most cases.
2004-07-27 10:46
Oswald

Registered: Apr 2002
Posts: 5094
richard: when you detect that the player collided with the wall automagically move it away from the wall within the same routine. So you will cancell the collision state, and you wont get into the infinite collide loop.

Maybe this simpler aproach is enough for what you want to do.
2004-07-27 11:01
Stingray
Account closed

Registered: Feb 2003
Posts: 117
Is this a trick question? not sure If I understood completely. You could give the sprite boundries. You could try a piece of code like this, it's off the top of my head so it could be wrong.

LDA $D000
CMP #$30
BCS SOMEWHERE
LDA #$30
STA $D000

This would stop Sprite 0 from moving any more left then #$30 but you could use a bit of code like this for any sprite in any direction if you know what I mean.

PS You probably know this but I think you could take the fellowing two lines out of the code your useing it should still work the same.

LDA STATUS
CMP #$00
2004-07-28 11:56
cadaver

Registered: Feb 2002
Posts: 1160
That's a horrible question, because the answer totally depends on your game's architecture, and it's not like we should be deciding that for you. Anyway, you could work out a routine to read a char from the screen based on sprite's X,Y coordinates.

When the sprite moves, save previous coordinates. Check using the new coordinates, if there's a collision-causing char under the sprite (for example, anything other than 32). If there is, revert back to saved coordinates.
2004-07-29 14:08
Kenho
Account closed

Registered: Jan 2003
Posts: 26
Sprite coordinates to char coordinates

This works when the sprite x coordinate only is within 0 to 255, additional stuff needs to be done if thats not the case.
(someone add code to that please)
Work out y coord:

the y coord has a formula of:

chary = (spritey-50)/8

to get to the char you use
x + y*40

lda spritey
cec
sbc #$32

why sub with $32 ? that is because the upper border is $32 pixels thick, you need to compensate.


lsr a ; a/2
lsr a ; a/2
lsr a ; a/2
tay

If you divide by two 3 times you have divided by 8. 8 is char width.
you know, on a screen you can have 40 chars. 40 * 8 is 320, ring a bell?



Now here is my solution for easy use of the y coord as i dont want to multiply by 40.
I have made two tables of bytes to be put in 2 consecutive zp adresses. These are screencodes.
As i am in bank 1 my screen starts at $4400. normally if no bankswitching, screen would start at $0400.

The y register now contains a value between 0 and 25 which i can use as an index in my table and put into the zp adresses like this


lda scrlo,y ; 0,28,50 etc
sta $70
lda scrhi,y ;44,44,45 etc
sta $71

Now to get to the x pos of the char you need to do almost the same thing again.

lda spritex
sec
sbc #$18 ; compensate for left border...


lsr a
lsr a
lsr a ;divide by 8
tay

now here comes the trick to get to the char you want:
lda ($70),y ; y in this is the x in x+y*40
cmp #32 ;was there a space char there?
bne hitt ;no space char, then hit

Explanation:
the lda($70),y takes the two consecutive bytes at $70 and $71 and makes them into an adress. for example.
lda #$28
sta $70
lda #$04
sta $71
ldy #3
lda ($70),y would give accum the char at the second row + 3
computer does (($71)*256 + ($70))+y

This are the tables:
scrhi.byte $44,$44,$44,$44,$44,$44,$44,$45,$45,$45,$45,$45
,$45,$46,$46,$46,$46,$46,$46,$46,$47,$47,$47,$47,$47,$47
scrlo .byte$0 ,$28,$50,$78,$a0,$c8,$f0,$18,$40,$68,$90,$b8,
$e0,$08,$30,$58,$80,$a8,$d0,$f8,$20,$48,$70,$98,$c0,$e0

Feel free to suggest other solutions or add something to get the whole spritex (including 9th bit)

Feel free to ask me if someting is unclear (should it be??)

Only my two cents..
2004-07-29 14:21
Kenho
Account closed

Registered: Jan 2003
Posts: 26
Just to add a question to rich about my code. where on the sprite does it hit the char?

2004-07-29 15:35
Richard

Registered: Dec 2001
Posts: 621
Don't know. The side of corner of the sprite perhaps?
2004-07-29 15:43
Oswald

Registered: Apr 2002
Posts: 5094
kenho:

to get the 9th bit of spriteX working simply do this:

lda $d000 ;x coord
lsr $d010 ;9th bit into -> CARRY
ror ;CARRY->into accu->
lsr
lsr

so ror is the same as LSR, just it pushes the CARRY into the MSB of the accumulator instead of 0.

this works only for sprite 0, but you can have a table to convert the actual sprites MSB from $d010, to an 1 or 0 in the Accumulator. Or without a table do more LSRs until the bit u need will get into carry.

the answer to your question:

as the sprites coordinates refer to their topleft corner, this aproach is very rude. Better to check the whole area under the sprite (3x3 char).

this would change your code to:

ldx #2

l1 lda ($70),y
cmp #32
beq hit
iny
cpy #3
bne l1

lda $70
clc
adc #$28
sta $70
bcc *+4
inc $71

dex
bpl l1


hit: (whatever)
2004-07-29 15:57
Richard

Registered: Dec 2001
Posts: 621
Quote: Just to add a question to rich about my code. where on the sprite does it hit the char?



The top of the sprite hits the bottom of the charset and this is a sort of collision.
2004-07-29 16:51
Kenho
Account closed

Registered: Jan 2003
Posts: 26
Thanks for your additions Oswald!

Now its a really great collission routine :-)

edit: cannot get it to work correctly.... i´m lame :-)

2004-07-29 18:21
ToD
Account closed

Registered: Dec 2003
Posts: 10
Quote: Thanks for your additions Oswald!

Now its a really great collission routine :-)

edit: cannot get it to work correctly.... i´m lame :-)



i cant get it to work aswell , seems way out
2004-07-29 18:25
Richard

Registered: Dec 2001
Posts: 621
Same with me....
2004-07-29 19:28
Kenho
Account closed

Registered: Jan 2003
Posts: 26
Some minor changes:

xtmp .byte 0

ldx #3
sty xtmp ;

lda xtmp
clc
adc #4 ;(if x xpanded, #3 otherwize)
sta xtmp

_l1
lda ($70),y
cmp #32
bne _hit
iny
cpy xtmp
bne _l1

lda $70
clc
adc #$28 ;next row
sta $70
bcc _l2
inc $71
_l2
dey
dey
dey
dey ; if x expanded

dex
bne _l1
rts
_hit
inc $d020
rts
2004-07-30 08:05
Oswald

Registered: Apr 2002
Posts: 5094
kenho: oh yeah, my code had some serious bugs, but this happens when one writes code from the top of his head, without any testing :) Sorry!

one thing: X expanded sprites are 6 chars wide, not 4 :)


one word to the part calculating the positon on the character screen:

its a very common way to calculate the onscreen position like that. But you can make it even faster. The table could be made so, that you dont need the sec sbc lsr lsr lsr before.. just ldy $d001 lda tablelo,y sta $70 lda tablehi,y sta $71, well depends how much speed you need :)


a bit of optimization follows, as I cannot stand not to brush up the code:)

ldx #3
sty selfmod+1

_l1

lda ($70),y
cmp #32
bne _hit
iny
lda ($70),y
cmp #32
bne _hit
iny
lda ($70),y
cmp #32
bne _hit

selfmod ldy #$00

lda $70
clc
adc #$28 ;next row
sta $70
bcc _l2
inc $71
_l2

dex
bne _l1
rts

_hit
inc $d020
rts
2004-07-30 11:23
Kenho
Account closed

Registered: Jan 2003
Posts: 26
Really nice Oswald :-) i couldnt stand that lousy variable solution i made either :-)

2004-07-30 12:02
Oswald

Registered: Apr 2002
Posts: 5094
to optimize it even more :) :

instead of selfmod and the 9 bit adc:

tya
clc
adc #$28-2
tay

=)

(y will never overflow)
2005-02-19 13:07
Richard

Registered: Dec 2001
Posts: 621
I have been following a routine which Kenho had supplied, on how to make a sprite collide into the background. This routine seems to work quite nicely if the sprite hits 'the A' character.
Source wrote:

;The sprite collides into the background, therefore we have a sprite to background collision Smile

backcollision: lda sprtpos+1
sec
sbc #$32
lsr
lsr
lsr
tay
lda scrlo,y
sta $70
lda scrhi,y
sta $71
lda sprtpos+0
sec
sbc #$0c
lsr
lsr
tay
ldx #3
sty _selfmod+1

_l1: lda ($70),y
cmp #32
bne _hit
iny
lda ($70),y
cmp #32
bne _hit
iny
lda ($70),y
cmp #32
bne _hit

_selfmod: ldy #$00
lda $70
clc
adc #$28 ;next row
sta $70
bcc _l2
inc $71

_l2: dex
bne _l1
rts

_hit: inc $d027
rts



xtmp: dc.b 00
killerchars: dc.b $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1a,$1b,$1c,$1d,$1e,$1f
dc.b $20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35
dc.b $36,$37,$38,$39,$3a,$3b,$3c,$3d,$3e,$3f,$40,$41,$42,$43,$44,$45
dc.b $46,$47,$48,$49,$4a,$4b,$4c,$4d,$4e,$4f,$50,$51,$52,$53,$54,$55
dc.b $56,$57,$58,$59,$5a,$5b,$5c,$5d,$5e,$5f,$60,$61,$62,$63,$64,$65
dc.b $66,$67,$68,$69,$6a,$6b,$6c,$6d,$6e,$6f,$70,$71,$72,$73,$74,$75
dc.b $76,$77,$78,$79,$7a,$7b,$7c,$7d,$7e,$7f,$80,$81,$82,$83,$84,$85
dc.b $86,$87,$88,$90,$8a,$8b,$8c,$8d,$8e,$8f,$90,$91,$92,$93,$94,$95
dc.b $96,$97,$98,$99,$9a,$9b,$9c,$9d,$9e,$9f,$a0,$a1,$a2,$a3,$a4,$a5
dc.b $a6,$a7,$a8,$a9,$aa,$ab,$ac,$ad,$ae,$af,$b0,$b1,$b2,$b3,$b4,$b5
dc.b $b6,$b7,$b8,$b9,$ba,$bb,$bc,$bd,$be,$bf,$c0,$c1,$c2,$c3,$c4,$c5
dc.b $c6,$c7,$c8,$c9,$ca,$cb,$cc,$cd,$ce,$cf,$d0,$d1,$d2,$d3,$d4,$d5
dc.b $d6,$d7,$d8,$d9,$da,$db,$dc,$dd,$de,$df,$e0,$e1,$e2,$e3,$e4,$e5
dc.b $e6,$e7,$e8,$e9,$ea,$eb,$ec,$ed,$ee,$ef,$f0,$f1,$f2,$f3,$f4,$f5
dc.b $f6,$f7,$f8,$f9,$fa,$fb,$fc,$fd,$fe,$ff,$ff,$ff,$ff,$ff,$ff,$ff

scrhi: dc.b $44,$44,$44,$44,$44,$44,$44,$45,$45,$45,$45,$45,$45,$46,$46,$46,$46,$46,$46,$46, $47,$47,$47,$47,$47,$47
scrlo: dc.b $00,$28,$50,$78,$a0,$c8,$f0,$18,$40,$68,$90,$b8,$e0,$08,$30,$58,$80,$a8,$d0,$f8, $20,$48,$70,$98,$c0,$e0


However I am still stuck regarding setting 'kill blocks' for my Real Speed We Need game project. I had to keep resetting the code from how it was, but I would like to import my kill tables into this particular routine, so that if a block is located according to the kill table, the sprite to background collision is detected.

2007-07-17 18:04
Richard

Registered: Dec 2001
Posts: 621
(Continued from Kehno's example)

Hi again. Oh not again, it is the return of an old topic :P

I am having problems with the sprite/background collision routine.

I'm doing a game, but having problems with the player sprite/background collision.

What I am trying to do is make the sprite stop *by* the rocks (which are built as 2x2 chars). The sprite is full size as 1 filled square. When the player sprite moves from the left to the right hand side of the rock, this works nicely, however, when the player moves from the right, to the left of the rock, it somehow stops on the whole char. The routine looks something like this:

;Player sprite to background collision routines

BACKCOLLISION: LDA OBJPOS+$01
SEC
SBC #$32
LSR
LSR
LSR
TAY
LDA SCRLO,Y
STA $70
LDA SCRHI,Y
STA $71
LDA OBJPOS+$00
SEC
SBC #$0C
LSR
LSR
TAY
LDX #3
STY _SELFMOD+1

_L1: INY
LDA ($70),Y
CMP #65
BEQ _HIT


LDA ($70),Y

CMP #65 ;Player touches the food,
BEQ _HIT; if touched the food is off screen
CMP #66;
BEQ _HIT;
CMP #67;
BEQ _HIT;
CMP #68;
BEQ _HIT;
INY
LDA ($70),Y
CMP #65
BEQ _HIT
CMP #67
BEQ _HIT
CMP #66
BEQ _HIT
CMP #68
BEQ _HIT
CMP #$56 ;Player touches the switch char
BEQ _SWITCH ;if touched, the switch will turn
CMP #$57 ;all the water into food
BEQ _SWITCH
CMP #$58
BEQ _SWITCH
CMP #$59
BEQ _SWITCH

CMP #$4A ;Player touches the water chars
BEQ _WATER ;if the player touches the water
CMP #$4B ;he will drown
BEQ _WATER
CMP #$4C
BEQ _WATER
CMP #$4D
BEQ _WATER
CMP #$4E
BEQ _WATER
CMP #$52 ;Player touches the rock chars
BEQ _ROCK ;if touched, then the player
CMP #$53 ;will stop according to the
BEQ _ROCK ;direction he moves
CMP #$54
BEQ _ROCK
CMP #$55
BEQ _ROCK
INY
JMP _SELFMOD





;LDA ($70),Y
;CMP #16
;BPL _HIT

_SELFMOD:
MODE2: LDY #$00
LDA $70
CLC
ADC #$28 ;NEXT ROW
STA $70
BCC _L2
INC $71

_L2: DEX
BNE _L1
RTS


_WATER: JSR PLAYER_DROWN ;Because player touched water, he drowns
RTS
_HIT: LDA #73
STA ($70),Y
JSR SCORE
JSR ADDFOOD
;CMP #$00
;BEQ LEVELDONE

NO: RTS
_SWITCH JSR WATER_TO_FOOD ;Turn water into food
RTS

_ROCK JSR STOP_AT_ROCK ;Stop player moving
RTS

STOP_AT_ROCK LDA DIRFACE
CMP #$01
BEQ STOPATUP
CMP #$02
BEQ STOPATDOWN
CMP #$03
BEQ STOPATLEFT
CMP #$04
BEQ STOPATRIGHT
RTS

Please can you help me solve this problem, why the sprite stops right in the middle of the rock, when it is supposed to stop right next to it (when moving left)?
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
XmikeX
E$G/HF ⭐ 7
Guests online: 95
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.6)
5 Edge of Disgrace  (9.6)
6 What Is The Matrix 2  (9.6)
7 The Demo Coder  (9.6)
8 Uncensored  (9.6)
9 Comaland 100%  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 No Listen  (9.6)
2 Layers  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.6)
6 X-Mas Demo 2024  (9.5)
7 Dawnfall V1.1  (9.5)
8 Rainbow Connection  (9.5)
9 Onscreen 5k  (9.5)
10 Morph  (9.5)
Top Groups
1 Performers  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Censor Design  (9.3)
5 Triad  (9.3)
Top Webmasters
1 Slaygon  (9.6)
2 Perff  (9.6)
3 Sabbi  (9.5)
4 Morpheus  (9.4)
5 CreaMD  (9.1)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.091 sec.