projectile physics (with ellipsoid / with linepick)


Attention! 👉Starting November 2024, BlitzCoder.org will now be BlitzBasic.org.

 

Tweet blitz3d collision-detection physics code-archives miscellaneous
RemiD

an example with linepicks and pickables :

;projectile physics (with linepick and pickables) 20181004

Graphics3D(1000,624,32,2)

HidePointer()

SeedRnd(MilliSecs())

Global MXDiff%
Global MYDiff%

;camera
Global Camera = CreateCamera()
CameraRange(Camera,1,1000)
CameraClsColor(Camera,001,001,001)

;origine
Origine = CreateCube()
ScaleMesh(Origine,0.03/2,0.03/2,0/03.2)
EntityColor(Origine,255,000,255)
EntityFX(Origine,1)

Global GhostRoot
Global GhostRootYaw#
Global GhostEyes
Global GhostEyesPitch#
AddGhost()

;room
Global Room = CreateCube() ;CreateCube() CreateCylinder(4) CreateCylinder(8) CreateSphere(2) CreateSphere(4) CreateSphere(8)
FlipMesh(Room)
ScaleMesh(Room,100.0/2,50.0/2,100.0/2)
PositionMesh(Room,50,25,50)
For GX% = 0 To 90 Step 10
 For GZ% = 0 To 90 Step 10
  TPart = CreateCube()
  ScaleMesh(TPart,10.0/2,50.0/2,10.0/2)
  PositionMesh(TPart,10.0/2,-50.0/2,10.0/2)
  PositionMesh(TPart,GX,Rand(1,12),GZ)
  AddMesh(TPart,Room) : FreeEntity(TPart)
 Next
Next
PositionEntity(Room,0,0,0,True)
EntityColor(Room,125,125,125)

;projectiles
Global ProjectilesCount%
Type Projectile
 Field State%
 Field Shape
 Field Radius#
 Field Gravity#
 Field VX#, VY#, VZ#
 Field VLength#
End Type

Const CIdle% = 1
Const CTranslate% = 2

Global Pivot = CreatePivot()

EntityPickMode(Room,2)

DLight = CreateLight(1)
LightColor(DLight,255,255,255)
PositionEntity(DLight,50,1000,-1000)
RotateEntity(DLight,45,0,0)

AmbientLight(064,064,064)

PositionEntity(GhostRoot,50,25+1.65,90,True)
GhostRootYaw = 180

Global MainLoopTimer = CreateTimer(30)

;mainloop
Main()

End()

Function Main()

 Repeat

  MainLoopMilliStart% = MilliSecs()

  MXDiff = MouseXSpeed()
  MYDiff = MouseYSpeed()

  UpdateGhost()

  ;update projectiles
  UpdateProjectiles()

  PositionRotateEntityLikeOtherEntity(Camera,GhostEyes)

  ;wireframe mode off/on
  WireFrame(False)
  If( KeyDown(2)=True )
   WireFrame(True)
  EndIf

  ;render
  SetBuffer(BackBuffer())
  RenderWorld()

  Color(255,255,255)
  Text(0,0,"ProjectilesCount = "+ProjectilesCount) 
  PhysicsCount% = 0
  For pr.Projectile = Each Projectile
   If( pr\State = CTranslate )
    PhysicsCount = PhysicsCount + 1
   EndIf
  Next
  Text(0,15,"Physics active on "+PhysicsCount+" projectiles")

  Text(500,0,"Tris = "+TrisRendered()) 
  Text(500,16,"FPS = "+FPS)

  ;display the result on the screen
  ;Flip(1)
  WaitTimer(MainLoopTimer)
  VWait():Flip(False)

  MainLoopMilliTime = MilliSecs() - MainLoopMilliStart
  If( MainLoopMilliTime < 1 )
   MainLoopMilliTime = 1
  EndIf

  FPS% = 1000.0/MainLoopMilliTime

 Until( KeyDown(1)=1 )

End Function

Function PositionEntityLikeOtherEntity(Entity,OEntity)

 PositionEntity(Entity,EntityX(OEntity,True),EntityY(OEntity,True),EntityZ(OEntity,True),True)

End Function

Function RotateEntityLikeOtherEntity(Entity,OEntity)

 RotateEntity(Entity,EntityPitch(OEntity,True),EntityYaw(OEntity,True),EntityRoll(OEntity,True),True)

End Function

Function PositionRotateEntityLikeOtherEntity(Entity,OEntity)

 PositionEntity(Entity,EntityX(OEntity,True),EntityY(OEntity,True),EntityZ(OEntity,True),True)
 RotateEntity(Entity,EntityPitch(OEntity,True),EntityYaw(OEntity,True),EntityRoll(OEntity,True),True)

End Function

Function Distance2D#(PAX#,PAZ#,PBX#,PBZ#)

 Distance2D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) )
 Return Distance2D

End Function

Function Distance3D#(PAX#,PAY#,PAZ#,PBX#,PBY#,PBZ#)

 Distance3D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBY - PAY ) * ( PBY - PAY ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) )
 Return Distance3D

End Function

Function Angle3D#(V1X#,V1Y#,V1Z#,V2X#,V2Y#,V2Z#)

 D# = (V1X*V2X) + (V1Y*V2Y) + (V1Z*V2Z)
 M# = Sqr( V1X*V1X + V1Y*V1Y + V1Z*V1Z ) * Sqr( V2X*V2X + V2Y*V2Y + V2Z*V2Z )
 A# = ACos(D#/M#)
 Return A#

End Function

Function AddGhost()

 GhostRoot = CreatePivot()

 GhostEyes = CreatePivot()
 PositionRotateEntityLikeOtherEntity(GhostEyes,GhostRoot)
 EntityParent(GhostEyes,GhostRoot,True)

End Function

Function UpdateGhost()

 MoveMouse(GraphicsWidth()/2,GraphicsHeight()/2)
 GhostEyesPitch = GhostEyesPitch + Float(MYDiff)/10
 If( GhostEyesPitch < -89 )
  GhostEyesPitch = -89
 Else If( GhostEyesPitch > 89 )
  GhostEyesPitch = 89
 EndIf
 RotateEntity(GhostEyes,GhostEyesPitch,0,0,False)
 GhostRootYaw = GhostRootYaw - Float(MXDiff)/10
 RotateEntity(GhostRoot,0,GhostRootYaw,0,False)

 If( KeyDown(42) = 0 And KeyDown(29) = 0 )
  Speed# = 0.1
 Else If( KeyDown(42) = 1 And KeyDown(29) = 0 )
  Speed# = 1
 Else If( KeyDown(42) = 0 And KeyDown(29) = 1 )
  Speed# = 0.01
 EndIf

 If( KeyDown(17)=1 )
  MoveEntity(GhostRoot,0,0,Speed)
 Else If( KeyDown(31)=1 )
  MoveEntity(GhostRoot,0,0,-Speed)
 EndIf
 If( KeyDown(30)=1 )
  MoveEntity(GhostRoot,-Speed,0,0)
 Else If( KeyDown(32)=1 )
  MoveEntity(GhostRoot,Speed,0,0)
 EndIf
 If( KeyDown(16)=1 )
  MoveEntity(GhostRoot,0,-Speed,0)
 Else If( KeyDown(18)=1 )
  MoveEntity(GhostRoot,0,Speed,0)
 EndIf

 If( MouseHit(1)=1 )
  DebugLog("")
  ;create a new projectile
  ProjectilesCount = ProjectilesCount + 1
  pr.Projectile = New Projectile

  pr\Radius# = Rnd(0.05,0.5)/2*10
  pr\Shape = CreateSphere(16)
  ScaleMesh(pr\Shape,pr\Radius,pr\Radius,pr\Radius)
  ThrowForce# = 46.940*2.0/30.0
  pr\Gravity = 0 

  ;calculate translation vector (whole vector) 
  TFormVector(0,0,+ThrowForce,GhostEyes,0)
  pr\VX = TFormedX() : pr\VY = TFormedY() : pr\VZ = TFormedZ()

  ;calculate translation length (whole length)
  pr\VLength = Sqr( pr\VX*pr\VX + pr\VY*pr\VY + pr\VZ*pr\VZ )
  PositionEntity(pr\Shape,EntityX(GhostEyes,True),EntityY(GhostEyes,True),EntityZ(GhostEyes,True),True)

  ;state = translate
  pr\State = CTranslate
  EntityColor(pr\Shape,000,000,255)

  EntityRadius(pr\Shape,pr\Radius-0.01)
  EntityPickMode(pr\Shape,1)

 EndIf

End Function

Function UpdateProjectiles()

 For pr.Projectile = Each Projectile

  If( pr\State = CIdle )

   ;

  Else If( pr\State = CTranslate )

   ;calculate new Whole vector

   ;increase gravity force
   pr\Gravity = 9.81/30.0/2

   ;add gravity force to Whole vector
   pr\VX = pr\VX : pr\VY = pr\VY-pr\Gravity : pr\VZ = pr\VZ

   ;(add air friction to Whole vector)
   ;pr\VX = pr\VX*0.999 : pr\VY = pr\VY*0.999 : pr\VZ = pr\VZ*0.999

   ;calculate new Whole length
   pr\VLength = Sqr( pr\VX*pr\VX + pr\VY*pr\VY + pr\VZ*pr\VZ )

   ;initialize Remaining vector
   RVX# = pr\VX : RVY# = pr\VY : RVZ# = pr\VZ

   ;initialize Remaining length
   RLength# = pr\VLength

   Repeat

    ;store Before position
    befX# = EntityX(pr\Shape,True) : befY# = EntityY(pr\Shape,True) : befZ# = EntityZ(pr\Shape,True)

    ;check if there is an obstacle in this direction at the Remaining length (+radius)
    picEnt% = LinePick(befX,befY,befZ,RVX,RVY,RVZ,pr\Radius) 

    ;if yes
    If( picEnt <> 0 ) 

     ;store pic position
     picX# = PickedX() : picY# = PickedY() : picZ# = PickedZ()
     ;store pic normal
     picNX# = PickedNX() : picNY# = PickedNY() : picNZ# = PickedNZ()

     ;calculate When position
     PositionEntity(Pivot,picX,picY,picZ,True) : AlignToVector(Pivot,picNX,picNY,picNZ,3,1.0) : MoveEntity(Pivot,0,0,pr\Radius)
     wheX# = EntityX(Pivot,True) : wheY# = EntityY(Pivot,True) : wheZ# = EntityZ(Pivot,True)

     ;calculate Before length (Before position -> When position)
     BLength# = Distance3D(befX,befY,befZ,wheX,wheY,wheZ)
     ;calculate Before coef (BLength/RLength)
     BCoef# = BLength/RLength
     ;calculate Before vector
     BVX# = RVX*BCoef : BVY# = RVY*BCoef : BVZ# = RVZ*BCoef

     ;translate entity with Before vector
     TranslateEntity(pr\Shape,BVX,BVY,BVZ,True)

     ;calculate New vector (reflection vector)
     DP# = RVX*picNX + RVY*picNY + RVZ*picNZ 
     NFX# = -2.0*picNX*DP : NFY# = -2.0*picNY*DP : NFZ# = -2.0*picNZ*DP
     NVX# = RVX+NFX*1.1 : NVY# = RVY+NFY*1.1 : NVZ# = RVZ+NFZ*1.1

     ;calculate angle between Remaining vector and New vector
     A# = Angle3D(RVX,RVY,RVZ,NVX,NVY,NVZ)

     ;attenuate New vector depending on angle
     AttCoef# = (1.0-(A/180.0))

     ;DebugLog(A+" "+AttCoef)
     NVX = NVX*AttCoef : NVY = NVY*AttCoef : NVZ = NVZ*AttCoef

     ;attenuate New vector depending on arbitrary coef
     ;NVX = NVX*0.9 : NVY = NVY*0.9 : NVZ = NVZ*0.9

     ;calculate New length
     NLength# = Sqr( NVX*NVX + NVY*NVY + NVZ*NVZ )

     ;initialize Remaining vector
     RVX = NVX : RVY = NVY : RVZ = NVZ
     ;initialize Remaining length
     RLength = NLength

     ;
     pr\VX = NVX : pr\VY = NVY : pr\VZ = NVZ
     pr\VLength = NLength

     ;check if Remaining length is inferior or equal to gravityforce
     ;if yes
     If( RLength < pr\Gravity )

      EntityColor(pr\Shape,125,255,255)

      ;check if the ground below is near or far
      picEnt% = LinePick(wheX,wheY,wheZ,0,-100,0,pr\Radius)
      If( picEnt <> 0 )
       picX# = PickedX() : picY# = PickedY() : picZ# = PickedZ()     
       ;if near
       If( wheY-picY < pr\Radius+pr\Gravity )

        ;0 Remaining vector
        RVX = 0 : RVY = 0 : RVZ = 0
        ;0 Remaining length
        RLength = 0
        ;0 gravity force
        pr\Gravity = 0

        ;state = idle
        pr\State = CIdle
        EntityColor(pr\Shape,125,125,255)

       EndIf
       ;if far
        ;

      EndIf

     EndIf

    Else If( picEnt = 0 )

     ;translate entity with Remaining vector
     TranslateEntity(pr\Shape,RVX,RVY,RVZ,True)

     ;0 Remaining vector
     RVX = 0 : RVY = 0 : RVZ = 0
     ;0 Remaining length
     RLength = 0

    EndIf

   Until( Rlength = 0 )

  EndIf

  If( pr <> Null )
   If( EntityY(pr\Shape,True) < -100 )
    ProjectilesCount = ProjectilesCount - 1
    FreeEntity(pr\Shape) : Delete(pr)
   EndIf
  EndIf

 Next

End Function

an example with ellipsoids and collidables :

;projectile physics (with ellipsoid and collidables) 20181004

Graphics3D(1000,624,32,2)

HidePointer()

SeedRnd(MilliSecs())

Global MXDiff%
Global MYDiff%

;camera
Global Camera = CreateCamera()
CameraRange(Camera,1,1000)
CameraClsColor(Camera,001,001,001)

;origine
Origine = CreateCube()
ScaleMesh(Origine,0.03/2,0.03/2,0/03.2)
EntityColor(Origine,255,000,255)
EntityFX(Origine,1)

Global GhostRoot
Global GhostRootYaw#
Global GhostEyes
Global GhostEyesPitch#
AddGhost()

;room
Global Room = CreateCube() ;CreateCube() CreateCylinder(4) CreateCylinder(8) CreateSphere(2) CreateSphere(4) CreateSphere(8)
FlipMesh(Room)
ScaleMesh(Room,100.0/2,50.0/2,100.0/2)
PositionMesh(Room,50,25,50)
For GX% = 0 To 90 Step 10
 For GZ% = 0 To 90 Step 10
  TPart = CreateCube()
  ScaleMesh(TPart,10.0/2,50.0/2,10.0/2)
  PositionMesh(TPart,10.0/2,-50.0/2,10.0/2)
  PositionMesh(TPart,GX,Rand(1,12),GZ)
  AddMesh(TPart,Room) : FreeEntity(TPart)
 Next
Next
PositionEntity(Room,0,0,0,True)
EntityColor(Room,125,125,125)

;projectiles
Global ProjectilesCount%
Type Projectile
 Field State%
 Field Shape
 Field Radius#
 Field Gravity#
 Field VX#, VY#, VZ#
 Field VLength#
 Field befX#, befY#, befZ#
End Type

Const CIdle% = 1
Const CTranslate% = 2

Global Pivot = CreatePivot()

Const GRoom% = 1
Const GProjectile% = 2
EntityType(Room,GRoom)
Collisions(GProjectile,GRoom,2,1)
Collisions(GProjectile,GProjectile,1,1)

EntityPickMode(Room,2)

DLight = CreateLight(1)
LightColor(DLight,255,255,255)
PositionEntity(DLight,50,1000,-1000)
RotateEntity(DLight,45,0,0)

AmbientLight(064,064,064)

PositionEntity(GhostRoot,50,25+1.65,90,True)
GhostRootYaw = 180

Global MainLoopTimer = CreateTimer(30)

;mainloop
Main()

End()

Function Main()

 Repeat

  MainLoopMilliStart% = MilliSecs()

  MXDiff = MouseXSpeed()
  MYDiff = MouseYSpeed()

  UpdateGhost()

  ;update projectiles
  UpdateProjectilesBefore()

  UpdateWorld()

  UpdateProjectilesAfter()

  PositionRotateEntityLikeOtherEntity(Camera,GhostEyes)

  ;wireframe mode off/on
  WireFrame(False)
  If( KeyDown(2)=True )
   WireFrame(True)
  EndIf

  ;render
  SetBuffer(BackBuffer())
  RenderWorld()

  Color(255,255,255)
  Text(0,0,"ProjectilesCount = "+ProjectilesCount) 
  PhysicsCount% = 0
  For pr.Projectile = Each Projectile
   If( pr\State = CTranslate )
    PhysicsCount = PhysicsCount + 1
   EndIf
  Next
  Text(0,15,"Physics active on "+PhysicsCount+" projectiles")

  Text(500,0,"Tris = "+TrisRendered()) 
  Text(500,16,"FPS = "+FPS)

  ;display the result on the screen
  ;Flip(1)
  WaitTimer(MainLoopTimer)
  VWait():Flip(False)

  MainLoopMilliTime = MilliSecs() - MainLoopMilliStart
  If( MainLoopMilliTime < 1 )
   MainLoopMilliTime = 1
  EndIf

  FPS% = 1000.0/MainLoopMilliTime

 Until( KeyDown(1)=1 )

End Function

Function PositionEntityLikeOtherEntity(Entity,OEntity)

 PositionEntity(Entity,EntityX(OEntity,True),EntityY(OEntity,True),EntityZ(OEntity,True),True)

End Function

Function RotateEntityLikeOtherEntity(Entity,OEntity)

 RotateEntity(Entity,EntityPitch(OEntity,True),EntityYaw(OEntity,True),EntityRoll(OEntity,True),True)

End Function

Function PositionRotateEntityLikeOtherEntity(Entity,OEntity)

 PositionEntity(Entity,EntityX(OEntity,True),EntityY(OEntity,True),EntityZ(OEntity,True),True)
 RotateEntity(Entity,EntityPitch(OEntity,True),EntityYaw(OEntity,True),EntityRoll(OEntity,True),True)

End Function

Function Distance2D#(PAX#,PAZ#,PBX#,PBZ#)

 Distance2D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) )
 Return Distance2D

End Function

Function Distance3D#(PAX#,PAY#,PAZ#,PBX#,PBY#,PBZ#)

 Distance3D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBY - PAY ) * ( PBY - PAY ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) )
 Return Distance3D

End Function

Function Angle3D#(V1X#,V1Y#,V1Z#,V2X#,V2Y#,V2Z#)

 D# = (V1X*V2X) + (V1Y*V2Y) + (V1Z*V2Z)
 M# = Sqr( V1X*V1X + V1Y*V1Y + V1Z*V1Z ) * Sqr( V2X*V2X + V2Y*V2Y + V2Z*V2Z )
 A# = ACos(D#/M#)
 Return A#

End Function

Function AddGhost()

 GhostRoot = CreatePivot()

 GhostEyes = CreatePivot()
 PositionRotateEntityLikeOtherEntity(GhostEyes,GhostRoot)
 EntityParent(GhostEyes,GhostRoot,True)

End Function

Function UpdateGhost()

 MoveMouse(GraphicsWidth()/2,GraphicsHeight()/2)
 GhostEyesPitch = GhostEyesPitch + Float(MYDiff)/10
 If( GhostEyesPitch < -89 )
  GhostEyesPitch = -89
 Else If( GhostEyesPitch > 89 )
  GhostEyesPitch = 89
 EndIf
 RotateEntity(GhostEyes,GhostEyesPitch,0,0,False)
 GhostRootYaw = GhostRootYaw - Float(MXDiff)/10
 RotateEntity(GhostRoot,0,GhostRootYaw,0,False)

 If( KeyDown(42) = 0 And KeyDown(29) = 0 )
  Speed# = 0.1
 Else If( KeyDown(42) = 1 And KeyDown(29) = 0 )
  Speed# = 1
 Else If( KeyDown(42) = 0 And KeyDown(29) = 1 )
  Speed# = 0.01
 EndIf

 If( KeyDown(17)=1 )
  MoveEntity(GhostRoot,0,0,Speed)
 Else If( KeyDown(31)=1 )
  MoveEntity(GhostRoot,0,0,-Speed)
 EndIf
 If( KeyDown(30)=1 )
  MoveEntity(GhostRoot,-Speed,0,0)
 Else If( KeyDown(32)=1 )
  MoveEntity(GhostRoot,Speed,0,0)
 EndIf
 If( KeyDown(16)=1 )
  MoveEntity(GhostRoot,0,-Speed,0)
 Else If( KeyDown(18)=1 )
  MoveEntity(GhostRoot,0,Speed,0)
 EndIf

 If( MouseHit(1)=1 )
  DebugLog("")
  ;create a new projectile
  ProjectilesCount = ProjectilesCount + 1
  pr.Projectile = New Projectile

  pr\Radius# = Rnd(0.05,0.5)/2*10
  pr\Shape = CreateSphere(16)
  ScaleMesh(pr\Shape,pr\Radius,pr\Radius,pr\Radius)
  ThrowForce# = 46.940*2.0/30.0
  pr\Gravity = 0 

  ;calculate translation vector (whole vector) 
  TFormVector(0,0,+ThrowForce,GhostEyes,0)
  pr\VX = TFormedX() : pr\VY = TFormedY() : pr\VZ = TFormedZ()

  ;calculate translation length (whole length)
  pr\VLength = Sqr( pr\VX*pr\VX + pr\VY*pr\VY + pr\VZ*pr\VZ )
  PositionEntity(pr\Shape,EntityX(GhostEyes,True),EntityY(GhostEyes,True),EntityZ(GhostEyes,True),True)

  ;state = translate
  pr\State = CTranslate
  EntityColor(pr\Shape,000,000,255)

  EntityRadius(pr\Shape,pr\Radius-0.01)
  EntityType(pr\Shape,GProjectile)
  EntityPickMode(pr\Shape,2)

 EndIf

End Function

Function UpdateProjectilesBefore()

 For pr.Projectile = Each Projectile

  If( pr\State = CIdle )

   ;

  Else If( pr\State = CTranslate )

   ;calculate new Whole vector

   ;increase gravity force
   pr\Gravity = 9.81/30.0/2

   ;add gravity force to Whole vector
   pr\VX = pr\VX : pr\VY = pr\VY-pr\Gravity : pr\VZ = pr\VZ

   ;(add air friction to Whole vector)
   ;pr\VX = pr\VX*0.999 : pr\VY = pr\VY*0.999 : pr\VZ = pr\VZ*0.999

   ;calculate new Whole length
   pr\VLength = Sqr( pr\VX*pr\VX + pr\VY*pr\VY + pr\VZ*pr\VZ )

   ;store Before position
   pr\befX# = EntityX(pr\Shape,True) : pr\befY# = EntityY(pr\Shape,True) : pr\befZ# = EntityZ(pr\Shape,True)

   ;translate entity with whole vector
   TranslateEntity(pr\Shape,pr\VX,pr\VY,pr\VZ,True) 

  EndIf

  If( pr <> Null )
   If( EntityY(pr\Shape,True) < -100 )
    ProjectilesCount = ProjectilesCount - 1
    FreeEntity(pr\Shape) : Delete(pr)
   EndIf
  EndIf

 Next

End Function

Function UpdateProjectilesAfter()

 For pr.Projectile = Each Projectile

  If( pr\State = CIdle )

   ;

  Else If( pr\State = CTranslate )

   ;check if a collision happened when translating entity along whole vector
   nc% = CountCollisions(pr\Shape)
   ;if yes
   If( nc > 0 )

    ;collision detected, get infos about the collision
    colEnt% = CollisionEntity(pr\Shape,1)
    ;store collision position
    colX# = CollisionX(pr\Shape,1) : colY# = CollisionY(pr\Shape,1) : colZ# = CollisionZ(pr\Shape,1)
    ;store collision normal
    colNX# = CollisionNX(pr\Shape,1) : colNY# = CollisionNY(pr\Shape,1) : colNZ# = CollisionNZ(pr\Shape,1)

    ;calculate When position
    wheX# = EntityX(pr\Shape,True) : wheY# = EntityY(pr\Shape,True) : wheZ# = EntityZ(pr\Shape,True)

    ;calculate New vector (reflection vector)
    DP# = pr\VX*colNX + pr\VY*colNY + pr\VZ*colNZ 
    NFX# = -2.0*colNX*DP : NFY# = -2.0*colNY*DP : NFZ# = -2.0*colNZ*DP
    NVX# = pr\VX+NFX*1.1 : NVY# = pr\VY+NFY*1.1 : NVZ# = pr\VZ+NFZ*1.1

    ;calculate angle between Remaining vector and New vector
    A# = Angle3D(pr\VX,pr\VY,pr\VZ,NVX,NVY,NVZ)

    ;attenuate New vector depending on angle
    AttCoef# = (1.0-(A/180.0))

    ;DebugLog(A+" "+AttCoef)
    NVX = NVX*AttCoef : NVY = NVY*AttCoef : NVZ = NVZ*AttCoef

    ;calculate New length
    NLength# = Sqr( NVX*NVX + NVY*NVY + NVZ*NVZ )

    pr\VX = NVX : pr\VY = NVY : pr\VZ = NVZ
    pr\VLength = NLength

    ;check if Remaining length is inferior or equal to gravityforce
    ;if yes
    If( pr\VLength < pr\Gravity )
     EntityColor(pr\Shape,125,255,255)

     ;check if the ground below is near or far
     picEnt% = LinePick(wheX,wheY,wheZ,0,-100,0,pr\Radius-0.01)
     If( picEnt <> 0 )
      picX# = PickedX() : picY# = PickedY() : picZ# = PickedZ()     
      ;if near
      If( wheY-picY < pr\Radius+pr\Gravity )

       ;0 Remaining vector
       pr\VX = 0 :  pr\VY = 0 : pr\VZ = 0
       ;0 Remaining length
       pr\VLength = 0
       ;0 gravity force
       pr\Gravity = 0

       ;state = idle
       pr\State = CIdle
       EntityColor(pr\Shape,125,125,255)

      EndIf
      ;if far
       ;

     EndIf

    EndIf

   Else If( collEnt = 0 )

    ;

   EndIf

  EndIf

 Next

End Function

Reply To Topic (minimum 10 characters)

Please log in to reply