Collision Problem.
BlitzMax Forums/BlitzMax Programming/Collision Problem.
| ||
![]() In the above example, the red land area is my collision layer for my level, the black box, and smaller yellow box's are my player, and where on the player I am checking collisions. First of all to keep my player on the land I do a check at his feet, loop through small amounts until its touching or just on top of the land. I then check to see if the left is touching anything and the right and nudge the players x left or right to stop it touching. this is actually buggy and for some reason the left check seems to get ignored sometimes. Also another problem is at pos3 if I jump into a land mass as soon as my feet hit it, my loop code bounces me to the top of it, iv tried a number of things to avoid this but they all didnt work. so little help is needed, if you have a better of of checking player collisions on a large image like mine please let me know. oh the land mass in the air, I want to be able to jump through it, but only land on it if my feet actually hit the top of it. Method Collisions() debugstop Local LeftCheck:Int Local RightCheck:Int Local FootCheck:Int ' Im pre checking these here because as the method grows, I may need to call the same chack at the ' same pos more than once. footcheck = ImagesCollide(footcollisionImage , X , Y , 0 , bg_Coll , level_offset , gfx_height - ImageHeight(bg_Coll) , 0 ) rightcheck = ImagesCollide(rightcollisionImage , X , Y , 0 , bg_Coll , level_offset , gfx_height - ImageHeight(bg_Coll) , 0 ) leftcheck = ImagesCollide(leftcollisionImage , X , Y , 0 , bg_Coll , level_offset , gfx_height - ImageHeight(bg_Coll) , 0 ) If footcheck = 0 fallspeed = fallspeed + .5 gravity:+fallspeed End If 'keep the player on top of the collision layer. Local ontop = 0 Local steps= 0 Repeat If ImagesCollide(footcollisionImage , X , Y , 0 , bg_Coll , level_offset , gfx_height - ImageHeight(bg_Coll) , 0 ) = 1 y:-.2 fallspeed = 0 steps:+1 Else ontop=1 End If If ImagesCollide(rightcollisionImage , X , Y , 0 , bg_Coll , level_offset , gfx_height - ImageHeight(bg_Coll) , 0 ) = 1 And state<>state_jump x:-.2 End If If ImagesCollide(leftcollisionImage , X , Y , 0 , bg_Coll , level_offset , gfx_height - ImageHeight(bg_Coll) , 0 ) = 1 And state<>state_jump x:+ .2 ''debugstop End If Until ontop=1 End Method Last edited 2011 |
| ||
it's kind of hard to actually see what it's doing wrong from that bit of code. It can be a number of reason not having to do anything with the that code. it might be better if you can post an executable or even better the complete source code. |
| ||
You should keep your collisions separate from your movement. Collisions are best used when the code returns true or false if there's a collision, makes it easier to debug and get working right. I can see in your code that you have If....EndIf..... and then do another ImagesCollide. But yet you have movement (y:-0.2) going on before another collision, so that will affect subsequent collision checks. Is this the way you want to do this? Probably not. Separate your functionality. One way I do this is by using a NEWPOSX, NEWPOSY variable, and setting the new player's position when all the collisions are done checking the old position. |
| ||
yeah think I get what your saying, so call my update, do all the moveing by setting a newx newy, and then at the end in a new method/function do all collision checks and if there are any dont set the current x,y to the new x,y or am I getting something wrong ? God my memory is so bad Iv not touched code in years, taking my time getting back into things im sure iv made some other really stupid mistakes in the code so far I might just post the full source for some suggestions on how to clean it up. dont want to retain any old bad habbits. 'Black Night Test Code. Strict Framework brl.glmax2d Import brl.freeaudioaudio Import brl.linkedlist Import brl.math Import brl.random Import brl.wavloader Import brl.bmploader Import brl.pngloader Import brl.tgaloader Import brl.jpgloader Import brl.oggloader SetGraphicsDriver GLMax2DDriver() Global GFX_Width :Int = 1024 Global GFX_Height :Int = 768 Graphics GFX_Width,GFX_Height,0 Global bg_Sky:TImage = LoadImage ("sprite/level1/bground_sky.png") Global bg_Back:TImage = LoadImage ("sprite/level1/Ground_back_3.png") Global bg_Coll:TImage = LoadImage ("sprite/level1/ground_coll_3.png") Global bg_Fore:TImage = LoadImage ("sprite/level1/ground_fore_3.png") Global footcollisionImage:TImage = LoadImage ("sprite/footcollision.png") Global leftcollisionImage:TImage = LoadImage ("sprite/leftcollision.png") Global rightcollisionImage:TImage = LoadImage ("sprite/rightcollision.png") Const State_Idle:Int = 1 Const State_run:Int = 2 Const State_attack:Int = 3 Const State_jump:Int = 4 Const State_kneel:Int = 5 Const Direction_left:Int = 1 Const Direction_right:Int = 2 Const Direction_up:Int = 2 Global level_offset:Int =0 Global map_push:Int = 350 Global CurrentLevel:Int = 1 Type level Field x:Int Field y:Int Field name:String Field skyimage:TImage Field bgImage:TImage Field colImage:TImage Field foreImage:TImage Field levelOffset:Int Field segment:Int Field totalsegments:Int Field totalwidth:Int Field mappush:Int Field prevSeg:Int Field nextSeg:Int Field zorder:Int Method New () name = "Level " + CurrentLevel segment = 1 x = 0 'bgimage = LoadImage ("sprite/level" + currentlevel + "/ground_back_" + segment + ".png") 'colimage = LoadImage ("sprite/level" + currentlevel + "/ground_coll_" + segment + ".png") 'foreimage = LoadImage ("sprite/level" + currentlevel + "/ground_fore_" + segment + ".png") 'skyimage = LoadImage ("sprite/level" + currentlevel + "/bground_sky.png") 'y = gfx_height-ImageHeight(colimage) End Method Method loadlevel(newlevel:Int) 'do level loading here. End Method End Type Global Levels:level = New level levels.Loadlevel(CurrentLevel) Type Player Const RunRight_offset = 1 Const Runleft_offset = 0 Const idleRight_offset = 5 Const idleleft_offset = 4 Const attackRight_offset = 3 Const attackleft_offset = 2 Field x:Int Field y:Int Field oldx:Int Field oldy:Int Field runspeed:Float Field direction:Int Field image:TImage Field image_run:TImage Field image_idle:TImage Field image_attack:TImage Field frame:Int Field framerate:Int = 100 Field frametime:Int = MilliSecs() Field Gravity:Float = 5 Field state:Int=State_idle Method Draw() ''debugstop Select State Case State_idle Select direction Case Direction_right DrawImage image , X , Y , frame + (idleright_offset*7) Case direction_left DrawImage image , X , Y , frame + (idleleft_offset*7) End Select Case State_run Select direction Case Direction_right DrawImage image , X , Y , frame + (runright_offset*7) Case direction_left DrawImage image , X , Y , frame + (runleft_offset*7) End Select Case State_jump Select direction Case Direction_right DrawImage image , X , Y , frame + (runright_offset*7) Case direction_left DrawImage image , X , Y , frame + (runleft_offset*7) End Select Case State_attack Select direction Case Direction_right DrawImage image , X , Y , frame + (attackright_offset*7) Case direction_left DrawImage image , X , Y , frame + (attackleft_offset*7) End Select Case State_kneel Select direction Case Direction_right DrawImage image , X , Y , frame + (idleright_offset*7) Case direction_left DrawImage image , X , Y , frame + (idleleft_offset*7) End Select End Select DrawImage footcollisionImage , X , Y DrawImage leftcollisionImage , X , Y DrawImage rightcollisionImage , X , Y SetColor 255 , 255 , 255 Local data:String = "x ["+String.Fromfloat(x)+"] y ["+String.Fromfloat(y)+"]" DrawText data , 1 , 1 DrawText "x = " + player1.x , 1 , 20 DrawText "frametime = " + frametime , 1 , 40 DrawText "framerate = " + framerate , 1 , 60 End Method Method update() oldy = y oldx = x y = y + gravity collisions() If MilliSecs() - framerate > frametime If frame =< 5 frame = frame + 1 Else frame = 0 End If frametime = MilliSecs() End If If x > map_push Then x = map_push If KeyHit(KEY_SPACE) state = state_jump End If If state = state_jump Select direction Case direction_right ''debugstop If x => map_push level_offset:- runspeed x = map_push Else x:+ runspeed End If Case direction_left If x <= map_push And level_offset<0 level_offset:+ runspeed x = map_push Else x:- runspeed End If Case direction_up ' End Select End If If KeyDown(KEY_D) And state<>state_attack And state<>State_jump And state<>state_kneel state = State_run direction=Direction_right If x => map_push level_offset:- runspeed x = map_push Else x:+ runspeed End If End If If KeyDown(KEY_A) And state<>state_attack And state<>State_jump And state<>state_kneel state = State_run direction = Direction_left If x <= map_push And level_offset<0 level_offset:+ runspeed x = map_push Else x:- runspeed End If End If If KeyDown(key_A) = 0 And KeyDown(key_d) = 0 And state<>State_attack And state<>state_jump And state<>state_kneel 'not moving so set state to idle state = state_idle End If If MouseHit(1) And state <> state_attack And state <> state_kneel state = state_attack frame=0 DebugStop End If Select State Case State_idle player1.framerate=200 Case State_run player1.framerate=100 Case State_attack 'debugstop player1.framerate = 17 If frame => 6 state=state_idle End If Case state_kneel player1.framerate = 1000 Default framerate=100 End Select If player1.framerate = 1000 Local g:Int =1 End If End Method Method Collisions() 'debugstop If ImagesCollide(footcollisionImage , X , Y , 0 , bg_Coll , level_offset , gfx_height - ImageHeight(bg_Coll) , 0 ) = 0 End If 'keep the player on top of the collision layer. Local ontop = 0 Repeat If ImagesCollide(footcollisionImage , X , Y , 0 , bg_Coll , level_offset , gfx_height - ImageHeight(bg_Coll) , 0 ) = 1 y:-.2 Else ontop:+ 1 If state <> state_attack state = state_idle Else ' End If End If Until ontop => 1 End Method Method New () frametime=MilliSecs() framerate = 100 runspeed = 4 direction = Direction_left state = state_run image = LoadAnimImage("sprite/player.png" , 132 , 135 , 0 , 42) x = 350 y = 600 End Method End Type Global Player1:player = New player Repeat Cls update() render() Flip Until KeyHit(KEY_ESCAPE) Or AppTerminate() Function Update() ''debugstop player1.update() End Function Function Render() ''debugstop DrawImage bg_Sky , 0 , 0 DrawImage bg_Back , level_offset , gfx_height-ImageHeight(bg_back) DrawImage bg_Coll , level_offset , gfx_height-ImageHeight(bg_Coll) player1.draw() DrawImage bg_Fore , level_offset , gfx_height-ImageHeight(bg_Fore) End Function |
| ||
EDIT - think the above code might be a revision where i ripped out the jump code i had cos , well it sucked. Last edited 2011 |