Collisions/Slope/Linepick help !!!!
Blitz3D Forums/Blitz3D Programming/Collisions/Slope/Linepick help !!!!
| ||
I'm coding a 3d platform game, but I had some troubles dealing with blitz collisions. If using blitz standard collisions: 1)I want the player to reach the peak of the slope without any effort, and I want the player to move freely in any direction without being 'adjusted' by the gravity/collision force. 2)When the player goes down on the slope, sometimes it does not collide perfectly with it. 3)When the player is near an edge of the platform it slides down slowly(due to the ellipsoid collision shape) With linepick function I had less problems but: 1)The player is able to jump on the platform even from below it I need a good solution :( Graphics3D 800,600,32,2 Global cam=CreateCamera() RotateEntity cam,20,0,0 PositionEntity cam,0,10,-14 light=CreateLight(2) PositionEntity light,0,4000,-700 Type char Field mesh Field name$ Field pxDummy Field curdir_x# Field curdir_y# Field curdir_z# Field wanteddir_vx# Field wanteddir_vz# Field curPosY# Field moveSpeed# Field groundCollision End Type Const collType_Char=1 Const collType_Ground=2 Const collType_Platform=3 ;----------------------------------------------------- Global ch.char=New char ch\moveSpeed#=0.08 ch\pxDummy=CreateCube() EntityType ch\pxDummy,collType_Char EntityRadius ch\pxDummy,1,2 EntityColor ch\pxDummy,255,0,0 ScaleEntity ch\pxDummy,1,2,1 d=CreateCone() ScaleMesh d,.5,.5,.5 RotateMesh d,-90,0,0 PositionMesh d,0,0,-2 AddMesh d,ch\pxDummy PositionEntity ch\pxDummy,0,4,0 ch\curPosY=4 FreeEntity d Global Ground=CreateCube() EntityType Ground,collType_Ground ScaleMesh Ground,20,1,20 slope=CreateCube() ScaleMesh slope,10,10,10 RotateMesh slope,0,0,30 PositionMesh slope,-12,-4,0 AddMesh slope,Ground FreeEntity slope EntityPickMode Ground,2 plt=CreateCube() ScaleMesh plt,4,.5,4 PositionMesh plt,7,6,0 EntityType plt,collType_Platform EntityPickMode plt,2 ;----------------------------------------------------- Global collMethod=1 ;1>Blitz Collisions, 2>Ground LinePick ;----------------------------------------------------- If collMethod=1 Then Collisions collType_Char,collType_Ground,2,3 Collisions collType_Char,collType_Platform,2,2 EndIf timer=CreateTimer(60) Repeat WaitTimer(timer) ch\groundCollision=False ch\wanteddir_vx=0:ch\wanteddir_vz=0 If KeyDown(205) Then ch\wanteddir_vx=1 If KeyDown(203) Then ch\wanteddir_vx=-1 If KeyDown(200) Then ch\wanteddir_vz=1 If KeyDown(208) Then ch\wanteddir_vz=-1 TFormNormal ch\wanteddir_vx,0,ch\wanteddir_vz,0,0 ch\wanteddir_vx=TFormedX() ch\wanteddir_vz=TFormedZ() If ch\wanteddir_vx<>0 Or ch\wanteddir_vz<>0 Then AlignToVector ch\pxDummy,-ch\wanteddir_vz,0,ch\wanteddir_vx,1,1 TranslateEntity ch\pxDummy,((ch\wanteddir_vx)*ch\moveSpeed#),0,((ch\wanteddir_vz)*ch\moveSpeed#) EndIf If collMethod=2 Then ;Line GroundPick pick_length#=2.1 If LinePick(EntityX#(ch\pxDummy), EntityY#(ch\pxDummy), EntityZ#(ch\pxDummy), 0, -pick_length, 0) > 0 ch\groundCollision=True PositionEntity ch\pxDummy,EntityX#(ch\pxDummy,True),PickedY()+2,EntityZ(ch\pxDummy,True),True EndIf EndIf ;GRAVITY ----------------------------------- ty#=EntityY(ch\pxDummy) y_vel#=(ty-ch\curPosY) ch\curPosY=ty If KeyHit(57) ;jump y_vel=1.1 Else y_vel=y_vel-.1 ;2 EndIf TranslateEntity ch\pxDummy,0,y_vel,0 If CountCollisions( ch\pxDummy ) If EntityCollided( ch\pxDummy,collType_Ground ) Or EntityCollided( ch\pxDummy,collType_Platform ) ch\groundCollision=True EndIf EndIf UpdateWorld RenderWorld Text (610-FontWidth()),FontHeight()*tc,"Ground Collision: "+ch\groundCollision Flip (False) Until KeyHit(1) End |
| ||
answer to question #3 Collisions collType_Char,collType_Platform,2,2 in this line of code you are telling the char to slide down the slope by putting the response as 2 it tells it to use full sliding collision when on the platform...changing it to 3 will make the char stop and not slide down the slope...here is the help file... src_type - entity type to be checked for collisions. dest_type - entity type to be collided with. method - collision detection method. 1: sphere-to-sphere collisions 2: sphere-to-polygon collisions 3: sphere-to-box collisions response - what the source entity does when a collision occurs. 1: stop 2: slide1 - full sliding collision 3: slide2 - prevent entities from sliding down slopes hope this helps...pirate |
| ||
Thanks Pirate but it doesn't change much, the char should fall down directly without sliding at all on the edge! And with stop type response it may stick at the border of the platform if u keep holding direction keys. That's why I prefered collision type 2. |
| ||
Or you could use the toolbox upgrades. They have a sweet Collision system that outbests Blitz' commands. ~DarkShadowWing~ |
| ||
Use both the blitz collisions and linepick then. just make sure your linepick is slightly bigger than your collision radius, that way your linepick can tell you what it's picking, before the blitz collision kicks in. The blitz collision will stop your character running through walls and jumping through platforms. |
| ||
Thx I didn't notice that linepick would accept a radius paramenter :) But why if I set radius to 1 it is much difficoult to pick surfaces??If I try to jump it falls down through the ground. Can you show pls? :) |
| ||
When using linepicks it's always a good idea to start the pick slightly above your character, at least as much as the radius of the pick. Also make sure the length of the pick is extended to include this offset :If LinePick(EntityX#(ch\pxDummy), EntityY#(ch\pxDummy)+2, EntityZ#(ch\pxDummy), 0, -pick_length-2, 0) > 0 |
| ||
I see that you didn't use linepick radius? And if I use linepick only, the player will still be able to jump the platform from below...I should blitz collisions for the ground and linepick for the platform.. But at the edge of the platform as u may see, it slides down slowly..how to avoid that? Graphics3D 800,600,32,2 Global cam=CreateCamera() RotateEntity cam,20,0,0 PositionEntity cam,0,10,-14 light=CreateLight(2) PositionEntity light,0,4000,-700 Type char Field mesh Field name$ Field pxDummy Field curdir_x# Field curdir_y# Field curdir_z# Field wanteddir_vx# Field wanteddir_vz# Field curPosY# Field moveSpeed# Field blitzCollision Field pickedGround End Type Const collType_Char=1 Const collType_Ground=2 Const collType_Platform=3 ;----------------------------------------------------- Global ch.char=New char ch\moveSpeed#=0.08 ch\pxDummy=CreateCube() EntityType ch\pxDummy,collType_Char EntityRadius ch\pxDummy,1,2 EntityColor ch\pxDummy,255,0,0 ScaleEntity ch\pxDummy,1,2,1 d=CreateCone() ScaleMesh d,.5,.5,.5 RotateMesh d,-90,0,0 PositionMesh d,0,0,-2 AddMesh d,ch\pxDummy PositionEntity ch\pxDummy,0,4,0 ch\curPosY=4 FreeEntity d Global Ground=CreateCube() EntityType Ground,collType_Ground ScaleMesh Ground,20,1,20 slope=CreateCube() ScaleMesh slope,10,10,10 RotateMesh slope,0,0,30 PositionMesh slope,-12,-4,0 AddMesh slope,Ground FreeEntity slope EntityPickMode Ground,2 plt=CreateCube() ScaleMesh plt,4,.5,4 PositionMesh plt,7,6,0 EntityType plt,collType_Platform Collisions collType_Char,collType_Platform,2,2 timer=CreateTimer(60) Repeat WaitTimer(timer) ch\wanteddir_vx=0:ch\wanteddir_vz=0 If KeyDown(205) Then ch\wanteddir_vx=1 If KeyDown(203) Then ch\wanteddir_vx=-1 If KeyDown(200) Then ch\wanteddir_vz=1 If KeyDown(208) Then ch\wanteddir_vz=-1 TFormNormal ch\wanteddir_vx,0,ch\wanteddir_vz,0,0 ch\wanteddir_vx=TFormedX() ch\wanteddir_vz=TFormedZ() If ch\wanteddir_vx<>0 Or ch\wanteddir_vz<>0 Then AlignToVector ch\pxDummy,-ch\wanteddir_vz,0,ch\wanteddir_vx,1,1 TranslateEntity ch\pxDummy,((ch\wanteddir_vx)*ch\moveSpeed#),0,((ch\wanteddir_vz)*ch\moveSpeed#) EndIf ch\blitzCollision=False ch\pickedGround=False ;GRAVITY ----------------------------------- ty#=EntityY(ch\pxDummy) y_vel#=(ty-ch\curPosY) ch\curPosY=ty If KeyHit(57) ;jump y_vel=1.3 ElseIf ch\blitzCollision=False y_vel=y_vel-.1 ;2 EndIf TranslateEntity ch\pxDummy,0,y_vel,0 UpdateWorld pick_length#=2.1 If LinePick(EntityX#(ch\pxDummy), EntityY#(ch\pxDummy)+2, EntityZ#(ch\pxDummy), 0, -pick_length-2, 0) > 0 ch\pickedGround=True y_vel#=0 PositionEntity ch\pxDummy,EntityX#(ch\pxDummy,True),PickedY()+2,EntityZ(ch\pxDummy,True),True EndIf If CountCollisions( ch\pxDummy ) If EntityCollided( ch\pxDummy,collType_Platform ) ch\blitzCollision=True y_vel=0 EndIf EndIf RenderWorld Text (610-FontWidth()),FontHeight()*1,"Blitz Collision: "+ch\blitzCollision Text (610-FontWidth()),FontHeight()*2,"Picked Ground : "+ch\pickedGround Flip (False) Until KeyHit(1) End |
| ||
Just something to think about... if you're making a sidescroller, consider using coded collisions. Instead of having the CPU perform triangle collision checks on numerous triangles, if the sizes of things are relatively standard and you use a grid layout, you could do this much the same way as you would a 2D game - by checking the character's position against a map file or something similar. |
| ||
I would avoid the radius parameter if i were you tbh. It does slow things more. |
| ||
But at the edge of the platform as u may see, it slides down slowly..how to avoid that? This fixes it. It causes some clipping problems though. But at least now you can drop down normally. Personally, I'd take a clipping problem over some weird sliding off edges problem any day! EntityRadius ch\pxDummy,.05,2 If there's a way to do this though, I think then it'd be perfect! Does anyone know a way to simulate a mesh having four colliders like this? I tried making copies of the character, repositioning them, and making them invisible, but I couldn't get them to lock together. One would always end up on the platform, and the others on the ground. |
| ||
Hi Not sure if fox95871 already said that: when you combine a linepick versus the ground that is slightly longer than the distance to the gound and then you apply gravity only when the linepick did not hit the ground, this will prevent the sliding artefact. The relation of the to parameters of Entityradius (of the additional sphere vs polygonal collision of char vs world) will then allow to set the angle the character starts sliding. So he starts sliding only on a very steep ground for example. If feels rather natural this way, not sure if this is what you want. |
| ||
I definitely didn't say that, I'm a sub-beginner! I just thought I'd sneak into this area and throw in an Occam's razor :) |
| ||
Hello do you want the character to climb any slope? or there is a limit to with it wouldnot climb at all (too steep)? Here is the code i'm using at the moment, it is based on the mak/driver demo on the blitz3D sample, there is some physic for "sliding" temper by friction but you can disable it altogether. .physics ;------------------------------------------------------------------------- ; ;------------------------------------------------------------------------- ;calculate char velocities cx# = EntityX ( char ) x_vel = cx - prev_x prev_x = cx cy# = EntityY ( char ) y_vel = cy - prev_y prev_y = cy cz# = EntityZ ( char ) z_vel = cz - prev_z prev_z = cz .controls_States ;------------------------------------------------------------------------- ; ;------------------------------------------------------------------------- ; HIT controls If Hit > 0 Then Hit = Hit - 1 If Hit < 0 Then Hit = 0 ; wiimote control If EnableWiimote = True Then ;nun roll B_NunRollLeft = (JoyRoll(2)- WiiBlitz\NunRoll) < ANGsens;left B_NunRollRight = (JoyRoll(2)- WiiBlitz\NunRoll) > -ANGsens;right ;nunjoy B_NunJoyYUp = ((JoyV(2) - WiiBlitz\NunJoyY) < -DeadZone );up B_NunJoyYDown = ((JoyV(2) - WiiBlitz\NunJoyY) > DeadZone );down B_NunJoyXLeft = ((JoyU(2) - WiiBlitz\NunJoyX) < -DeadZone );left B_NunJoyXright = ((JoyU(2) - WiiBlitz\NunJoyX) > DeadZone );right Else ;nun roll B_NunRollLeft = False B_NunRollRight = False ;nunjoy B_NunJoyYUp = False B_NunJoyYDown = False B_NunJoyXLeft = False B_NunJoyXright = False EndIf ; turn char If KeyDown ( 203 ) Or B_NunRollLeft And (Not KeyDown (29)) Then TurnEntity char, 0, 3, 0 ;turn left EndIf If KeyDown ( 205 ) Or B_NunRollRight And (Not KeyDown (29)) Then TurnEntity char, 0, -3, 0 ;turn right EndIf ;try to insert a "force to contact" to avoid jittery move on slope LinePick ( EntityX(char),EntityY(char),EntityZ(char),0,-Attract ,0,GRadius) PickTime#=PickedTime() PickGround = PickedEntity() If (PickGround = 0) And (y_vel <> 0)Then; no contact with ground contact = 0 Else; no contact with ground, keep feet on slide (to optimize with contact normal to movement) TranslateEntity char,0,-PickedNY()*Delta,0 EndIf ; on contact If pickground <> 0 Then contact = 1 ; reset Y velocities y_vel# = 0 : prev_y# = EntityY ( char ) ; //button test ; key up pressed If KeyDown ( 200 ) Or B_NunJoyYUp And (Not KeyDown (29)) speed = speed + THRUST EndIf ; key down pressed If KeyDown ( 208 ) Or B_NunJoyYDown And (Not KeyDown (29)) speed = speed - THRUST EndIf ; strafe left button test If KeyDown ( 44 ) Or B_NunJoyXLeft And (Not KeyDown (29)) MoveEntity char, -StrafeStr , 0, 0 EndIf ; strafe rigth button test If KeyDown ( 46 ) Or B_NunJoyXright And (Not KeyDown (29)) MoveEntity char, StrafeStr , 0, 0 EndIf ; jump button test If ((KeyHit ( 45 ) Or JoyHit(5,1)) And PickGround <>0) MoveEntity char, 0, MaxSP * JUMP, 0 EndIf ; //end button test ;speed limiter If (speed > MaxSP) speed = MaxSP If (speed < -MinSP) speed = -MinSP ;when no move If (Not KeyDown ( 200 )) And (Not KeyDown ( 208 )) Then speed = 0;speed * ( 1 - ( FRICTION ) ) EndIf ;perform the movement MoveEntity char, 0, 0, speed x_vel = x_vel * ( 1 - FRICTION ) y_vel = ( y_vel + GRAVITY ) * ( 1 - FRICTION ) z_vel = z_vel * ( 1 - FRICTION ) TranslateEntity char, x_vel, y_vel, z_vel ; use static friction code here ; if speed under static then speed = 0 ; careful! static should be less strong than Thrust or maxSP/MinSP If (Abs(speed) < STATIC) speed = 0 If (Abs(x_vel) < STATIC) x_vel# = 0 If (Abs(y_vel) < STATIC) y_vel# = 0 If (Abs(z_vel) < STATIC) z_vel# = 0 ; no contact Else contact = 0 TranslateEntity char, x_vel, y_vel + GRAVITY, z_vel EndIf |
| ||
Is there a way to load a mesh as a collider? Or is there any other way to make the collider be like in the picture I posted? |
| ||
hmmm it is usually a good idea to make an invisible much simpler mesh for collisions. if you make these right they will prevent sliding too much and speed up the collisions. |
| ||
@fox95871 Regarding your picture... just look the mak/driver blitz3D sample, it has these king of collider (i have actually remove them when updating the code in mine while adding more physics) ;align car to wheels zx#=(EntityX( wheels[2],True )+EntityX( wheels[4],True ))/2 zx=zx-(EntityX( wheels[1],True )+EntityX( wheels[3],True ))/2 zy#=(EntityY( wheels[2],True )+EntityY( wheels[4],True ))/2 zy=zy-(EntityY( wheels[1],True )+EntityY( wheels[3],True ))/2 zz#=(EntityZ( wheels[2],True )+EntityZ( wheels[4],True ))/2 zz=zz-(EntityZ( wheels[1],True )+EntityZ( wheels[3],True ))/2 AlignToVector car,zx,zy,zz,1 zx#=(EntityX( wheels[1],True )+EntityX( wheels[2],True ))/2 zx=zx-(EntityX( wheels[3],True )+EntityX( wheels[4],True ))/2 zy#=(EntityY( wheels[1],True )+EntityY( wheels[2],True ))/2 zy=zy-(EntityY( wheels[3],True )+EntityY( wheels[4],True ))/2 zz#=(EntityZ( wheels[1],True )+EntityZ( wheels[2],True ))/2 zz=zz-(EntityZ( wheels[3],True )+EntityZ( wheels[4],True ))/2 AlignToVector car,zx,zy,zz,3 ;calculate car velocities cx#=EntityX( car ):x_vel=cx-prev_x:prev_x=cx cy#=EntityY( car ):y_vel=cy-prev_y:prev_y=cy cz#=EntityZ( car ):z_vel=cz-prev_z:prev_z=cz ;resposition wheels cnt=1 For z=1.5 To -1.5 Step -3 For x=-1 To 1 Step 2 ; PositionEntity wheels[cnt],0,0,0 ; ResetEntity wheels[cnt] PositionEntity wheels[cnt],x,-1,z cnt=cnt+1 Next Next ;move car If KeyDown(203) TurnEntity car,0,3,0 If KeyDown(205) TurnEntity car,0,-3,0 If EntityCollided( car,SCENE ) If KeyDown(200) speed=speed+.02 If speed>.7 speed=.7 Else If KeyDown(208) speed=speed-.02 If speed<-.5 speed=-.5 Else speed=speed*.9 EndIf MoveEntity car,0,0,speed TranslateEntity car,0,GRAVITY,0 Else TranslateEntity car,x_vel,y_vel+GRAVITY,z_vel EndIf This is the part of the code you are looking for, the "wheel" are the marker. It follow slope and don't slide... If you perform a test for individual collision on each wheel you can have extra info about the character position in the world (ie if near a edge). |
| ||
Thanks, I'll check it out tonight. Nate, that was so you could see what I was talking about, not to have them be visible in the actual game. One narrow collider in the center prevents sliding at the edges (yeah, I know about mode 3, but that doesn't always work, as the code in post 8 shows) so that characters fall more like in the old days, like in a nes game. But I was just showing that by having four of those, if there's some way to do that, you could also prevent the one side effect of having a narrow collider - the character's often half in a wall. Hopefully Tomago's code will show me some things I never thought of as a fix to that. |
| ||
I'm not saying there's actually lichen starting to grow on this topic, but I am getting the feeling it won't be long... Is there a way to make mulitiply pointy collision meshes, or to import a custom mesh that looks like that and use it as a collider? Flag's character is now dropping down perfectly (see post 11) but it's clipping wrong as a side effect. Only multiple colliders or a custom collider mesh would fix that as far as I can tell. Does anyone know a way to achieve either? I know it's not my topic, but I'm pretty curious now because his example is a lot like my game will be :) Tomago, could you give me a more complete code sample than the one you gave? I mean like with Graphics3D and everything. I'm actually an infiltrator from the beginner's forum, so I'm not really sure exactly what to do with the code you posted. Sorry! D: Thanks! |
| ||
Which one? |
| ||
Okay, a reply! I meant your last one, but I guess that's from the mak driver example. I looked at that last night, but man...I can't understand it at all! I understand the program running though, I guess each wheel is a collider? Thing is, when I do that I can never seem to get them to all stay attached to the character. For example, in the picture I posted above, when I actually coded it to do that, if you jumped up onto the ledge so just your "foot" lands on it, the corresponding collider ends up on the ledge, and the other three drop down. So for a beginner like me who starts to lose consciousness just looking at the mak code, what simple example could you give to lock four colliders together and to the character? Please wrap it if you can, with Graphics3D and While Wend and all that. Thanks! Hope you can help :) |
| ||
I'm starting a new thread about this in the beginners area if anyone's interested: http://www.blitzbasic.com/Community/posts.php?topic=84103 |