how do I move acube around?
Blitz3D Forums/Blitz3D Beginners Area/how do I move acube around?
I was suprized to find out that there is no examples on how to push objects around like in tomb raider, or resident evil. like when they move blocks or pillars and stuff. If anyone would like to help me with this code I will post it in the code base. Here is what I have so far. A sphere and a cube; player controls sphere with keys w,s,a and d;
What I want to happen is when sphere collides with box (for example from the top of the cube, the cube should move down)or vise versa. I think I need to use the comands collision x,y,z but not sure how to do that.
Another way I tried is if sphere is to check if sphere is higher or lower, to the right of or to the left of box at time of collision, so that box would move acordingly.
Do I at least have a clue?
Graphics3D 640,480,16
SetBuffer BackBuffer()
Const cube_col=1
Const sphere_col=2
light= CreateLight()
camera=CreateCamera()
PositionEntity camera,0,40,0
Type cubedata
Field x#,y#
End Type
Type circledata
Field x#,y#
End Type
box.cubedata = New cubedata
box\x#=-10
box\y#=40
cube= CreateCube()
ScaleEntity cube,1,2,2
PositionEntity cube,box\x#,box\y#,20
EntityColor cube,255,0,0
EntityType cube,cube_col;colitionccccccccccccccccccccccccccccc
;EntityBox entity,x#,y#,z#,width#,height#,depth#
EntityBox cube,-10,40,20,1,2,2
;CollisionX# ( entity,index )
;CollisionX# ( cube,1 )
;CollisionY# ( cube,1 )
;player
circle.circledata = New circledata
circle\x#=10
circle\y#=40
sphere= CreateSphere()
EntityColor sphere,0,0,255
PositionEntity sphere,circle\x#,circle\y#,20
EntityType sphere,sphere_col;colitionccccccccccccccccccccccccccccc
Collisions sphere_col,cube_col,2,3
Global rsx#=-.25
Global lsx#=.25
Global rsy#=-.25
Global lsy#=.25
While Not KeyHit(1)
If KeyDown(30) MoveEntity sphere,rsx#,0,0
If KeyDown(32) MoveEntity sphere,lsx#,0,0
If KeyDown(17) MoveEntity sphere,0,lsy#,0
If KeyDown(31) MoveEntity sphere,0,rsy#,0
UpdateWorld()
RenderWorld()
Text 10,20,circle\x + circle\y
If EntityCollided(sphere,cube_col)
Text 370,80,"Collided !!!"
TranslateEntity cube,-.25+(bx#*2),0,0
EndIf
Text 335,500,"Collision Detection"
Flip
Wend
End
Lost in space........................
This might help..
Graphics3D 640,480,16
SetBuffer BackBuffer()
Const cube_col=1
Const sphere_col=2
light= CreateLight()
camera=CreateCamera()
PositionEntity camera,0,40,0
Type cubedata
Field x#,y#
End Type
Type circledata
Field x#,y#
End Type
box.cubedata = New cubedata
box\x#=-10
box\y#=40
cube= CreateCube()
ScaleEntity cube,1,2,2
PositionEntity cube,box\x#,box\y#,20
EntityColor cube,255,0,0
EntityType cube,cube_col;colitionccccccccccccccccccccccccccccc
;EntityBox entity,x#,y#,z#,width#,height#,depth#
EntityBox cube,-10,40,20,1,2,2
;CollisionX# ( entity,index )
;CollisionX# ( cube,1 )
;CollisionY# ( cube,1 )
;player
circle.circledata = New circledata
circle\x#=10
circle\y#=40
sphere= CreateSphere()
EntityColor sphere,0,0,255
PositionEntity sphere,circle\x#,circle\y#,20
EntityType sphere,sphere_col;colitionccccccccccccccccccccccccccccc
Collisions sphere_col,cube_col,2,3
Global rsx#=-.25
Global lsx#=.25
Global rsy#=-.25
Global lsy#=.25
While Not KeyHit(1)
If KeyDown(30) MoveEntity sphere,rsx#,0,0
If KeyDown(32) MoveEntity sphere,lsx#,0,0
If KeyDown(17) MoveEntity sphere,0,lsy#,0
If KeyDown(31) MoveEntity sphere,0,rsy#,0
UpdateWorld()
RenderWorld()
Text 10,20,circle\x + circle\y
If EntityCollided(sphere,cube_col)
Text 370,80,"Collided !!!"
If EntityX(sphere) > EntityX(cube) Then ; Check on wich side the sphere is
TranslateEntity cube,-.25+(bx#*2),0,0
EndIf
If EntityX(sphere) < EntityX(cube) Then ; Check on wich side the sphere is
TranslateEntity cube,.25+(bx#*2),0,0
EndIf
EndIf
Text 335,500,"Collision Detection"
Flip
Wend
End
Yep works perfect. Thanks for the help.
Well, you could store the players current x,y,z position, before they move. Then check to see if the player has collided with the box. Then compare the players last x,y,z with their current, and move the box according to this.
Or, you could work on a grid based system like tomb raider. Every piece of scenary is grid based. To push something you check for a collision, find the direction the player is facing, then move the player and the cube a grid unit in that direction. The player obviously (like tomb raider) move smoothly and isn't confine to grid squares.
Ross C
The latter seems like more what I'm looking for. Not sure
if start over to do it. I'll try it, and see if I can do it.
ps: sorry about the duel posts, fustration drove me to it!
;)
What you could try is this. Create the player. Create the boxes. Parent all the box to a pivot. When you press the keys to move the player, move the level instead.
Thats very easy way of doing it, i learned
something from this too. Thanks Ross :)
Check this out. Surprised that it actually worked. Each cube when pushed, will push others too. Blitz collisions are cool :D
Graphics3D 640,480,16
SetBuffer BackBuffer()
Const cube_col=1
Const sphere_col=2
Global light= CreateLight()
Global camera=CreateCamera()
PositionEntity camera,0,40,0
RotateEntity camera,90,0,0
Global sphere=CreateSphere()
EntityType sphere,sphere_col
Global level=CreatePivot()
Dim cube(10)
For loop=0 To 10
cube(loop)=CreateCube()
PositionEntity cube(loop),-10,0,-10+loop*2
EntityType cube(loop),cube_col
EntityParent cube(loop),level
Next
Collisions 1,2,2,2
Collisions 1,1,2,2
Collisions 1,3,2,2
While Not KeyHit(1)
If KeyDown(30) MoveEntity level,0.1,0,0
If KeyDown(32) MoveEntity level,-0.1,0,0
If KeyDown(17) MoveEntity level,0,0,-0.1
If KeyDown(31) MoveEntity level,0,0,0.1
UpdateWorld
updatecubes() ; make sure collisions doesn't push the cubes downwards or upwards
RenderWorld
Flip
Wend
End
Function updatecubes()
For loop=0 To 10
PositionEntity cube(loop),EntityX(cube(loop)),0,EntityZ(cube(loop))
Next
End Function
Very nice Ross. Here's an alternative which pushes the cubes directly but doesn't allow the cubes to affect each other (apart from stopping).
Graphics3D 800,600,0,2
sphere=CreateCone()
RotateMesh sphere,90,0,0
PositionEntity sphere,5,0,-10
EntityType sphere,1
Dim cubes(6)
For n=0 To 6
cubes(n)=CreateCube()
EntityType cubes(n),2
PositionEntity cubes(n),0,0,-25+(n*3)
Next
light=CreateLight()
PositionEntity light,-5,-5,-5
PointEntity light, cubes(1)
cam=CreateCamera()
PositionEntity cam,0,25,0
PointEntity cam,cubes(1)
Collisions 1,2,3,2
Collisions 2,2,3,2
While Not KeyHit(1)
If KeyDown(200) MoveEntity sphere,0,0,0.2
If KeyDown(208) MoveEntity sphere,0,0,-0.2
If KeyDown(203) TurnEntity sphere,0,3,0
If KeyDown(205) TurnEntity sphere,0,-3,0
If EntityCollided(sphere,2)
For n=1 To CountCollisions(sphere)
ent = CollisionEntity(sphere,n)
x#=CollisionNX(sphere,n)/10
y#=CollisionNY(sphere,n)/10
z#=CollisionNZ(sphere,n)/10
TranslateEntity ent,-x#,-y#,-z#
Next
EndIf
UpdateWorld
RenderWorld
Flip
Wend
Hey you gues ar amasing. Just slinen code like nothin.
Here is what I ended up with kinda basic but does what I wanted. mabye a little longer than nessesary.
;sphere moveing a box around by Matt Anthony
Graphics3D 640,480,16
SetBuffer BackBuffer()
Const cube_col=1
Const sphere_col=2
light= CreateLight()
camera=CreateCamera()
PositionEntity camera,0,40,0
Type cubedata
Field x#,y#
End Type
Type circledata
Field x#,y#
End Type
AutoMidHandle =True
box.cubedata = New cubedata
box\x#=-10
box\y#=40
cube= CreateCube()
ScaleEntity cube,3,3,3
PositionEntity cube,box\x#,box\y#,20
EntityColor cube,255,0,0
EntityType cube,cube_col;collisionccccccccccccccccccccccccccccc
;player
circle.circledata = New circledata
circle\x#=10
circle\y#=40
sphere= CreateSphere()
EntityColor sphere,0,0,255
PositionEntity sphere,circle\x#,circle\y#,20
EntityType sphere,sphere_col;collisionccccccccccccccccccccccccccccc
Collisions sphere_col,cube_col,2,3
Global rsx#= .25 ;right movment value
Global lsx#=-.25 ;left movment value
Global usy#=-.25 ;up movement value
Global dsy#= .25 ;down movement value
;Const bx#=1
While Not KeyHit(1);Main MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
If KeyDown(30) MoveEntity sphere,lsx#,0,0
If KeyDown(32) MoveEntity sphere,rsx#,0,0
If KeyDown(17) MoveEntity sphere,0,dsy#,0
If KeyDown(31) MoveEntity sphere,0,usy#,0
UpdateWorld()
RenderWorld()
Color 255,255,0
Text 335,500,"Collision Detection"
Text 10,20,circle\x + circle\y
If EntityCollided(sphere,cube_col);collision
Text 370,80,"Collided !!!"
If EntityX(sphere)+1.5 > EntityX(cube) Then ; Check on wich side the sphere is
TranslateEntity cube,-.25,0,0
EndIf
If EntityX(sphere)-1.5 < EntityX(cube) Then ; Check on wich side the sphere is
TranslateEntity cube,.25,0,0
EndIf
EndIf
If EntityCollided(sphere,cube_col);collision
Text 370,80,"Collided !!!"
If EntityY(sphere)+1.5 < EntityY(cube) Then ; Check on wich side the sphere is
TranslateEntity cube,0,.25,0
EndIf
If EntityY(sphere)-1.5 > EntityY(cube) Then ; Check on wich side the sphere is
TranslateEntity cube,0,-.25,0
EndIf
EndIf
Flip
Wend ;End of Main MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
End
cool :)
Here's a little tweak that uses the collision normals to decide which direction to move the cube
Graphics3D 640,480,16
SetBuffer BackBuffer()
Const cube_col=1
Const sphere_col=2
light= CreateLight()
camera=CreateCamera()
PositionEntity camera,0,40,0
Type cubedata
Field x#,y#
End Type
Type circledata
Field x#,y#
End Type
AutoMidHandle =True
box.cubedata = New cubedata
box\x#=-10
box\y#=40
cube= CreateCube()
ScaleEntity cube,3,3,3
PositionEntity cube,box\x#,box\y#,20
EntityColor cube,255,0,0
EntityType cube,cube_col;collisionccccccccccccccccccccccccccccc
;player
circle.circledata = New circledata
circle\x#=10
circle\y#=40
sphere= CreateSphere()
EntityColor sphere,0,0,255
PositionEntity sphere,circle\x#,circle\y#,20
EntityType sphere,sphere_col;collisionccccccccccccccccccccccccccccc
Collisions sphere_col,cube_col,2,3
Global rsx#= .25 ;right movment value
Global lsx#=-.25 ;left movment value
Global usy#=-.25 ;up movement value
Global dsy#= .25 ;down movement value
;Const bx#=1
While Not KeyHit(1);Main MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
If KeyDown(30) MoveEntity sphere,lsx#,0,0
If KeyDown(32) MoveEntity sphere,rsx#,0,0
If KeyDown(17) MoveEntity sphere,0,dsy#,0
If KeyDown(31) MoveEntity sphere,0,usy#,0
UpdateWorld()
RenderWorld()
Color 255,255,0
Text 335,500,"Collision Detection"
Text 10,20,circle\x + circle\y
If EntityCollided(sphere,cube_col);collision
Text 370,80,"Collided !!!"
TranslateEntity cube,CollisionNX(sphere,1)*lsx#,CollisionNY(sphere,1)*usy,0
EndIf
Flip
Wend ;End of Main MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
End
Thats a sweet little tweak you just replaced 6 lines of code
with one line !!! I like it!
ok, so why isn't this working????? the collisions I meen
Graphics3D 640,480,16
SeedRnd MilliSecs()
light=CreateLight()
cam=CreateCamera()
;position camera looking straight down on plane
grid_tex=CreateTexture( 32,32,8 )
ScaleTexture grid_tex,10,10
SetBuffer TextureBuffer( grid_tex )
Color 0,0,64:Rect 0,0,32,32
Color 200,20,255:Rect 0,0,32,32,False
plane=CreatePlane()
EntityTexture plane,grid_tex
EntityBlend plane,1
EntityAlpha plane,.6
EntityFX plane,1
;mirror=CreateMirror()
;RotateEntity plane,0,90,0
PositionEntity cam,0,40,0
PointEntity cam,plane
;create player
Global sphere=CreateSphere()
ScaleEntity sphere,1.5,1.5,1.5
PositionEntity sphere,0,EntityY(plane)+4,0
;EntityType sphere,1
EntityType sphere,1
Dim cubes(6)
For n=1 To 6
cubes(n)=CreateCube()
EntityType cubes(n),2
;EntityType cubes(n),2
PositionEntity cubes(n),10+Rnd(-50,50),EntityY(plane)+6 ,0+Rnd(-50,50)
ScaleEntity cubes(n),6,6,6
Next
Global camangle
camangle=0
Global rsx#= .25 ;right movment value
Global lsx#=-.25 ;left movment value
Global usz#=-.25 ;up movement value
Global dsz#= .25 ;down movement value
Collisions 1,2,3,2
Collisions 2,2,3,2
;Collisions sphere,cube_col,2,3
While Not KeyHit(1)
;check for movement by user
If KeyDown(30) TranslateEntity sphere,lsx#,0,0
If KeyDown(32) TranslateEntity sphere,rsx#,0,0
If KeyDown(17) TranslateEntity sphere,0,0 ,dsz#
If KeyDown(31) TranslateEntity sphere,0,0,usz#
If EntityCollided(sphere,2)
For n=1 To CountCollisions(sphere)
ent = CollisionEntity(sphere,n)
x#=CollisionNX(sphere,n)/10
y#=CollisionNY(sphere,n)/10
z#=CollisionNZ(sphere,n)/10
TranslateEntity cubes(n),CollisionNX(sphere,2)*lsx#,0,CollisionNZ(sphere,2)*usz
TranslateEntity ent,-x#,-y#,-z#
Next
EndIf
updatePosition(cam,sphere)
UpdateWorld
RenderWorld
Flip
Wend
;This function checks to see if sphere is going to far away in any
;direction and if it does resets it on the oposit side of the screen
;also controls camera angle view of world
Function updatePosition(cam,sphere)
If KeyHit(42) Then camangle=camangle+1
If camangle>2 Then camangle=0
If camangle=1 Then
PositionEntity cam,EntityX(sphere),40,EntityZ(sphere)
EndIf
If camangle=2 Then
PositionEntity cam,EntityX(sphere)-15,40,EntityZ(sphere)-15
EndIf
PointEntity cam,sphere
If EntityX(sphere)=60 PositionEntity sphere,-50,EntityY(sphere),EntityZ(sphere)
If EntityX(sphere)=-60 PositionEntity sphere,50,EntityY(sphere),EntityZ(sphere)
If EntityZ(sphere)=60 PositionEntity sphere,EntityX(sphere),EntityY(sphere),-50
If EntityZ(sphere)=-60 PositionEntity sphere,EntityX(sphere),EntityY(sphere),50
End Function
Hi Matthew,
It's that you have scaled and repositioned the entities - but not their boundingboxes or collision radius (see entityradius() and entitybox() - they aren't colliding because they are on slightly different y planes with the original collision radius/boundingboxes setup.
Here's the fix Matthew - with the scaled up bounding
boxes/radii...
(;TranslateEntity cubes(n),CollisionNX(sphere,n) - I commented out this line - no idea what you mean it to do)
Graphics3D 640,480,16
SeedRnd MilliSecs()
light=CreateLight()
cam=CreateCamera()
;position camera looking straight down on plane
grid_tex=CreateTexture( 32,32,8 )
ScaleTexture grid_tex,10,10
SetBuffer TextureBuffer( grid_tex )
Color 0,0,64:Rect 0,0,32,32
Color 200,20,255:Rect 0,0,32,32,False
plane=CreatePlane()
EntityTexture plane,grid_tex
EntityBlend plane,1
EntityAlpha plane,.6
EntityFX plane,1
;mirror=CreateMirror()
;RotateEntity plane,0,90,0
PositionEntity cam,0,40,0
PointEntity cam,plane
;create player
Global sphere=CreateSphere()
ScaleEntity sphere,1.5,1.5,1.5
PositionEntity sphere,0,EntityY(plane)+4,0
;EntityType sphere,1
EntityType sphere,1
EntityRadius sphere,1.5
Dim cubes(6)
For n=1 To 6
cubes(n)=CreateCube()
EntityType cubes(n),2
;EntityType cubes(n),2
PositionEntity cubes(n),10+Rnd(-50,50),EntityY(plane)+6 ,0+Rnd(-50,50)
ScaleEntity cubes(n),6,6,6
EntityBox cubes(n),-6,-6,-6,12,12,12
EntityRadius cubes(n),6
Next
Global camangle
camangle=0
Global rsx#= .25 ;right movment value
Global lsx#=-.25 ;left movment value
Global usz#=-.25 ;up movement value
Global dsz#= .25 ;down movement value
Collisions 1,2,3,2
Collisions 2,2,3,2
;Collisions sphere,cube_col,2,3
While Not KeyHit(1)
;check for movement by user
If KeyDown(30) TranslateEntity sphere,lsx#,0,0
If KeyDown(32) TranslateEntity sphere,rsx#,0,0
If KeyDown(17) TranslateEntity sphere,0,0 ,dsz#
If KeyDown(31) TranslateEntity sphere,0,0,usz#
If EntityCollided(sphere,2)
For n=1 To CountCollisions(sphere)
ent = CollisionEntity(sphere,n)
x#=CollisionNX(sphere,n)/10
y#=CollisionNY(sphere,n)/10
z#=CollisionNZ(sphere,n)/10
;TranslateEntity cubes(n),CollisionNX(sphere,n)*lsx#,0,CollisionNZ(sphere,n)*usz ; DUNNO what you intend with this line
TranslateEntity ent,-x#,-y#,-z#
Next
EndIf
updatePosition(cam,sphere)
UpdateWorld
RenderWorld
Flip
Wend
;This function checks to see if sphere is going to far away in any
;direction and if it does resets it on the oposit side of the screen
;also controls camera angle view of world
Function updatePosition(cam,sphere)
If KeyHit(42) Then camangle=camangle+1
If camangle>2 Then camangle=0
If camangle=1 Then
PositionEntity cam,EntityX(sphere),40,EntityZ(sphere)
EndIf
If camangle=2 Then
PositionEntity cam,EntityX(sphere)-15,40,EntityZ(sphere)-15
EndIf
PointEntity cam,sphere
If EntityX(sphere)=60 PositionEntity sphere,-50,EntityY(sphere),EntityZ(sphere)
If EntityX(sphere)=-60 PositionEntity sphere,50,EntityY(sphere),EntityZ(sphere)
If EntityZ(sphere)=60 PositionEntity sphere,EntityX(sphere),EntityY(sphere),-50
If EntityZ(sphere)=-60 PositionEntity sphere,EntityX(sphere),EntityY(sphere),50
End Function
Thanks for the fix Brendan. I think I understand what you said about scaling the bounding box but I just have a few questions about your code.
1. Why do the position values in the line
EntityBox cubes(n),-6,-6,-6,12,12,12 have a negative value.
Does that mean its being drawn from that point -6 Xon the cube,-6 y on the cube, -6z on the cube and has nothing to do with the global xyz position of the cube it's self?
2.x#=CollisionNX(sphere,n)/10
y#=CollisionNY(sphere,n)/10
z#=CollisionNZ(sphere,n)/10
How did you come up with dividing by 10? I have tried diferent values that has a diferent efect each time.
Hi Matt,
1. Since you scaled the cube by 6 (the cube was originally from -1 to 1 on it's local axis) the -6's are the start position of the collision box (since 0,0,0 is the exact centre of the cube, in it's local axis of course)...
not sure if I have explained that clearly enough - but essentially the midpoint of the cube is 0,0,0 - using EntityBox you have to specify the start point of the collision box (ie. one corner) and tell it the size. In this case the new scaled up corner is now -6,-6,-6 and the new size is 12,12,12. It's much easier to grasp this if you draw it on paper - in effect it means that your collision box can be anywhere relative to your actual geometry.
2. The collision normal will always be of length 1. Now, since my character was moving by 0.2 units each frame I just scaled down this length to make an arbitrary but reasonable effect of pushing the boxes at half the speed of the player - ie. 1/10 = 0.1 - this gives the effect that the boxes have friction against the floor.
In your instance you are moving the character by 0.25 units each frame - therefore if you divide the collision normal values by 4 you will be moving the boxes at the exact speed of the player (1/4 = 0.25).
Sorry for waffling, hope that was a reasonable explanation.
You were not "waffling". You were in fact responding to a waffly question. Thanks for helping me out. I think I understand the first one(I'll experiment with it.)
The second one I get completly. It controls the speed during contact. Now I'm going to try to make my first puzzle
game. Don't worry, When I make my millions from it I'll share the glorry! Ha Ha
Hey no problem. Good luck!
I am new to Blitz3d and so am not sure if I will be much help, but I thought it looked silly not to have the cubes rotate. The physics of this are way off, but I kind of liked the effect this code gave me.
Graphics3D 640,480,16
SetBuffer BackBuffer()
Const cube_col=1
Const sphere_col=1
Global light= CreateLight()
Global camera=CreateCamera()
PositionEntity camera,0,40,0
RotateEntity camera,90,0,0
Global sphere=CreateSphere()
EntityType sphere,sphere_col
Global level=CreatePivot()
Dim cube(10)
For loop=0 To 10
cube(loop)=CreateCube(level)
PositionEntity cube(loop),-10,0,-10+loop*2
EntityType cube(loop),cube_col
Next
Collisions 1,1,2,2
While Not KeyHit(1)
If KeyDown(30) MoveEntity level,0.1,0,0
If KeyDown(32) MoveEntity level,-0.1,0,0
If KeyDown(17) MoveEntity level,0,0,-0.1
If KeyDown(31) MoveEntity level,0,0,0.1
If EntityCollided(sphere,1) Then colliderotate(sphere,EntityCollided(sphere,1))
UpdateWorld
RenderWorld
Flip
Wend
End
Function colliderotate(srcentity,dstentity)
x#=CollisionX(dstentity,1)
y#=CollisionY(dstentity,1)
z#=CollisionZ(dstentity,1)
RotateEntity dstentity,-y-EntityY(dstentity)*5,-z-EntityZ(dstentity)*5,-x-EntityX(dstentity)*5
End Function
If you have a more interesting or more acurate idea, I would be glad to see some code or hear a theory!
>I was suprized to find out that there is no examples on
>how to push objects around like in tomb raider, or
>resident evil.
http://www.blitzbasic.com/codearcs/codearcs.php?code=943Andy
You guys realize this was posted one year ago, right?
Yeah, isn't it great!
one thing to say.
Tokamak...