Platform Collision
BlitzPlus Forums/BlitzPlus Programming/Platform Collision
| ||
Hello, I'm using BlitzPlus to get the hang of the basic mechanics behind a platform game. My problem is with the collision detection between the player sprite and the floor. The play area is 640x480, divided in to tiles of 8x8, and the player sprite is 15x16 pixels. (x,y) The code I have used checks all of the tiles around the player at any given time. Using this information it knows if the player should be falling, walking on the floor etc This is all great, however, I'm finding that the player sprite doesn't always land flush with the floor tile. Sometimes the player lands pixel perfectly on the top of the floor, other times the players feet dip a few pixels below and overlap in to the floor. Can anybody throw some light on it for me? Cheers! *******Code now follows********** AppTitle "Little Platformer" ;Player Variables Global frmplayer, tmrplayer ;player animation Global playerx, playery, jumping ;player position/status Global ladderpresent ;is the player on a ladder Global tileleft Global tileright Global tileabove Dim tilebelow(1) Dim tileon(1) ;Player constants playerx=250 ;start position playery=455 ;Environment Variables Global gravity#,yspeed# ;Environment Constants gravity =.3;Affects jump jump#= -5 ;jump height speedx#=0 ;ground friction ;Level variables Dim level(79,59) ;MAIN PROGRAM; ;************; ;Prepare Screen Graphics 640,480,16,1 ;set resolution ;load player animation and mask gfxplayer=LoadAnimImage("c:\dk\player.bmp",15,16,0,12) MaskImage gfxplayer,255,0,255 ;load level gfx floorgfx=LoadImage("C:\dk\floor.bmp") MaskImage floorgfx,255,0,255 laddergfx=LoadImage("C:\dk\ladder.bmp") MaskImage laddergfx,255,0,255 ;Load the current level from file to the array filein = ReadFile("c:\dk\levels\level1.txt") For y = 0 To 59 For x = 0 To 79 level(x,y) = ReadByte(filein) ;read 1 byte at a time Next Next CloseFile(filein) ;MAIN GAME LOOP; ;**************; While Not KeyDown(1) ;until esc is pressed SetBuffer BackBuffer() Cls ;draw the level/objects on screen ;Floor tiles For y = 0 To 59 For x = 0 To 79 Select level(x,y) Case 49 DrawImage floorgfx,x*8,y*8 Case 50 DrawImage laddergfx,x*8,y*8 End Select Next Next ;draw the player DrawImage gfxplayer,playerx,playery,frmplayer ;discover players immediate surroundings tilebelow(0) = level(playerx/8,(playery/8)+2) tilebelow(1) = level((playerx/8)+1,(playery/8)+2) tileabove = level(playerx/8,(playery/8)-1) tileleft = level((playerx/8)-2,playery/8) tileright = level((playerx/8)+2,playery/8) tileon(0) = level(playerx/8,playery/8) tileon(1) = level(playerx/8+1,playery/8) ;check collisions against surroundings If tileon(0) = 49 Or tileon(1) = 49 And yspeed <= 0 Then ;stop jumping you have hit your head yspeed=0 End If If tileon(0) = 50 Or tileon(1) = 50 Then ;player is over a ladder ladderpresent=1 Else ladderpresent=0 End If If tilebelow(0) = 49 Or tilebelow(1) = 49 And yspeed >=0 Then ;stop if you are falling and land on a tile jumping = 0 yspeed=0 End If If tilebelow(0) = 48 And tilebelow(1) = 48 Then ;falling if nothing is below jumping=1 End If ;check player input and update accordingly If JoyX()=-1 Then ;left ;friction speedx = speedx -.2 If speedx < -2 Then speedx = -2 If MilliSecs() > tmrplayer + 100 Then tmrplayer=MilliSecs() ; 'reset' the timer frmplayer=( frmplayer + 1 ) Mod 3 ; increment the frame, flip to 0 if we are out End If EndIf If JoyX()=+1 Then ;right speedx = speedx +.2 If speedx > 2 Then speedx=2 If MilliSecs() > tmrplayer + 100 Then tmrplayer=MilliSecs() ; 'reset' the timer frmplayer=3+( frmplayer + 1 ) Mod 3; increment the frame, flip to 0 if we are out End If EndIf If JoyY()=-1 And ladderpresent=1 Then ;up if a ladder is present playery=playery-1 ;only go up if there is more ladder If MilliSecs() > tmrplayer + 100 Then tmrplayer=MilliSecs() ; 'reset' the timer If frmplayer=8 Then frmplayer=10 Else frmplayer=8 EndIf End If EndIf If JoyY()=+1 And ladderpresent=1 Then ;down if a ladder is present playery=playery+1 ;only go down if there is more ladder to go down If MilliSecs() > tmrplayer + 100 Then tmrplayer=MilliSecs() ; 'reset' the timer If frmplayer=8 Then frmplayer=10 Else frmplayer=8 EndIf End If EndIf If JoyHit(1) And jumping=0 Then ;jump if not already jumping = 1 ;the player is mid-jump yspeed# = jump# EndIf If jumping=1 ; check that we have pushed the jump key YSpeed# = YSpeed# + Gravity# ; this will calculate the y location in pixels If yspeed# > 4 Then yspeed# = 4 playery = playery + YSpeed ; this will add our calculated number to our current y position End If ;updates on player variables speedx = speedx * .88 ;friction playerx = playerx + speedx ;update player x position ;debugging ;Show tilesbelow ;Rect(playerx,playery+16,8,8,0) ;Rect(playerx+8,playery+16,8,8,0) ;show tileon ;Rect(playerx,playery,8,8,0) ;Rect(playerx+8,playery,8,8,0) Flip ;draw the screen Wend |
| ||
First, move the line where you draw the player:DrawImage gfxplayer,playerx,playery;,frmplayer Before the line: If JoyY()=-1 And ladderpresent=1 Then ;up if a ladder is present So that the player is drawn right after checking the collisions. In this collision code, there are two parts that stop the jumping with "yspeed = 0" Before that line, insert: playery=playery / 8 * 8 This will place the player back on a whole tile again after a jump. In your main loop, you are setting the buffer, "SetBuffer BackBuffer()" I don't know if it matters much, but it can be moved before the loop. |
| ||
b32, thank you for taking the time to check this for me. The line "playery=playery / 8 * 8" was exactly what I needed. What can I say...it was late! I've also moved the setbuffer line out of the main loop as it's not required as you mention. Many thanks! Neil |