Jump to content
  • Advertisement
Sign in to follow this  
JavaMava

*NEW* Almost have rectangle collision, just need help with some odd bugs

This topic is 4589 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Okay so I've been working on collision for a while, and have had some troubels, which you guys have mostly been ale to help me with (thanks). I'm so close now. It's almost working flawlessly. I handel my x and y collsison seperately. First I see if the character moved into a non walkable tile on the x axis, if he did I move him out. Then I see if he moved into a non walkable tile on the y axis, if he did I move him out. My problem is when I collide on a tile on its corner and then let my code move it out, it wont let me move my character(a square)in one of the directions. Example. I hit the bottom left corner of a non wakable tile. The code moves it to just outside. Then I can't move it left or up, when it should have been moved out. Another problem is I can't move under a non walkable tile when there is only one walkable tile space under it. Another problem is if I am directly under a set of tile I can't move left or right, but if I'm on top I can. I did this in TURING and left out everthing except drawing my tiles, collsions, and a test rectangle that you can move around. import GUI var win := Window.Open ("graphics:704;448") View.Set ("offscreenonly") %These are variables for input from a controller var JoyX, JoyY : int var JoyButton1, JoyButton2, JoyButton7, JoyButton8 : boolean %Variables used in Move Collided Object var newx, newy, oldx, oldy : array 1 .. 2 of int %These variables are the surrounding collision box cordinates of the character var tilex1, tilex2, tiley1, tiley2 : int const UP := 3 const DOWN := 4 const LEFT := 1 const RIGHT := 2 var penetrationLeft, penetrationRight, penetrationUp, penetrationDown : int var collision : int := 0 %This is the values for the collision box around the character newx (1) := 100 newy (1) := 170 newx (2) := newx (1) + 32 newy (2) := newy (1) + 32 oldx (1) := newx (1) oldx (2) := newx (2) oldy (1) := newy (1) oldy (2) := newy (2) %These are variables used for gravity and jumping var count, limit, vel, grav, power : int count := 0 limit := 10 %How long you can keep moving up power := 20 %The power you jump up at grav := 10 %The Gravity of the world vel := 0 %Your current velocity const MAPTILEX := 100 %amount of x tiles in the entire map const MAPTILEY := 25 %amount of y tiles in the entire map const TILESIZEX := 32 %Size of x tile in pixels const TILESIZEY := 32 %Size of x tile in pixels const SCREENHIEGHT := 14 %number of tile up on screen at once const SCREENWIDTH := 22 %number of tile across on screen at once var map : array 0 .. MAPTILEX of array 0 .. MAPTILEY of int %saves what tile is in each location var tile, tile1 : int := 0 %current tile being drawn var disX, disY : int := 0 % This is the displacement for when the world is scrolled over var fileNo : int tile1 := Pic.FileNew ("tile.bmp") %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% proc Open %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% var fileName : string := "TestMap" % Name of file var fileNo : int % Number of file open : fileNo, fileName, read read : fileNo, map close : fileNo end Open %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% proc Draw_Map %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% for x : 0 .. SCREENWIDTH - 1 %Goes through every tile on the x on the screen for y : 0 .. SCREENHIEGHT - 1 %Goes through every tile on the y on the screen tile := map (x + disX) (y + disY) %Makes current tile being drawn equal to corresponding tile in map if tile > 0 then %Skips drawing if the tile is not walkable Pic.Draw (tile, (x * TILESIZEX), (y * TILESIZEY), picCopy) %draws tile end if end for end for end Draw_Map %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%% proc DRAW %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% oldx (1) := newx (1) oldx (2) := newx (2) oldy (1) := newy (1) oldy (2) := newy (2) Draw.Box (oldx (1), oldy (1), oldx (2), oldy (2), brightred) %This is the character right now, a box end DRAW %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%% %%%%%%%%%%%% proc INPUT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Joystick.GetInfo (joystick1, JoyX, JoyY, JoyButton1, JoyButton2, JoyButton7, JoyButton8) %Movement on x axis if JoyX > 0 then newx (1) += 10 newx (2) := newx (1) + 32 elsif JoyX < 0 then newx (1) -= 10 newx (2) := newx (1) + 32 end if if JoyY > 0 then newy (1) += 10 newy (2) := newy (1) + 32 elsif JoyY < 0 then newy (1) -= 10 newy (2) := newy (1) + 32 end if end INPUT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% procedure Control_Functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %THIS WORKS FOR COLLIDING RIGHT SIDE OF RECT if newx (1) > oldx (1) then %character has moved right tile := map (floor (newx (2) / TILESIZEX)) (floor (newy (1) / TILESIZEY)) %What tile the bottome right of the rect is in if tile > 0 then tilex1 := TILESIZEX * floor (newx (2) / TILESIZEX) %Gets the tiles x1 newx (1) := newx (1) - (newx (2) - tilex1) %moves the rect left too outside the tile newx (2) := newx (1) + 32 end if tile := map (floor (newx (2) / TILESIZEX)) (floor (newy (2) / TILESIZEY)) %What tile the top right of the rect is in if tile > 0 then tilex1 := TILESIZEX * floor (newx (2) / TILESIZEX) %Gets the tiles x1 newx (1) := newx (1) - (newx (2) - tilex1) %moves the rect left too outside the tile newx (2) := newx (1) + 32 end if collision := RIGHT %THISWORKS FOR COLLIDING LEFT SIDE OF RECT elsif newx (1) < oldx (1) then %character has moved left tile := map (floor (newx (1) / TILESIZEX)) (floor (newy (1) / TILESIZEY)) %What tile the bottome left of the rect is on if tile > 0 then tilex2 := TILESIZEX * ceil (newx (1) / TILESIZEX) %Gets the tiles x2 newx (1) := newx (1) + (tilex2 - newx (1)) %moves the rect right too outside the tile newx (2) := newx (1) + 32 end if tile := map (floor (newx (1) / TILESIZEX)) (floor (newy (2) / TILESIZEY)) %What tile the top left of the rect is on if tile > 0 then tilex2 := TILESIZEX * ceil (newx (1) / TILESIZEX) %Gets the tiles x2 newx (1) := newx (1) + (tilex2 - newx (1)) %moves the rect right too outside the tile newx (2) := newx (1) + 32 end if end if %THISWORKS FOR COLLIDING TOP SIDE OF RECT if newy (1) > oldy (1) then %character has moved up tile := map (floor (newx (1) / TILESIZEX)) (floor (newy (2) / TILESIZEY)) %What tile the top left of the rect is in if tile > 0 then tiley1 := TILESIZEY * floor (newy (2) / TILESIZEY) %Gets the tiles y1 newy (1) := newy (1) - (newy (2) - tiley1) %moves the rect down too outside the tile newy (2) := newy (1) + 32 end if tile := map (floor (newx (2) / TILESIZEX)) (floor (newy (2) / TILESIZEY)) %What tile the top right of the rect is in if tile > 0 then tiley1 := TILESIZEY * floor (newy (2) / TILESIZEY) %Gets the tiles y1 newy (1) := newy (1) - (newy (2) - tiley1) %moves the rect down too outside the tile newy (2) := newy (1) + 32 end if %THIS WORKS FOR COLLIDING BOTTOM SIDE OF RECT elsif newy (1) < oldy (1) then %character has moved down tile := map (floor (newx (1) / TILESIZEX)) (floor (newy (1) / TILESIZEY)) %What tile the bottom left of the rect is in if tile > 0 then tiley2 := TILESIZEY * ceil (newy (1) / TILESIZEY) %Gets the tiles y2 newy (1) := newy (1) + (tiley2 - newy (1)) %moves the rect up too outside the tile newy (2) := newy (1) + 32 end if tile := map (floor (newx (2) / TILESIZEX)) (floor (newy (1) / TILESIZEY)) %What tile the bottom left of the rect is in if tile > 0 then tiley2 := TILESIZEY * ceil (newy (1) / TILESIZEY) %Gets the tiles y2 newy (1) := newy (1) + (tiley2 - newy (1)) %moves the rect up too outside the tile newy (2) := newy (1) + 32 end if end if end Control_Functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Open loop cls INPUT Control_Functions Draw_Map DRAW View.Update delay (50) end loop So heres basically how my collision works. If the character has moved right I see if the tile his x2 is in is walkable. If its not I then find out its x1 and figure out how much to move him out. I do this for the two possible tiles he could be in on the x cord if he moved right. I do very similar steps for left up and down. [Edited by - JavaMava on January 22, 2006 8:55:55 PM]

Share this post


Link to post
Share on other sites
Advertisement
I must be missing something there - it seems like since you're using <= for your comparisons, one of the four options would always be chosen, even if some of the penetration values were equal. For example, consider the worst-case scenario of one square box right on top of another, so that all four penetration values are the same. In this case, wouldn't your logic (arbitrarily, but correctly) select LEFT to resolve the collision?

So I guess I must not be understanding the problem...

[Edit: Sorry, I think I'm misunderstanding the problem, since your subject line mentions colliding into two tiles at once. If after a while you don't get the answers you need, you might try explaining the problem again, perhaps with some more details or even a little ascii art.]

Share this post


Link to post
Share on other sites
Find out which tile your character would be in when the position is updated, and if it's a 'solid' tile, handle the case accordingly.

Here, have some (bad) pseudocode:

newPosition.x = playerPosition.x + dx
newPosition.y = playerPosition.y + dy

if newPosition != 'solid'
playerPosition = newPosition
else switch (newPosition) {
case (upperRight): {
playerPosition.x = leftBoundary
playerPosition.y = topBoundary
break
}
case (top): {
playerPosition.x = newPosition.x
playerPosition.y = topBoundary
break
}
...etc
}



Hope that helps.

Share this post


Link to post
Share on other sites
Okay I've made some quick fixes. I changed the characters rectangle to 30 by 30 so he can fit under a space thats only one tile wide. And to fix the other problems I offset right collision and up collision by one pixel. It's working like a dream, thanks for your help.

Now onto AI......

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!