HERE IS A DEMO.
[CODE]
; thanks to SSWIFT for the nuts and bolts of this code
AppTitle "Ball Movement Demo ","goodbye"
; check to see if a graphics mode exist then
; if so set it, if not display error
If GfxMode3DExists (1024,768,16)
Graphics3D 1024,768
HidePointer
Else
RuntimeError "UPGRADE YOUR VIDEO CARD!"
EndIf
;-------------------------------------------------------------------------------------\
; GLOBALS
;-------------------------------------------------------------------------------------
; world vars
Global cam,lite,ball,world,ball_type,world_type
; Physics vars (thanks goes to sswift)
Const GRAVITY# = .0098
Const AIR_FRICTION_CONSTANT# = 0.01
Const GROUND_FRICTION_CONSTANT# = .0030
Global bullet_life=600
Global VX#,VY#,VZ#,NX#,NY#,NZ#,oldx#,newx#,oldz#,newz#,MX#,mz#
Global Velocity#,VdotN#,nfx#,nfy#,nfz#,Thrust_X#,Thrust_z#
Global Direction_X#,Direction_y#,Direction_z#
Global xAngleAdjust# ,ZAngleAdjust#,BallRadius#
Global Entity_Hit
Global jumping,player,vector_piv,balltex,BOX
Global midw=GraphicsWidth()/2,midh=GraphicsHeight()/2
Global speed#,lateral_speed#,cam_mx#,cam_my#,pyvel#
Global shot_timer
Type ball
Field entity,life,brush
Field vx#,vy#,vz#
Field oldx#,oldz#,newx#,newz#
End Type
SeedRnd MilliSecs
initialize_world()
For x= 1 To 32
b.ball= New ball
b\entity =CopyEntity(ball)
EntityType b\entity,ball_type
EntityRadius b\entity,.5
b\brush=CreateBrush()
BrushTexture b\brush,balltex
BrushColor b\brush,Rnd(0,255),Rnd(0,255),Rnd(0,255)
PaintEntity b\entity,b\brush
b\life=2
EntityAlpha b\entity,0
Next
; -------------------------------------------------------------------------------
Repeat ; * * * * beginning of loop
user_input()
update_ball()
fps_camera()
UpdateWorld
RenderWorld ; render the 3d scene
draw_crosshairs()
Flip ; flip the buffer
Until KeyDown(1)=1 ; * * * * end of loop
RuntimeError "goodbye"
ClearWorld
End
;=====================================================================================
; FUNCTIONS
;=====================================================================================
Function create_checker_tex(red1,green1,blue1,red2,green2,blue2,scale_u#,scale_v#)
texture_handle=CreateTexture(32,32)
SetBuffer TextureBuffer(texture_handle)
Color red1,green1,blue1
Rect 0,0,32,32
Color red2,green2,blue2
Rect 0,0,16,16,1
Rect 16,16,15,15,1
ScaleTexture texture_handle,scale_u#,scale_v#
SetBuffer BackBuffer()
Return texture_handle
End Function
;=====================================================================================
Function update_ball()
shot_timer=shot_timer-1
If shot_timer<1 Then shot_timer=0
For b.ball=Each ball
b\life=b\life-1
If b\life=1
HideEntity b\entity
PositionEntity b\entity,EntityX(cam),EntityY(cam),EntityZ(cam)
b\vx=0
b\vy=0
b\vz=0
b\life=0
EndIf
Entity_Hit = EntityCollided(b\entity, world_type)
For x=1 To CountCollisions(B\ENTITY)
If CollisionEntity(b\entity,x)=box
EntityColor box,Rnd(0,100),Rnd(0,100),Rnd(0,100)
EndIf
Next
Velocity# = Sqr(b\Vx#^2 + b\Vy#^2 + b\Vz#^2)
If Velocity# > 0 ; Calculate the direction vector. The direction vector has a length of 1.
If b\life>1 ; only if there is life left
Direction_X# = b\Vx# / Velocity#
Direction_Y# = b\Vy# / Velocity#
Direction_Z# = b\Vz# / Velocity#
; Compute air friction. ; Air friction is dependent on the speed of the entity, and will prevent it from accelerting forever.
Air_Friction_Force# = AIR_FRICTION_CONSTANT# * Velocity#^2.0
Velocity# = Velocity# - (Air_Friction_Force# )
; If the entity collided with the level, apply ground friction.
If Entity_Hit > 0 ; Compute ground friction. Ground friction is not dependent on the speed of the entity.
Velocity# = Velocity# - (GROUND_FRICTION_CONSTANT#)
EndIf
; Make sure the entity's velocity doesn't go below 0.
; It is impossible to have a negative velocity in physics and "bad things" happen if you try to.
If (Velocity# < 0) Then Velocity# = Velocity#+.001
; Convert the entity's velocity and direction back into a motion vector.
b\Vx# = Direction_X# * Velocity#
b\Vy# = Direction_Y# * Velocity#
b\Vz# = Direction_Z# * Velocity#
; If the entity collided with the level, make it bounce.
If Entity_Hit > 0
; Calculate bounce:
; Get the normal of the surface which the entity collided with.
Nx# = CollisionNX(b\entity, 1)
Ny# = CollisionNY(b\entity, 1)
Nz# = CollisionNZ(b\entity, 1)
; Compute the dot product of the entity's motion vector and the normal of the surface collided with.
VdotN# = b\Vx#*Nx# + b\Vy#*Ny# + b\Vz#*Nz#
; Calculate the normal force.
NFx# = -2.0 * Nx# * VdotN#
NFy# = -2.0 * Ny# * VdotN#
NFz# = -2.0 * Nz# * VdotN#
; Add the normal force to the direction vector.
b\Vx# = b\Vx# + NFx#
b\Vy# = b\Vy# + NFy#
b\Vz# = b\Vz# + NFz#
; Do not allow the entity to move vertically.
;If Vy# > 0 Then Vy# = 0
EndIf
EndIf
EndIf
; Apply directional thrust:
; If the entity collided with the level, apply directional thrust.
;If Entity_Hit > 0
; Take thrust in object space, and translates it to an XYZ vector in world space.
;TFormVector 0, 0, Thrust#, ballpos, 0
; Add any thrust being applied this frame.
; There's a very good reason why this is done AFTER the friction is calculated.
; It involves inequalities in force cause by variable framerates.
b\Vx# = b\Vx# + (Thrust_X# )
b\Vz# = b\Vz# + (Thrust_Z# )
;EndIf
; Apply gravity:
b\Vy# = b\Vy# - (GRAVITY# )
; Move and rotate the entity:
; We rotate the entity by the actual distance moved and not by the velocity because if we rotate according
; to the velocity then the entity will roll when it's up against a wall and not moving.
b\OldX# = b\NewX#
b\OldZ# = b\NewZ#
TranslateEntity b\entity, b\Vx#, b\Vy#, b\Vz#, True
b\NewX# = EntityX#(b\entity, True)
b\NewZ# = EntityZ#(b\entity, True)
Mx# = (b\NewX# - b\OldX#)
Mz# = (b\NewZ# - b\OldZ#)
; Rotate the entity the right amount for it's radius and the distance it has moved along the X and Z axis.
; This is kinda a hack and only designed for rolling on planes but you won't notice the diffrence.
XAngleAdjust# = (Mx# / BallRadius#) * (180.0/Pi)
ZAngleAdjust# = (Mz# / BallRadius#) * (180.0/Pi)
TurnEntity b\entity,ZAngleAdjust#,0,-XAngleAdjust#,True
Next
End Function
;=====================================================================================
Function user_input()
If KeyDown(17)=1 Or KeyDown(200) Then vz#=vz#+ .01
If KeyDown(30)=1 Or KeyDown(203) Then vx# = vx# - .01
If KeyDown(31)=1 Or KeyDown(208) Then vz# = vz# -.01
If KeyDown(32)=1 Or KeyDown(205) Then vx# = vx# + .01
If KeyDown(57)=1 Then VY#=VY#+.1
End Function
;=====================================================================================
Function initialize_world()
cam=CreateCamera() ; create a world camera
player=CreatePivot()
EntityRadius player,2
MoveEntity player,0,10,-10
vector_piv=CreatePivot()
;MoveEntity cam,0,10,-25 ; move the camera "back" 5 units
;MoveEntity lite,-10,10,-10
ball=CreateSphere(12) ; create a cube and call it blob
HideEntity ball
PositionEntity ball,-1,10,0 ; place the blob at world coordinate 0,0,3
AmbientLight(50,50,50)
lite=CreateLight(3) ; create a light for our world
PositionEntity lite,-20,20,-20
PointEntity lite,ball
balltex=create_checker_tex(0,150,0,0,0,100,.25,.25)
;EntityColor ball,255,0,0 ; color our blob, red, green , blue
world=CreateCube()
;RotateMesh world,0,0,0
ws=CreateSphere(12)
EntityTexture ws,create_checker_tex(0,50,0,100,75,0,.125,.125)
BOX=CreateCube()
EntityAlpha BOX,.8
RotateMesh BOX,0,45,0
PositionEntity box,10,5,10
ScaleEntity box,3,6,3
ScaleEntity ws,7,3,7
;MoveEntity ws,0,-5,0
ScaleEntity world,25,15,25
MoveEntity world,0,15,0
;AddMesh ws,world
EntityTexture world,create_checker_tex(200,200,0,0,0,0,.5,.5)
FlipMesh world
; SETUP COLLISIONS
ball_type=1 ; collision types
world_type=2
BallRadius#=.5
EntityType world,world_type
EntityType ws,world_type
EntityType box,world_type
EntityColor box,255,0,0
EntityType player,ball_type
Collisions ball_type,world_type,2,2 ;sphere-to-poly collisions between the ball and the world and set response to "STOP"
End Function
;=====================================================================================
Function fps_camera()
;If KeyDown(57) And jumping=0 ; SPACE to JUMP
; jumping=1
; pyvel#=.2
;EndIf
If KeyDown(17)=1 Or KeyDown(200) Then speed#=speed#+.005 +boost#
If KeyDown(30)=1 Or KeyDown(203) Then lateral_speed# = lateral_speed# - .004 +boost#
If KeyDown(31)=1 Or KeyDown(208) Then speed# = speed# -(.005 +boost#)
If KeyDown(32)=1 Or KeyDown(205) Then lateral_speed# = lateral_speed# + .004 +boost#
; FRICTION FOR SMOOTH MOVEMENT
lateral_speed#=lateral_speed#*.97
speed#=speed#*.95
PositionEntity cam,EntityX(player),EntityY(player)+1,EntityZ(player)
; CAMERA MOVEMENTS
cam_MY#=curvevalue#(MouseYSpeed(),cam_MY#,4 )
cam_MX#=curvevalue#(MouseXSpeed(),cam_MX#,4 )
TurnEntity cam,cam_MY#,0,0 ; turn camera up and down
TurnEntity player,0,-cam_mx,0 ; turn pivot left --right
RotateEntity cam,EntityPitch(cam),EntityYaw(player),0
MoveMouse midw,midh; Bring mouse to middle of screen for mouselook to work
If on_platform=0 Then pyvel#=pyvel#-gravity#
;pyvel#=pyvel#*.99
;move the player --- the camera in this case!
MoveEntity player,lateral_speed#,pyvel#,speed#
TranslateEntity player,pxvel#,0,pzvel#
pxvel#=pxvel#*.9
pzvel#=pzvel#*.9
If MouseDown(1)= 1 Then fire_cannon()
FlushKeys
FlushMouse
End Function
;=====================================================================================
Function curvevalue#(newvalue#,oldvalue#,increments# )
If increments>1 Then oldvalue#=oldvalue#-(oldvalue#-newvalue#)/increments
If increments<=1 Then oldvalue=newvalue
Return oldvalue#
End Function
;=====================================================================================
Function fire_cannon()
If shot_timer=0
For b.ball = Each ball
If b\life<1
ShowEntity b\entity
EntityAlpha b\entity,1
PositionEntity b\entity,EntityX(cam),EntityY(cam)+.4,EntityZ(cam)
PositionEntity vector_piv,EntityX(cam),EntityY(cam)+.4,EntityZ(cam)
RotateEntity vector_piv,EntityPitch(cam),EntityYaw(cam),EntityRoll(cam)
MoveEntity vector_piv,0,0,5
vectx#=EntityX(vector_piv)-EntityX(cam)
vecty#=EntityY(vector_piv)-EntityY(cam)
vectz#=EntityZ(vector_piv)-EntityZ(cam)
TFormVector vectx#,vecty#,vectz#,vector_piv,cam
b\vx=TFormedX() /8
b\vz=TFormedZ() /8
b\vy=TFormedY() /4
b\life=bullet_life
shot_timer=20
Exit
EndIf
Next
EndIf
End Function
;=====================================================================================
Function update_cannon()
shot_timer=shot_timer-1
If shot_timer<1 Then shot_timer=0
For b.ball = Each ball
Next
End Function
;=====================================================================================
Function draw_crosshairs()
Color 0,235,0
Rect midw-6,midh-6,12,12,0
Line midw-6,midh,midw+6,midh
End Function
;=====================================================================================
;=====================================================================================
;=====================================================================================
;=====================================================================================
;=====================================================================================
;=====================================================================================
;=====================================================================================
;=====================================================================================
;=====================================================================================
[/CODE]