I've been thinking about creating a simple platform game, and am already having trouble with the collisions. I took some .bb source code that someone posted on CodersWorkshop, ported it to blitzmax, giving me this:
It works, in a sense, but is far from perfect. At times, it will put me off of the screen for no apparent reason, along with a few other quirks. I was wondering, for one, can anyone tell me what I can improve/fix to make the collisions work better? Even better, does anyone have some blitzmax code already written that shows basic collision detection? All help is appreciated.
SuperStrict '********************************** screen constants Const SCREEN_WIDTH:Int = 800 Const SCREEN_HEIGHT:Int = 600 Const FULL_SCREEN:Int = False Const HERTZ:Int = 60 '********************************** grid constants Const MAP_WIDTH:Int = 20 Const MAP_HEIGHT:Int = 15 Global map:Int[MAP_WIDTH,MAP_HEIGHT] '********************************** player state enumeration Const ST_NORMAL:Int = 0 Const ST_FALLING:Int = 1 Const ST_JUMPING:Int = 2 '********************************** Const GRAVITY:Float = .2 Const TILE_SIZE:Int = 40 Const DIR_RIGHT:Int = 2 Const DIR_LEFT:Int = 1 Graphics SCREEN_WIDTH,SCREEN_HEIGHT,FULL_SCREEN,HERTZ Global player:Tplayer = New Tplayer player.x = 200 player.y = 200 'player.state = ST_FALLING player.bg_width = 40 player.bg_height = 40 fillmap() While Not KeyDown(KEY_ESCAPE) drawmap() player.update() DrawText("x: " + player.x,50,50) DrawText("y: " + player.y,50,70) DrawText("state: " + player.state,50,90) Flip Cls Wend Function drawmap() For Local loop_x:Int = 0 To MAP_WIDTH - 1 For Local loop_y:Int = 0 To MAP_HEIGHT - 1 SetColor map[loop_x,loop_y] * 255,60,60 DrawRect loop_x*TILE_SIZE,loop_y * TILE_SIZE,TILE_SIZE,TILE_SIZE Next Next End Function Type Tplayer Field x:Float Field y:Float Field xv:Float Field yv:Float Field id:String Field state:Int Field direction:Int Field distance:Int Field bg_width:Int 'bounding box width Field bg_height:Int 'bounding box height Method Update() checkkeys() draw() End Method Method draw() SetColor 255,255,255 DrawRect x,y,bg_width,bg_height End Method Method RightCollision:Int(speed:Float) For Local loop_x:Int = 0 To MAP_WIDTH - 1 For Local loop_y:Int = 0 To MAP_HEIGHT - 1 If rectsoverlap(x + speed + 1, y, bg_width, bg_height, loop_x * TILE_SIZE, loop_y * TILE_SIZE, TILE_SIZE, TILE_SIZE) Select map[loop_x,loop_y] Case 1 distance = (loop_x * TILE_SIZE) - (x + bg_width) Return True End Select EndIf Next Next End Method Method LeftCollision:Int(speed:Float) For Local loop_x:Int = 0 To MAP_WIDTH - 1 For Local loop_y:Int = 0 To MAP_HEIGHT - 1 If rectsoverlap(x + speed - 1, y, bg_width, bg_height, loop_x * TILE_SIZE, loop_y * TILE_SIZE, TILE_SIZE, TILE_SIZE) Select map[loop_x,loop_y] Case 1 distance = x - ((loop_x + 1) * bg_width) Return True End Select EndIf Next Next End Method Method BottomCollision:Int(speed:Float) For Local loop_x:Int = 0 To MAP_WIDTH - 1 For Local loop_y:Int = 0 To MAP_HEIGHT - 1 If rectsoverlap(x, y + speed + 1, bg_width, bg_height, loop_x * TILE_SIZE, loop_y * TILE_SIZE, TILE_SIZE, TILE_SIZE) Select map[loop_x,loop_y] Case 1 distance = (loop_y * TILE_SIZE) - (Y + bg_width) Return True End Select EndIf Next Next End Method Method TopCollision:Int(speed:Float) For Local loop_x:Int = 0 To MAP_WIDTH - 1 For Local loop_y:Int = 0 To MAP_HEIGHT - 1 If rectsoverlap(x, y + speed - 1, bg_width, bg_height, loop_x * TILE_SIZE, loop_y * TILE_SIZE, TILE_SIZE, TILE_SIZE) Select map[loop_x,loop_y] Case 1 distance = ((loop_y + 1) * TILE_SIZE) - (y) Return True End Select EndIf Next Next End Method Method checkkeys() Select state Case ST_NORMAL If Not bottomCollision(yv) state = ST_FALLING EndIf Case ST_FALLING yv = yv + GRAVITY If bottomCollision(yv) And state <> ST_JUMPING yv = 0 y = y + distance state = ST_NORMAL EndIf Case ST_JUMPING If topCollision(yv) yv = 0 y = y + distance state = ST_FALLING EndIf yv = yv + GRAVITY If yv >= 0 state = ST_FALLING EndIf End Select If KeyHit(KEY_UP) And (Not topCollision(yv)) And (state = ST_NORMAL) state = ST_JUMPING yv = -8 EndIf If yv > 10 yv = 10 EndIf If xv > 5 xv = 5 ElseIf xv < -5 xv = -5 EndIf x = x + xv y = y + yv If KeyDown(KEY_RIGHT) direction = DIR_RIGHT If rightCollision(xv) xv = 0 x = x + distance Else If xv > 0 If leftCollision(xv) xv = 0 x = x - distance EndIf xv = xv + 0.5 Else xv = xv + 0.2 EndIf EndIf EndIf If KeyDown(KEY_LEFT) direction = DIR_LEFT If leftCollision(xv) xv = 0 x = x - distance Else If xv < 0 If rightCollision(xv) xv = 0 x = x + distance EndIf xv = xv - 0.5 Else xv = xv - 0.2 EndIf EndIf EndIf If (xv > 0 Or xv < 0) And ((Not KeyDown(KEY_RIGHT)) And (Not KeyDown(KEY_LEFT))) Select direction Case DIR_LEFT If leftCollision(xv) xv = 0 x = x - distance Else xv = xv + GRAVITY If xv >= 0 xv = 0 EndIf EndIf Case DIR_RIGHT If rightCollision(xv) xv = 0 x = x + distance Else xv = xv - GRAVITY If xv <= 0 xv = 0 EndIf EndIf End Select EndIf End Method End Type Function fillmap() Local line:String For Local y:Int = 0 To MAP_HEIGHT - 1 ReadData line For Local x:Int = 0 To MAP_WIDTH - 1 map[x,y] = Int(Mid(line,x+1,1)) Next Next End Function Function RectsOverlap:Int(x0:Float, y0:Float, w0:Float, h0:Float, x2:Float, y2:Float, w2:Float, h2:Float) If x0 > (x2 + w2) Or (x0 + w0) < x2 Then Return False If y0 > (y2 + h2) Or (y0 + h0) < y2 Then Return False Return True End Function 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"
It works, in a sense, but is far from perfect. At times, it will put me off of the screen for no apparent reason, along with a few other quirks. I was wondering, for one, can anyone tell me what I can improve/fix to make the collisions work better? Even better, does anyone have some blitzmax code already written that shows basic collision detection? All help is appreciated.