Error in Jump & Run Collision
Blitz3D Forums/Blitz3D Beginners Area/Error in Jump & Run Collision
| ||
| Hi, i have found this BMax Code somewhere in this forum: SuperStrict Graphics 800 , 600 , 0 Const Gravity:Float = .1 Type TPlayer Field x:Float,y:Float Field width:Float , height:Float Field speedx:Float , speedy:Float Method Draw() DrawRect x , y , width , height EndMethod Method Update() 'ground friction speedx:* .85 'x conrtols If KeyDown(key_left) Then speedx = - 2 If KeyDown(key_right) Then speedx = 2 'x movement x:+ speedx 'if you ran into a wall If map.rectcollide(x , y , width , height) Then 'move back out of the wall x:- speedx 'stop your speed speedx = 0 EndIf 'y controls (jump) If KeyHit(key_up) Then 'make sure you are on the ground If map.rectcollide(x , y + 1 , width , height) Then 'jump! speedy = - 5 EndIf EndIf 'y movement speedy:+ gravity y:+ speedy 'if you hit a wall If map.rectcollide(x , y , width , height) Then 'move back out of the wall y:- speedy 'stop your speed speedy = 0 EndIf EndMethod EndType Type TMap Field width:Int , height:Int Field array:Int[,] Const tilesize:Int = 30 Method Load() Local x:Int,y:Int Local line:String ReadData width ReadData height array=New Int[width,height] For y = 0 Until height ReadData line For x = 0 Until width array[x , y] = Int(Mid(line , x + 1 , 1) ) Next Next EndMethod Method Draw() Local x:Int , y:Int For y = 0 Until height For x = 0 Until width If array[x , y] = 1 Then DrawRect x * tilesize , y * tilesize , tilesize , tilesize EndIf Next Next EndMethod 'Returns True if the rectangle collides with the map. 'This one and only collision function can be used for everything. Method RectCollide:Int(x:Float , y:Float , width:Float , height:Float) Local x1:Int , y1:Int Local x2:Int , y2:Int 'convert pixel positions to tile positions x1 = x / tilesize y1 = y / tilesize x2 = (x + width) / tilesize y2 = (y + height) / tilesize Local tilex:Int , tiley:Int 'check each tile that the rect is in For tiley = y1 To y2 For tilex = x1 To x2 If array[tilex , tiley] = 1 Then Return True EndIf Next Next Return False EndMethod EndType Global You:tplayer = New tplayer you.x = 200 you.y = 100 you.width = 20 you.height = 25 Global Map:tmap = New tmap map.load() Repeat you.update() you.draw() map.draw() Flip Cls If KeyHit(key_escape) Then End Forever DefData 20,15 DefData "11111111111111111111" DefData "11010101010101010101" DefData "10000000000000000001" DefData "11110000000000111111" DefData "10000000000000000001" DefData "10000000000000000001" DefData "10000000111100000001" DefData "10000000000000000001" DefData "11110000000000000001" DefData "10000000000000000001" DefData "10000000001110001111" DefData "10000000000000000001" DefData "10000000000000000001" DefData "10000000000000000001" DefData "11111111111111111111" I have convert the code zu Blitz3D: Graphics 800,600,16,2 SetBuffer BackBuffer() Global MAPWIDTH = 20 Global MAPHEIGHT = 15 Global TILESIZE = 32 Global Mode = 1 Dim Map(MAPWIDTH,MAPHEIGHT) Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 Data 1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1 Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1 Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 For Y = 1 To MAPHEIGHT For X = 1 To MAPWIDTH Read Map(X,Y) Next Next Const Gravity# = .3 Type TPlayer Field X# Field Y# Field Width# Field Height# Field SpeedX# Field SpeedY# End Type Player.TPlayer = New TPlayer Player\X# = 200 Player\Y# = 100 Player\Width# = 32 Player\Height# = 64 Global t = CreateTimer(60) ; ################################################ Function DrawScreen() For X = 0 To MAPWIDTH For Y = 0 To MAPHEIGHT Select Map(X,Y) Case 1 Color 250,250,250 If Mode = 0 Rect(X*TILESIZE-16,Y*TILESIZE-16,TILESIZE,TILESIZE,1) ElseIf Mode = 1 Rect(X*TILESIZE,Y*TILESIZE,TILESIZE,TILESIZE,1) EndIf End Select Next Next For Player.TPlayer = Each TPlayer Rect(Player\X,Player\Y,Player\Width,Player\Height) Next End Function ; ################################################ Function Update() If KeyHit(57) Mode = 1 - Mode For Player.TPlayer = Each TPlayer ; ground friction Player\SpeedX = Player\SpeedX * .85 ; x controls If KeyDown(203) Player\SpeedX = -2 If KeyDown(205) Player\SpeedX = 2 ; x movement Player\X = Player\X + Player\SpeedX ; i you ran into a wall If Collide(Player\X,Player\Y,Player\Width,Player\Height) ; move back out of the wall Player\X = Player\X - Player\SpeedX ; stop your speed Player\SpeedX = 0 EndIf ; y controls (jump) If KeyHit(200) ; make sure you are on the ground If Collide(Player\X,Player\Y+1,Player\Width,Player\Height) ; jump Player\SpeedY = - 10 EndIf EndIf ; y movement Player\SpeedY = Player\SpeedY + Gravity Player\Y = Player\Y + Player\SpeedY ; if you hit a wall If Collide(Player\X,Player\Y,Player\Width,Player\Height) ;move back out of the wall Player\Y = Player\Y - Player\SpeedY ; stop your speed Player\SpeedY = 0 EndIf Next End Function ; ################################################ Function Collide(X#,Y#,Width#,Height#) Local X1 Local Y1 Local X2 Local Y2 ; convert pixel positions To tile positions X1 = X / TILESIZE Y1 = Y / TILESIZE X2 = (X + Width) / TILESIZE Y2 = (Y + Height) / TILESIZE Local TileX Local TileY ; check Each tile that the Rect is in For TileX = X1 To X2 For TileY = Y1 To Y2 If Map(TileX,TileY) = 1 Then Return True EndIf Next Next Return False End Function ; ################################################ Repeat WaitTimer(t) Cls Update() DrawScreen() Flip 0 Until KeyHit(1) : End It works basically, but all the collisions are set -16 pixels. When i paint the Level -16px all is ok. But this cant be the right way. (Press Space to see what i mean) Can anyone tell me what is the error? Sry for my bad english, Lucius |
| ||
| Your best using blitzbasic's own collision routines for 2d graphics. Mainly imagesoverlap() and imagescollide(). bMAX works with 3D graphics and therefore has to use a slower detection method. I'm not saying that the code won't work though :o) I'm in work and can't help you with the code i'm afraid. |
| ||
| This collision code is based on positions, not on the images. But thanks anyway. Any other users that can help? |
| ||
My guess is that it has something to do with this code:; convert pixel positions To tile positions X1 = X / TILESIZE Y1 = Y / TILESIZE X2 = (X + Width) / TILESIZE Y2 = (Y + Height) / TILESIZEMaybe you have to subtract 1/2 tile to compensate for rounding errors? X1 = X / TILESIZE - .5 (Sorry for not knowing for sure...I'm very tired and can barely stay awake :) |
| ||
| Yes, you are right with the rounding errors. Thank you! :) |