simple collision system using linepicks and pickables


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

 

Tweet blitz3d collision-detection physics code-archives miscellaneous
RemiD

simple collision system using linepicks and pickables

;simple collision system using linepicks and pickables
Graphics3D(1000,625,32,2)

HidePointer()

SeedRnd(MilliSecs())

;----------premade shapes---------- 
Global XRock = CreateRock(8,0.4)
ScaleMesh(XRock,2.0/2,1.5/2,2.0/2)
PositionMesh(XRock,0,1.5/2-0.5,0)
EntityColor(XRock,125,125,125)

Global XTree = CreateTree()
HideEntity(XTree)

Global XPlayer = CreateCylinder(16)
ScaleMesh(XPlayer,0.5/2,1.75/2,0.5/2)
PositionMesh(XPlayer,0,0.875,0)
EntityColor(XPlayer,000,000,255)
HideEntity(XPlayer)

Global XBot = CreateCylinder(16)
ScaleMesh(XBot,0.5/2,1.75/2,0.5/2)
PositionMesh(XBot,0,0.875,0)
EntityColor(XBot,125,125,255)
HideEntity(XBot)

Global XBullet = CreateSphere(8)
ScaleMesh(XBullet,0.2/2,0.2/2,0.2/2)
EntityColor(XBullet,125,125,125)
HideEntity(XBullet)

Global XParticle = CreateCube()
ScaleMesh(XParticle,0.04/2,0.04/2,0.04/2)
EntityColor(XParticle,125,125,125)
HideEntity(XParticle)

;-----------------------------------

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

;input
Global MXDiff%
Global MYDiff%

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

;ground
Global GroundShape 
AddGround()

;rocks
Type Rock
 Field Shape
End Type
AddRocks()

;trees
Type Tree
 Field Shape
End Type
AddTrees()

;bots
Type Bot
 Field Shape
 Field Life#
 Field VX#
 Field VY#
 Field VZ#
 Field PrevMS%
End Type
AddBots()

;player
Global PlayerShape
Global PlayerYaw#
Global PlayerLife#
Global PlayerVX#
Global PlayerVY#
Global PlayerVZ#
Global PlayerPrevMS%
AddPlayer()

;bullets
Type Bullet
 Field Shape
 Field Life#
 Field VX#
 Field VY#
 Field VZ#
End Type

;particles
Type Particle
 Field Shape
 Field Life#
End Type

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

AmbientLight(064,064,064)

;setup pickables entities
EntityPickMode(GroundShape,2)
For r.Rock = Each Rock
 EntityPickMode(r\Shape,2)
Next
For t.Tree = Each tree
 EntityPickMode(t\Shape,2)
Next
For b.Bot = Each Bot
 EntityPickMode(b\Shape,2)
Next
EntityPickMode(PlayerShape,2)

Global PickPoint = CreateCube()
ScaleMesh(PickPoint,0.03/2,0.03/2,0.03/2)
EntityColor(PickPoint,255,000,255)
EntityFX(PickPoint,1)

Global PickNormal = CreateCube()
ScaleMesh(PickNormal,0.01/2,0.01/2,0.3/2)
PositionMesh(PickNormal,0,0,0.3/2)
EntityColor(PickNormal,125,000,125)
EntityFX(PickNormal,1)

PositionEntity(Camera,EntityX(PlayerShape,True),EntityY(PlayerShape,True),EntityZ(PlayerShape,True))
MoveEntity(Camera,0,1.65+1.5,-3.0)
TurnEntity(Camera,22.5,0,0)
EntityParent(Camera,PlayerShape)

Global BulletsCount% = 0 ;to track how many bullets are active in the scene
Global ParticlesCount% = 0 ;to track how many particles are active in the scene

Global MainLoopTimer = CreateTimer(30) ;to lock the FPS at 30FPS max

;mainloop
Main()

End()

Function Main()

 Repeat

  MXDiff = MouseXSpeed()
  MYDiff = MouseYSpeed()

  ;update player depending on input (mouse and keyboard)
  UpdatePlayer()

  ;update bots depending on ai
  UpdateBots()

  ;update bullets
  UpdateBullets()

  ;update particles
  UpdateParticles()

  WireFrame(False)
  If( KeyDown(2)=True )
   WireFrame(True)
  EndIf

  ;render
  RenderWorld()

  Text(0,0,"BulletsCount = "+BulletsCount)
  Text(0,16,"ParticlesCount = "+ParticlesCount)

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

 Until( KeyDown(1)=1 )

End Function

Function CreateRock(Details%=8,MaxIrregularity#=0.3)

 SMesh = CreateSphere(Details)
 SSurface = GetSurface(SMesh,1)

 DMesh = CreateMesh()
 DSurface = CreateSurface(DMesh)
 DVerticesCount% = 0

 ;for each triangle of the source surface
 For STI% = 0 To CountTriangles(SSurface)-1 Step 1

  ;for vertex0 of this triangle
  SV0I% = TriangleVertex(SSurface,STI,0)
  ;get this vertex0 position
  X# = VertexX(SSurface,SV0I) : Y# = VertexY(SSurface,SV0I) : Z# = VertexZ(SSurface,SV0I)
  ;check if there is already a vertex existing at this position in the destination surface (with a tolerance of 0.01unit)
  TVI% = -1
  For DVI% = 0 To CountVertices(DSurface)-1 Step 1
   If( VertexX(DSurface,DVI) >= X-0.01 And VertexX(DSurface,DVI) <= X+0.01 And VertexY(DSurface,DVI) >= Y-0.01 And VertexY(DSurface,DVI) <= Y+0.01 And VertexZ(DSurface,DVI) >= Z-0.01 And VertexZ(DSurface,DVI) <= Z+0.01 )
    TVI = DVI
    Exit
   EndIf
  Next
  ;if yes
  If( TVI <> - 1 )
   ;use this vertex
   DV0I% = TVI
  ;if no
  Else If( TVI% = - 1 )
   ;create a new vertex in the destination surface
   DVerticesCount = DVerticesCount + 1
   DV0I% = DVerticesCount - 1
   AddVertex(DSurface,X,Y,Z)
  EndIf

  ;for vertex1 of this triangle
  SV1I% = TriangleVertex(SSurface,STI,1)
  ;get this vertex1 position
  X# = VertexX(SSurface,SV1I) : Y# = VertexY(SSurface,SV1I) : Z# = VertexZ(SSurface,SV1I)
  ;check if there is already a vertex existing at this position in the destination surface (with a tolerance of 0.01unit)
  TVI% = -1
  For DVI% = 0 To CountVertices(DSurface)-1 Step 1
   If( VertexX(DSurface,DVI) >= X-0.01 And VertexX(DSurface,DVI) <= X+0.01 And VertexY(DSurface,DVI) >= Y-0.01 And VertexY(DSurface,DVI) <= Y+0.01 And VertexZ(DSurface,DVI) >= Z-0.01 And VertexZ(DSurface,DVI) <= Z+0.01 )
    TVI = DVI
    Exit
   EndIf
  Next
  ;if yes
  If( TVI <> - 1 )
   ;use this vertex
   DV1I% = TVI
  ;if no
  Else If( TVI% = - 1 )
   ;create a new vertex in the destination surface
   DVerticesCount = DVerticesCount + 1
   DV1I% = DVerticesCount - 1
   AddVertex(DSurface,X,Y,Z)
  EndIf

  ;for vertex2 of this triangle
  SV2I% = TriangleVertex(SSurface,STI,2)
  ;get this vertex0 position
  X# = VertexX(SSurface,SV2I) : Y# = VertexY(SSurface,SV2I) : Z# = VertexZ(SSurface,SV2I)
  ;check if there is already a vertex existing at this position in the destination surface (with a tolerance of 0.01unit)
  TVI% = -1
  For DVI% = 0 To CountVertices(DSurface)-1 Step 1
   If( VertexX(DSurface,DVI) >= X-0.01 And VertexX(DSurface,DVI) <= X+0.01 And VertexY(DSurface,DVI) >= Y-0.01 And VertexY(DSurface,DVI) <= Y+0.01 And VertexZ(DSurface,DVI) >= Z-0.01 And VertexZ(DSurface,DVI) <= Z+0.01 )
    TVI = DVI
    Exit
   EndIf
  Next
  ;if yes
  If( TVI <> - 1 )
   ;use this vertex
   DV2I% = TVI
  ;if no
  Else If( TVI% = - 1 )
   ;create a new vertex in the destination surface
   DVerticesCount = DVerticesCount + 1
   DV2I% = DVerticesCount - 1
   AddVertex(DSurface,X,Y,Z)
  EndIf

  ;create a new triangle in the destination surface
  AddTriangle(DSurface,DV0I,DV1I,DV2I)

 Next

 UpdateNormals(DMesh)

 ;add some irregularities to the surface
 For DVI% = 0 To CountVertices(DSurface)-1 Step 1
  X# = VertexX(DSurface,DVI) : Y# = VertexY(DSurface,DVI) : Z# = VertexZ(DSurface,DVI)
  NX# = VertexNX(DSurface,DVI) : NY# = VertexNY(DSurface,DVI) : NZ# = VertexNZ(DSurface,DVI)
  NewX# = X + NX*Rnd(0.1,MaxIrregularity) : NewY# = Y + NY*Rnd(0.1,MaxIrregularity) : NewZ# = Z + NZ*Rnd(0.1,MaxIrregularity)
  VertexCoords(DSurface,DVI,NewX,NewY,NewZ)
 Next

 DebugLog(CountVertices(SSurface)+" "+CountTriangles(SSurface))
 DebugLog(CountVertices(DSurface)+" "+CountTriangles(DSurface))

 FreeEntity(SMesh)

 UpdateNormals(DMesh)

 Return DMesh

End Function

Function CreateTree()

 DMesh = CreateMesh()

 ;trunc
 CreateSurface(DMesh)
 TPart= CreateCylinder(8)
 ScaleMesh(TPart,0.3/2,3.0/2,0.3/2)
 PositionMesh(TPart,0,3.0/2,0)
 For SI% = 1 To CountSurfaces(TPart) Step 1
  AddSurfaceToOtherSurface(GetSurface(TPart,SI),TPart,GetSurface(DMesh,1),DMesh)
 Next
 FreeEntity(TPart)
 ColorWithBrush(GetSurface(DMesh,1),100,050,000)

 ;leaves
 CreateSurface(DMesh)
 TPart = CreateCone(8)
 ScaleMesh(TPart,3.0/2,6.0/2,3.0/2)
 PositionMesh(TPart,0,3.0+6.0/2,0)
 For SI% = 1 To CountSurfaces(TPart) Step 1
  AddSurfaceToOtherSurface(GetSurface(TPart,SI),TPart,GetSurface(DMesh,2),DMesh)
 Next
 FreeEntity(TPart)
 ColorWithBrush(GetSurface(DMesh,2),000,100,000)

 Return DMesh

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

;vertices+triangles (with normals, with colors, with alphas, with uvs)
Function AddSurfaceToOtherSurface(Surface,Mesh,OSurface,OMesh)

 SurfaceVerticesCount% = CountVertices(Surface)
 ;DebugLog("SurfaceVerticesCount = "+SurfaceVerticesCount)
 OSurfaceVerticesCount% = CountVertices(OSurface)
 ;DebugLog("OSurfaceVerticesCount = "+OSurfaceVerticesCount)
 For VI% = 0 To CountVertices(Surface)-1 Step 1
  ;DebugLog("VI = "+VI)
  VLX# = VertexX(Surface,VI)
  VLY# = VertexY(Surface,VI)
  VLZ# = VertexZ(Surface,VI)
  TFormPoint(VLX,VLY,VLZ,Mesh,0)
  VGX# = TFormedX()
  VGY# = TFormedY()
  VGZ# = TFormedZ()
  VNX# = VertexNX(Surface,VI)
  VNY# = VertexNY(Surface,VI)
  VNZ# = VertexNZ(Surface,VI)
  VR% = VertexRed(Surface,VI)
  VG% = VertexGreen(Surface,VI)
  VB% = VertexBlue(Surface,VI)
  VA# = VertexAlpha(Surface,VI)
  VU# = VertexU(Surface,VI,0)
  VV# = VertexV(Surface,VI,0)
  If( OSurfaceVerticesCount = 0 )
   NVI = VI
  Else If( OSurfaceVerticesCount > 0 )
   NVI% = OSurfaceVerticesCount+VI
  EndIf
  ;DebugLog("NVI = "+NVI)
  AddVertex(OSurface,VGX,VGY,VGZ)
  VertexNormal(OSurface,NVI,VNX,VNY,VNZ)
  VertexColor(OSurface,NVI,VR,VG,VB,VA)
  VertexTexCoords(OSurface,NVI,VU,VV)
  ;WaitKey()
 Next
 SurfaceTrianglesCount% = CountTriangles(Surface)
 ;DebugLog("SurfaceTrianglesCount = "+SurfaceTrianglesCount)
 OSurfaceTrianglesCount% = CountTriangles(OSurface)
 ;DebugLog("OSurfaceTrianglesCount = "+OSurfaceTrianglesCount)
 For TI% = 0 To CountTriangles(Surface)-1 Step 1
  V0I% = TriangleVertex(Surface,TI,0) ;vertex0
  V1I% = TriangleVertex(Surface,TI,1) ;vertex1
  V2I% = TriangleVertex(Surface,TI,2) ;vertex2
  ;DebugLog("oldtriangle"+TI+" "+V0I+","+V1I+","+V2I)
  If( OSurfaceVerticesCount = 0 )
   NV0I% = V0I
   NV1I% = V1I
   NV2I% = V2I
  Else If( OSurfaceVerticesCount > 0 )
   NV0I% = OSurfaceVerticesCount+V0I
   NV1I% = OSurfaceVerticesCount+V1I
   NV2I% = OSurfaceVerticesCount+V2I
  EndIf
  ;DebugLog("newtriangle"+TI+" "+NV0I+","+NV1I+","+NV2I)
  AddTriangle(OSurface,NV0I,NV1I,NV2I)
 Next
 ;WaitKey()

End Function

Function ColorWithBrush(Surface,R%,G%,B%,A#=1.0,Fx%=0,BlendMode%=1)

 Brush = CreateBrush()
 BrushColor(Brush,R,G,B)
 BrushAlpha(Brush,A)
 BrushFX(Brush,Fx)
 BrushBlend(Brush,BlendMode)
 PaintSurface(Surface,Brush)
 FreeBrush(Brush)

End Function

Function AddGround()

 GroundShape = CreateCube()
 ScaleMesh(GroundShape,100.0/2,1.0/2,100.0/2)
 PositionMesh(GroundShape,100.0/2,-1.0/2,100.0/2)
 EntityColor(GroundShape,050,150,050)
 NameEntity(GroundShape,"GRO"+Str(1))

End Function

Function AddRocks()

 For n% = 1 To 15 Step 1
  ;choose a position
  .LineChooseRockPosition
  X# = Rnd(0+1.0,100-1.0) : Z# = Rnd(0+1.0,100-1.0)
  ;check if this position is far enough from others existing rocks
  For rr.Rock = Each Rock
   D# = Distance2D(X,Z,EntityX(rr\Shape,True),EntityZ(rr\Shape,True))
   If( D < 1.0+1.0+1.0 )
    Goto LineChooseRockPosition ;i have not added a check to exit the loop in case there are no more empty space, so don't add too many rocks !!!
   EndIf
  Next
  r.Rock = New Rock
  r\Shape = CopyEntity(XRock)
  Size# = Rnd(0.5,2.0)
  ScaleEntity(r\Shape,Size,Size,Size)
  PositionEntity(r\Shape,X,0,Z)
  NameEntity(r\Shape,"ROC"+Handle(r))
 Next

End Function

Function AddTrees()

 For n% = 1 To 60 Step 1
  ;choose a position
  .LineChooseTreePosition
  X# = Rnd(0+1.5,100-1.5) : Z# = Rnd(0+1.5,100-1.5)
  ;check if this position is far enough from others existing rocks
  For rr.Rock = Each Rock
   D# = Distance2D(X,Z,EntityX(rr\Shape,True),EntityZ(rr\Shape,True))
   If( D < 2.0+1.5+1.0 )
    Goto LineChooseTreePosition ;i have not added a check to exit the loop in case there are no more empty space, so don't add too many trees !!!
   EndIf
  Next
  ;check if this position is far enough from others existing trees
  For tt.Tree = Each Tree
   D# = Distance2D(X,Z,EntityX(tt\Shape,True),EntityZ(tt\Shape,True))
   If( D < 1.5+1.5+1.0 )
    Goto LineChooseTreePosition ;i have not added a check to exit the loop in case there are no more empty space, so don't add too many trees !!!
   EndIf
  Next
  t.Tree = New Tree
  t\Shape = CopyEntity(XTree)
  Size# = Rnd(1.0,3.0)
  ScaleEntity(t\Shape,Size,Size,Size)
  PositionEntity(t\Shape,X,0,Z)
  NameEntity(t\Shape,"TRE"+Handle(t))
 Next

End Function

Function AddBots()

 For n% = 1 To 10 Step 1
  ;choose a position
  .LineChooseBotPosition
  X# = Rnd(0+0.25,100-0.25) : Z# = Rnd(0+0.25,100-0.25)
  ;check if this position is far enough from others existing rocks
  For rr.Rock = Each Rock
   D# = Distance2D(X,Z,EntityX(rr\Shape,True),EntityZ(rr\Shape,True))
   If( D < 2.0+0.25+1.0 )
    Goto LineChooseBotPosition ;i have not added a check to exit the loop in case there are no more empty space, so don't add too many bots !!!
   EndIf
  Next
  ;check if this position is far enough from others existing trees
  For tt.Tree = Each Tree
   D# = Distance2D(X,Z,EntityX(tt\Shape,True),EntityZ(tt\Shape,True))
   If( D < 1.5+0.25+1.0 )
    Goto LineChooseBotPosition ;i have not added a check to exit the loop in case there are no more empty space, so don't add too many bots !!!
   EndIf
  Next
  ;check if this position is far enough from others existing bots
  For bb.Bot = Each Bot
   D# = Distance2D(X,Z,EntityX(bb\Shape,True),EntityZ(bb\Shape,True))
   If( D < 0.25+0.25+1.0 )
    Goto LineChooseBotPosition ;i have not added a check to exit the loop in case there are no more empty space, so don't add too many bots !!!
   EndIf
  Next
  b.Bot = New Bot
  b\Shape = CopyEntity(XBot)
  PositionEntity(b\Shape,X,0,Z)
  b\Life = 1.0
  b\PrevMS = MilliSecs()
  NameEntity(b\Shape,"BOT"+Handle(b))
 Next

End Function

Function AddPlayer()

 PlayerShape = CopyEntity(XPlayer)
 PositionEntity(PlayerShape,50,0,50)
 PlayerLife = 1.0
 PlayerPrevMS = MilliSecs()
 NameEntity(PlayerShape,"PLA"+Str(1))

End Function

Function UpdatePlayer()

 ;turn left/right
 MoveMouse(GraphicsWidth()/2,GraphicsHeight()/2)
 PlayerYaw = PlayerYaw - Float(MXDiff)/10
 RotateEntity(PlayerShape,0,PlayerYaw,0,False)
 ;move forward/backward/left/right
 If( KeyDown(17)=0 And KeyDown(31)=0 And KeyDown(30)=0 And KeyDown(32)=0 ) 
  TFormVector(0,0,0,PlayerShape,0)
 Else If( KeyDown(17)=1 ) 
  TFormVector(0,0,+0.347,PlayerShape,0) ;player speed is 0.347
 Else If( KeyDown(31)=1 ) 
  TFormVector(0,0,-0.347,PlayerShape,0) ;player speed is 0.347
 Else If( KeyDown(30)=1 )  
  TFormVector(-0.347,0,0,PlayerShape,0) ;player speed is 0.347
 Else If( KeyDown(32)=1 ) 
  TFormVector(+0.347,0,0,PlayerShape,0) ;player speed is 0.347
 EndIf 
 ;calculates the movement vector
 PlayerVX = TFormedX() : PlayerVY = TFormedY() : PlayerVZ = TFormedZ()
 ;before moving player, check if it will collides with an obstacle entity (tree or bot)
 TFormPoint(0,0.25,0,PlayerShape,0) ;root of Player shape +0.25 (on the Y axis)
 LinePick(TFormedX(),TFormedY(),TFormedZ(),PlayerVX,PlayerVY,PlayerVZ,0.25-0.01) ;player ellipsoid radius is 0.25 ;throws a linepick from the position of player root +0.25 to direction of the movement vector
 EntRef% = PickedEntity()
 ;if yes
 If( EntRef <> 0 )
  ;debug collision point / normal
  PositionEntity(PickPoint,PickedX(),PickedY(),PickedZ())
  PositionEntity(PickNormal,PickedX(),PickedY(),PickedZ()) : AlignToVector(PickNormal,PickedNX(),PickedNY(),PickedNZ(),3,1.0)
  ;recalculate the appropriate position
  PlayerX# = EntityX(PlayerShape,True) : PlayerY# = EntityY(PlayerShape,True) : PlayerZ# = EntityZ(PlayerShape,True)
  PickX# = PickedX() : PickY# = PickedZ() : PickZ# = PickedZ()
  D# = Distance2D(PlayerX,PlayerZ,PickX,PickZ)
  TCoeff# = (D-0.25)/(0.347)
  PlayerVX = PlayerVX*TCoeff : PlayerVZ = PlayerVZ*TCoeff
  ;move player
  TranslateEntity(PlayerShape,PlayerVX,PlayerVY,PlayerVZ)
 ;if no
 Else If( EntRef = 0 )
  ;move player
  TranslateEntity(PlayerShape,PlayerVX,PlayerVY,PlayerVZ)
 EndIf

 ;shoot a bullet
 If( MouseHit(1)=1 )
  NowMS% = MilliSecs()
  ;allow to shoot a new bullet only if the previous bullet was shot more than 100ms ago (1000milliseconds = 1second)
  If( NowMS - PlayerPrevMS > 100 )
   ;create a new bullet
   BulletsCount = BulletsCount + 1
   bu.bullet = New bullet
   bu\Shape = CopyEntity(XBullet)
   PositionEntity(bu\Shape,EntityX(PlayerShape,True),EntityY(PlayerShape,True)+0.875,EntityZ(PlayerShape,True))
   RotateEntity(bu\Shape,EntityPitch(PlayerShape,True),EntityYaw(PlayerShape,True),EntityRoll(PlayerShape,True))
   TurnEntity(bu\Shape,Rand(-1,+1),Rand(-1,+1),0)
   bu\Life# = 1.0
   PlayerPrevMS = NowMS
  EndIf
 EndIf

End Function

Function UpdateBots()

 For bo.Bot = Each Bot
  ;depending on ai (wander, pursue and attack, flee and hide), decide how bot will move / act
 Next

End Function

Function UpdateBullets()

 For bu.Bullet = Each Bullet
  ;decrease bullet life so that it does not last forever
  bu\Life = bu\Life - 0.01
  ;if life is more than 0, update the bullet
  If( bu\Life > 0 )
   ;calculates the movement vector
   TFormVector(0,0,+1.2,bu\Shape,0) ;bullet speed is 1.2
   ;calculates the movement vector
   bu\VX = TFormedX() : bu\VY = TFormedY() : bu\VZ = TFormedZ()
   ;before moving the bullet, check if it will collides with an obstacle entity (tree or player or bot)
   TFormPoint(0,0,0,bu\Shape,0) ;root of bullet shape 
   LinePick(TFormedX(),TFormedY(),TFormedZ(),bu\VX,bu\VY,bu\VZ,0.1) ;bullet ellipsoid radius is 0.1 ;throws a linepick from the position of bullet +0 to direction of the movement vector  
   EntRef% = PickedEntity()
   ;if yes
   If( EntRef <> 0 )
    ;recalculate the appropriate position
    BulletX# = EntityX(bu\Shape,True) : BulletY# = EntityY(bu\Shape,True) : BulletZ# = EntityZ(bu\Shape,True)
    PickX# = PickedX() : PickY# = PickedY() : PickZ# = PickedZ()
    PickNX# = PickedNX() : PickNY# = PickedNY() : PickNZ# = PickedNZ()
    D# = Distance2D(BulletX,BulletZ,PickX,PickZ)
    TCoeff# = (D-0.1)/(1.2)
    bu\VX = bu\VX*TCoeff : bu\VZ = bu\VZ*TCoeff
    ;move bullet
    TranslateEntity(bu\Shape,bu\VX,bu\VY,bu\VZ)
    ;destroy the bullet
    FreeEntity(bu\Shape) : Delete(bu)
    BulletsCount = BulletsCount - 1
    ;get kind of the picked entity
    EntName$ = EntityName(EntRef) : EntKind$ = Left(EntName,3) : EntH% = Right(EntName,Len(EntName)-3)
    If( EntKind = "GRO" )
     MaterialR% = 050 : MaterialG% = 150 : MaterialB% = 050
    Else If( EntKind = "ROC" )
     MaterialR% = 125 : MaterialG% = 125 : MaterialB% = 125
    Else If( EntKind = "TRE" )
     MaterialR% = 100 : MaterialG% = 050 : MaterialB% = 000
    Else If( EntKind = "BOT" )
     MaterialR% = 125 : MaterialG% = 125 : MaterialB% = 255
    Else If( EntKind = "PLA" )
     MaterialR% = 000 : MaterialG% = 000 : MaterialB% = 255
    EndIf
    ;create some particles
    For n% = 1 To 16 Step 1
     pa.Particle = New Particle : ParticlesCount = ParticlesCount + 1
     pa\Shape = CopyEntity(XParticle)
     EntityColor(pa\Shape,MaterialR,MaterialG,MaterialB)
     PositionEntity(pa\Shape,PickX,PickY,PickZ,True)
     AlignToVector(pa\Shape,PickNX,PickNY,PickNZ,3,1.0) : TurnEntity(pa\Shape,Rand(-45,+45),Rand(-45,+45),0)
     pa\Life# = 1.0
    Next
   ;if no
   Else If( EntRef = 0 )
    ;move the bullet
    TranslateEntity(bu\Shape,bu\VX,bu\VY,bu\VZ)
   EndIf
  ;if life is equal or less than 0, destroy the bullet
  Else If( bu\Life <= 0 )
   FreeEntity(bu\Shape) : Delete(bu)
   BulletsCount = BulletsCount - 1
  EndIf
 Next

End Function

Function UpdateParticles()

 For pa.Particle = Each Particle
  MoveEntity(pa\Shape,0,0,0.03)
  pa\Life = pa\Life - 0.03
  EntityAlpha(pa\Shape,pa\Life)
  If( pa\Life <= 0 ) 
   FreeEntity(pa\Shape) : Delete(pa)
   ParticlesCount = ParticlesCount - 1
  EndIf
 Next

End Function

Reply To Topic (minimum 10 characters)

Please log in to reply