Collision problem

Advanced game related topics
ChebbyShabby
Enthusiast
Enthusiast
Posts: 121
Joined: Mon Jun 26, 2006 10:47 am

Collision problem

Post by ChebbyShabby »

i'm coding a game and i currently have this in the main event code:

Code: Select all

If SpriteCollision(#Player, x, Y, #Platform, xX, yY) And x + SpriteWidth(#Player) > xX And Y<yY
      x = xX - SpriteWidth(#Platform)
EndIf
where x and y are the coordinates of the player while xX and yY are the coordinates of the platform. the code basically checks if the player has collided with the platform from the left.

and this too (for movement)...

Code: Select all

If KeyboardPushed(#PB_Key_Right)
    x + 5
EndIf
the problem is that when the player collides with the platform from the left, he moves inside the block and when the user lets go of the right key button he stops. how do i stop this?
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

if you already compare x with xX and y with yY, you don't need ne collision anymore.

you should not set the coordinate of the player directly on collision,
better just manipulate it, to keep it possible to move tha player further.
oh... and have a nice day.
ChebbyShabby
Enthusiast
Enthusiast
Posts: 121
Joined: Mon Jun 26, 2006 10:47 am

Post by ChebbyShabby »

what do you mean? note that the comparison of the x and xX and y and YY are only half. that is, if a player was anywhere to the left of or underneath the box it would still count as a collision.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

then complete the coordinate check.
it is surely better, because you want to react if the feet of the player hit the elevator, not if his head does.

and you don't need to request the width of the sprite, it is a fixed value,
so better carry it in a variable, it's faster then a function-call.

and the main problem still is, you set x to a fix value there,
so your player will move to that new position, every time the condition is true.
oh... and have a nice day.
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

Kaeru, do you mean that the player should BOUNCE BACK?

I do miss the built in collision system in BB!
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

I dunno what he wants to do exactly. it's just too little information.

but I can say, that it's most times not useful, to set an absolut position as reaction to a collision.

and I can say, that four coordinate-checks are better than one collision check plus two coordinate checks.


> I do miss the built in collision system in BB!
I don't know what it can, but would it be that difficult, to implement such things?
you are talking about 2D, do you?
oh... and have a nice day.
ChebbyShabby
Enthusiast
Enthusiast
Posts: 121
Joined: Mon Jun 26, 2006 10:47 am

Post by ChebbyShabby »

you don't understand -- everything works perfectly; the consequences you claim, such as "the main problem still is, you set x to a fix value there,
so your player will move to that new position, every time the condition is true", do not happen. instead, the player stops where he's supposed to. the main problem is that before the player stops, he moves into the block.

lemme try to explain this better: when the player collides into a platform, he goes into it first, and when the user lets go of the keyboard, THEN the player moves where he's supposed to.

and 4-point coordinate checks give me the same result anyway.
User avatar
Demivec
Addict
Addict
Posts: 4283
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

ChebbyShabby wrote:lemme try to explain this better: when the player collides into a platform, he goes into it first, and when the user lets go of the keyboard, THEN the player moves where he's supposed to
It seems as if your display is out of sequence.

Code: Select all

You are using:

 * Calculate new positions
 * display updated positions
 * check for collisions and correct new positions if something collided.


You should use:

 * Calculate new positions
 * check for collisions and correct new positions if something collided.
 * display updated positions
According to your words, the detection works fine. If that is true why are you asking for help on the detection? You would need a larger snippet of your code that includes display as well as calculation to demonstrate the problem you're having so you could get the needed input (from the forum).
Last edited by Demivec on Wed Aug 29, 2007 7:41 am, edited 1 time in total.
ChebbyShabby
Enthusiast
Enthusiast
Posts: 121
Joined: Mon Jun 26, 2006 10:47 am

Post by ChebbyShabby »

give me your email and i'll send the file to you (if this isn't a problem). i can't find any free upload sites which don't require creating an account.

but here is the main code:

Code: Select all

; Platform scroller example
; 2007
; Adam Boulfoul
;

;-Physics variables
Gravity.f = 0.5

;-Load the level
Procedure CountLines(file$)
  If ReadFile(0,file$)
    l = Lof(0)
    m = AllocateMemory(l)
    ReadData(0,m,l)
    m$ = PeekS(m)
    FreeMemory(m)
    CloseFile(0)
  EndIf;
  ProcedureReturn CountString(m$,Chr(10))
EndProcedure;
n = CountLines("Level.txt")

Dim pX.l(n)
Dim pY.l(n)

ReadFile(1,"Level.txt")
While Eof(1) = 0
  a + 1
  If a & 1
    pX(a) = Val(ReadString(1))
  Else
    pY(a) = Val(ReadString(1))
  EndIf
Wend
CloseFile(1)

;-Prepare the screen
InitKeyboard()
InitSprite()

OpenScreen(640,480,32,"")
SetFrameRate(60)

;-Prepare the sprites
Enumeration
  #Player
  #Platform
EndEnumeration

LoadSprite(#Player,"Eraser.bmp")
LoadSprite(#Platform,"Platform.bmp")

x = 30
Repeat
  FlipBuffers()
  ClearScreen(RGB(0,0,0))
    
  ;-Display the level
  For i = 0 To n
    If i & 1
      xX = pX(i)
      yY = pY(i + 1)
    EndIf
    If pX(i) <> 0
      DisplayTransparentSprite(#Platform,xX,yY)
    EndIf
  Next
      
  DisplayTransparentSprite(#Player,x,Y)
  
  ;-Jump physics
  Velocity = Power - (Gravity * FlightTime) ;Adaptation of "v = u + at"
  FlightTime + 1
  y - Velocity
  
  ;-Collision detection
  For i = 1 To n
    If i & 1
      xX = pX(i)
      yY = pY(i + 1)
    EndIf
    
    If x<xX + 15 And x + 15>xX And Y + 24>yY And Y<yY ;Collision with TOP of platform
      FlightTime = 0
      Power = 0
      y = yY - SpriteHeight(#Player)
    EndIf
    If x<xX + 20 And x>xX And Y + 24>yY And Y<yY ;Collision with RIGHT of platform
      x = xX + 20
    EndIf
    If x + 20>xX And x<xX + 20 And Y + 24>yY And Y<yY ;Collision with LEFT of platform
      x = xX - 20
    EndIf
  Next i
    
  ;-Horizontal movement
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Left)
    x - 5
  ElseIf KeyboardPushed(#PB_Key_Right)
    x + 5
  EndIf
  
  ;-Jump
  If KeyboardPushed(#PB_Key_Space): Power = 10: EndIf
  
Until KeyboardPushed(#PB_Key_Escape)
End
the platform sprite is just a 20x20 block and the player sprite is just a 24x24 block and the level is a txt file.
User avatar
Demivec
Addict
Addict
Posts: 4283
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

I've sent you my e-mail via a PM.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

i can't find any free upload sites which don't require creating an account.
what about www.uploaded.to or www.upload.sc ?
oh... and have a nice day.
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

the platform sprite is just a 20x20 block and the player sprite is just a 24x24 block and the level is a txt file.
Actually if that is true you could create the blocks inside the program and use [c*de][/c*de] to show us the text file as well...
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
ChebbyShabby
Enthusiast
Enthusiast
Posts: 121
Joined: Mon Jun 26, 2006 10:47 am

Post by ChebbyShabby »

ok. sorry for the delay (and thanks, kaeru), people. here's the link anyway:

http://uploaded.to/?id=epm1mw
User avatar
Demivec
Addict
Addict
Posts: 4283
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

Here is an example of some changes that would help:

Code: Select all

;-Physics variables
Gravity.f = 0.5

;-Load the level
Procedure CountLines(file$)
  If ReadFile(0,file$)
    l = Lof(0)
    m = AllocateMemory(l)
    ReadData(0,m,l)
    m$ = PeekS(m)
    FreeMemory(m)
    CloseFile(0)
  EndIf;
  ProcedureReturn CountString(m$,Chr(10))/2
EndProcedure;
n = CountLines("Level.txt")-1

;Dim pX.l(n)
;Dim pY.l(n)
Dim p.POINT(n)

ReadFile(1,"Level.txt")
; While Eof(1) = 0
  ; a + 1
  ; If a & 1
    ; pX(a) = Val(ReadString(1))
  ; Else
    ; pY(a) = Val(ReadString(1))
  ; EndIf
; Wend
For I=0 To n
  p(I)\x=Val(ReadString(1))
  p(I)\y=Val(ReadString(1))
Next 



CloseFile(1)

;-Prepare the screen
InitKeyboard()
InitSprite()

OpenScreen(640,480,32,"")
SetFrameRate(60)

;-Prepare the sprites
Enumeration
  #Player
  #Platform
EndEnumeration

LoadSprite(#Player,"Eraser.bmp")
LoadSprite(#Platform,"Platform.bmp")
playerHeight = SpriteHeight(#Player)
playerWidth = SpriteWidth(#Player)
platformHeight = SpriteHeight(#Platform)
platformWidth = SpriteWidth(#Platform)
diffWidth = (playerWidth - platformWidth) / 2
diffHeight = (playerHeight - platformHeight) / 2

x = 30
Repeat
  FlipBuffers()
  ClearScreen(RGB(0,0,0))
    
  ;-Display the level
  For I = 0 To n
    ; If I & 1
      ; xx = pX(I)
      ; yy = pY(I + 1)
    ; EndIf
    ; If pX(I) <> 0
      ; DisplayTransparentSprite(#Platform,xx,yy)
    ; EndIf
      xx = p(I)\x
      yy = p(I)\y
      DisplayTransparentSprite(#Platform,xx,yy)
  Next
      
  DisplayTransparentSprite(#Player,x,y)
  
  ;-Jump physics
  Velocity = Power - (Gravity * FlightTime) ;Adaptation of "v = u + at"
  FlightTime + 1
  y - Velocity
  
  ;-Horizontal movement
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Left)
    x - 5
  ElseIf KeyboardPushed(#PB_Key_Right)
    x + 5
  EndIf
  
  ;-Jump
  If KeyboardPushed(#PB_Key_Space): Power = 10: EndIf  
  ;-Collision detection
  For I = 0 To n
  ; For I = 1 To n
    ; If I & 1
      ; xx = pX(I)
      ; yy = pY(I + 1)
    ; EndIf
      xx = p(I)\x
      yy = p(I)\y
    
      ;If x<xx + 15 And x + 15>xx And y + 24>yy And y<yy ;Collision with TOP of platform
      If (xx - 19)<x And x<(xx + 15) And (yy - playerHeight)<y And y<(yy - diffHeight) And Velocity<0;Collision with TOP of platform
        FlightTime = 0
        Power = 0
        ;y = yy - SpriteHeight(#Player)
        y = yy - playerHeight
      EndIf
      If (xx - 19)<x And x<(xx + 15) And (yy - diffHeight)<y And y<(yy + platformHeight) And Velocity>0;Collision with BOTTOM of platform
        FlightTime = 20
        y = yy + platformHeight
      EndIf
    ;If x<xx + 20 And x>xx And y + 24>yy And y<yy ;Collision with RIGHT of platform
    If (xx - diffWidth)<x  And x<(xx + platformWidth) And (yy - playerHeight)<y And y<yy ;Collision with RIGHT of platform
      x = xx + platformWidth
    EndIf
    ;If x + 20>xx And x<xx + 20 And y + 24>yy And y<yy ;Collision with LEFT of platform
    If (xx - playerWidth)<x And x<(xx - diffWidth) And (yy - playerHeight)<y And y<yy ;Collision with LEFT of platform
      x = xx - playerWidth
    EndIf
  Next I
    

  
Until KeyboardPushed(#PB_Key_Escape)
End
The major change thoughis to move the collision checking before the displaying section. Your code does: display,checking,moving. It now does: display,moving,checking.

I made some small changes also. I changed the variables and loops for accesing the level data. Instead of pX() and pY() where only every other index had any data it now uses p.point() and every index contains data. This gives p(i)\x=x and p(i)\y=y.
I rearranged the terms in your collision checking to assist with one other small problem. Each now shows that a coodinate of 5<x<12 as "5<x and x<12" to make it easier to see the range the variable is in.
The player was allowed to go partially in to the Left of the platform but not the right. This was fixed with coordinates being adjusted, though I personally think it would be appropriate to have overlap on the platform in both left and right directions.
I substituted variables for the heights, widths and the difference of widths for the player and platforms. This is so you could see the way the formula was constructed easier. You may prefer to replace these with a constant value. In the meantime it allows you to change somethings a little easier.
I added a collision method for overhanging platforms, in case you add that in other levels. To demonstrate it I added three platforms to the beginning of your level.txt file:

Code: Select all

310
310
330
290
350
270
The collision includes the direction of travel (velocity) to determine if the player moved into a platform from above or below. This included a small modification to the collision from the TOP code.

The collision method still has at least one case that it can't handlel. This is if a block is falling and moving into a platform on the left.
ChebbyShabby
Enthusiast
Enthusiast
Posts: 121
Joined: Mon Jun 26, 2006 10:47 am

Post by ChebbyShabby »

thank you so much, dem :D. great help. now i'll just sit here and try to work out how to stop the case of jumping and moving to the left of the platform as well as why there's overlapping if this happens from the right. still, your work is appreciate.

Edit: also, i see you used mechanics/physics concepts to make FlightTime equal to 20 when falling down. can i just ask, what do you do in uni and what did you study at school?
Post Reply