Collisions/Slope/Linepick help !!!!

Blitz3D Forums/Blitz3D Programming/Collisions/Slope/Linepick help !!!!

FlagDKT(Posted 2008) [#1]
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




Pirate(Posted 2008) [#2]
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


FlagDKT(Posted 2008) [#3]
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.


Guy Fawkes(Posted 2008) [#4]
Or you could use the toolbox upgrades. They have a sweet Collision system that outbests Blitz' commands.

~DarkShadowWing~


Ross C(Posted 2008) [#5]
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.


FlagDKT(Posted 2008) [#6]
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? :)


Stevie G(Posted 2008) [#7]
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



FlagDKT(Posted 2008) [#8]
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




Buggy(Posted 2008) [#9]
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.


Ross C(Posted 2008) [#10]
I would avoid the radius parameter if i were you tbh. It does slow things more.


fox95871(Posted 2009) [#11]
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.


jfk EO-11110(Posted 2009) [#12]
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.


fox95871(Posted 2009) [#13]
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 :)


neoshaman(Posted 2009) [#14]
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




fox95871(Posted 2009) [#15]
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?


Nate the Great(Posted 2009) [#16]
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.


neoshaman(Posted 2009) [#17]
@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).


fox95871(Posted 2009) [#18]
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.


fox95871(Posted 2009) [#19]
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!


neoshaman(Posted 2009) [#20]
Which one?


fox95871(Posted 2009) [#21]
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 :)


fox95871(Posted 2009) [#22]
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