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);----------------------------------- ;cameraGlobal Camera = CreateCamera()CameraRange(Camera,1,1000)CameraClsColor(Camera,000,000,000);inputGlobal MXDiff%Global MYDiff%;origineOrigine = CreateCube()ScaleMesh(Origine,0.03/2,0.03/2,0/03.2)EntityColor(Origine,255,000,255)EntityFX(Origine,1);groundGlobal GroundShape AddGround();rocksType Rock Field ShapeEnd TypeAddRocks();treesType Tree Field ShapeEnd TypeAddTrees();botsType Bot Field Shape Field Life# Field VX# Field VY# Field VZ# Field PrevMS%End TypeAddBots();playerGlobal PlayerShapeGlobal PlayerYaw#Global PlayerLife#Global PlayerVX#Global PlayerVY#Global PlayerVZ#Global PlayerPrevMS%AddPlayer();bulletsType Bullet Field Shape Field Life# Field VX# Field VY# Field VZ#End Type;particlesType Particle Field Shape Field Life#End Type;lightDLight = CreateLight(1)LightColor(DLight,255,255,255)PositionEntity(DLight,50,1000,-1000)RotateEntity(DLight,45,0,0)AmbientLight(064,064,064);setup pickables entitiesEntityPickMode(GroundShape,2)For r.Rock = Each Rock EntityPickMode(r\Shape,2)NextFor t.Tree = Each tree EntityPickMode(t\Shape,2)NextFor b.Bot = Each Bot EntityPickMode(b\Shape,2)NextEntityPickMode(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 sceneGlobal ParticlesCount% = 0 ;to track how many particles are active in the sceneGlobal MainLoopTimer = CreateTimer(30) ;to lock the FPS at 30FPS max;mainloopMain()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 FunctionFunction 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 DMeshEnd FunctionFunction 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 DMeshEnd FunctionFunction Distance2D#(PAX#,PAZ#,PBX#,PBZ#) Distance2D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) ) Return Distance2DEnd FunctionFunction Distance3D#(PAX#,PAY#,PAZ#,PBX#,PBY#,PBZ#) Distance3D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBY - PAY ) * ( PBY - PAY ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) ) Return Distance3DEnd 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 FunctionFunction 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 FunctionFunction 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)) NextEnd FunctionFunction 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)) NextEnd FunctionFunction 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)) NextEnd FunctionFunction AddPlayer() PlayerShape = CopyEntity(XPlayer) PositionEntity(PlayerShape,50,0,50) PlayerLife = 1.0 PlayerPrevMS = MilliSecs() NameEntity(PlayerShape,"PLA"+Str(1))End FunctionFunction 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 EndIfEnd FunctionFunction UpdateBots() For bo.Bot = Each Bot ;depending on ai (wander, pursue and attack, flee and hide), decide how bot will move / act NextEnd FunctionFunction 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 NextEnd FunctionFunction 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 NextEnd Function
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);----------------------------------- ;cameraGlobal Camera = CreateCamera()CameraRange(Camera,1,1000)CameraClsColor(Camera,000,000,000);inputGlobal MXDiff%Global MYDiff%;origineOrigine = CreateCube()ScaleMesh(Origine,0.03/2,0.03/2,0/03.2)EntityColor(Origine,255,000,255)EntityFX(Origine,1);groundGlobal GroundShape AddGround();rocksType Rock Field ShapeEnd TypeAddRocks();treesType Tree Field ShapeEnd TypeAddTrees();botsType Bot Field Ellipsoid Field Shape Field Life# Field PrevMS%End TypeAddBots();playerGlobal PlayerEllipsoidGlobal PlayerShapeGlobal PlayerYaw#Global PlayerLife#Global PlayerPrevMS%AddPlayer();bulletsType Bullet Field Ellipsoid Field Shape Field Life#End Type;particlesType Particle Field Shape Field Life#End Type;lightDLight = CreateLight(1)LightColor(DLight,255,255,255)PositionEntity(DLight,50,1000,-1000)RotateEntity(DLight,45,0,0)AmbientLight(064,064,064);setup collision groups (do not confuse "EntityType()" which define a group of entities and "Type End Type" which define a customtype variable !!! )Const GShape% = 1Const GTurningMoving% = 2EntityType(GroundShape,GShape)For r.Rock = Each Rock EntityType(r\Shape,GShape)NextFor t.Tree = Each Tree EntityType(t\Shape,GShape)NextFor bo.Bot = Each Bot EntityType(bo\Shape,GShape) : EntityType(bo\Ellipsoid,GTurningMoving)NextEntityType(PlayerShape,GShape) : EntityType(PlayerEllipsoid,GTurningMoving);setup collidables entities and collisions detection / responseCollisions(GTurningMoving,GShape,2,1)EntityPickMode(GroundShape,2) For r.Rock = Each Rock EntityPickMode(r\Shape,2)NextFor t.Tree = Each tree EntityPickMode(t\Shape,2)NextFor b.Bot = Each Bot EntityPickMode(b\Shape,2) : NextEntityPickMode(PlayerShape,2) : Global CollPoint = CreateCube()ScaleMesh(CollPoint,0.03/2,0.03/2,0.03/2)EntityColor(CollPoint,255,000,255)EntityFX(CollPoint,1)Global CollNormal = CreateCube()ScaleMesh(CollNormal,0.01/2,0.01/2,0.3/2)PositionMesh(CollNormal,0,0,0.3/2)EntityColor(CollNormal,125,000,125)EntityFX(CollNormal,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 sceneGlobal ParticlesCount% = 0 ;to track how many particles are active in the sceneGlobal MainLoopTimer = CreateTimer(30) ;to lock the FPS at 30FPS max;mainloopMain()End()Function Main() Repeat MXDiff = MouseXSpeed() MYDiff = MouseYSpeed() ;update player before collisions (depending on input mouse/keyboard) UpdatePlayerBC() ;update bots before collisions (depending on ai) UpdateBotsBC() ;update bullets before collisions UpdateBulletsBC() ;detect collisions + response (reposition) UpdateWorld() ;update player after collisions UpdatePlayerAC() ;update bots after collisions UpdateBotsAC() ;update bullets after collisions UpdateBulletsAC() ;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 FunctionFunction 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 DMeshEnd FunctionFunction 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 DMeshEnd FunctionFunction Distance2D#(PAX#,PAZ#,PBX#,PBZ#) Distance2D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) ) Return Distance2DEnd FunctionFunction Distance3D#(PAX#,PAY#,PAZ#,PBX#,PBY#,PBZ#) Distance3D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBY - PAY ) * ( PBY - PAY ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) ) Return Distance3DEnd 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 FunctionFunction 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 FunctionFunction 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)) NextEnd FunctionFunction 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)) NextEnd FunctionFunction 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) b\Ellipsoid = CreatePivot() EntityRadius(b\Ellipsoid,0.24) PositionEntity(b\Ellipsoid,X,0.24+0.1,Z) b\Life = 1.0 b\PrevMS = MilliSecs() NameEntity(b\Shape,"BOT"+Handle(b)) NextEnd FunctionFunction AddPlayer() PlayerShape = CopyEntity(XPlayer) PlayerEllipsoid = CreatePivot() EntityRadius(PlayerEllipsoid,0.24) PositionEntity(PlayerEllipsoid,50,0.24+0.1,50) PlayerLife = 1.0 PlayerPrevMS = MilliSecs() NameEntity(PlayerShape,"PLA"+Str(1))End FunctionFunction UpdatePlayerBC() ;turn left/right MoveMouse(GraphicsWidth()/2,GraphicsHeight()/2) PlayerYaw = PlayerYaw - Float(MXDiff)/10 RotateEntity(PlayerEllipsoid,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 ) MoveEntity(PlayerEllipsoid,0,0,0) Else If( KeyDown(17)=1 ) MoveEntity(PlayerEllipsoid,0,0,+0.347) Else If( KeyDown(31)=1 ) MoveEntity(PlayerEllipsoid,0,0,-0.347) Else If( KeyDown(30)=1 ) MoveEntity(PlayerEllipsoid,-0.347,0,0) Else If( KeyDown(32)=1 ) MoveEntity(PlayerEllipsoid,+0.347,0,0) 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) bu\Ellipsoid = CreatePivot() PositionEntity(bu\Ellipsoid,EntityX(PlayerShape,True),EntityY(PlayerShape,True)+0.875,EntityZ(PlayerShape,True)) RotateEntity(bu\Ellipsoid,EntityPitch(PlayerShape,True),EntityYaw(PlayerShape,True),EntityRoll(PlayerShape,True)) MoveEntity(bu\Ellipsoid,0,0,+0.25+0.1+0.01) TurnEntity(bu\Ellipsoid,Rand(-1,+1),Rand(-1,+1),0) bu\Life# = 1.0 EntityRadius(bu\Ellipsoid,0.1) EntityType(bu\Shape,GShape) : EntityType(bu\Ellipsoid,GTurningMoving) PlayerPrevMS = NowMS EndIf EndIf End FunctionFunction UpdateBotsBC() For bo.Bot = Each Bot ;depending on ai (wander, pursue and attack, flee and hide), decide how bot will move / act NextEnd FunctionFunction UpdateBulletsBC() 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 ) ;move the bullet MoveEntity(bu\Ellipsoid,0,0,+1.2) ;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 NextEnd FunctionFunction UpdatePlayerAC() ;position rotate PlayerShape depending on PlayerEllipsoid position orientation (-0.25 on the Y axis because of the ellipsoid radius) PositionEntity(PlayerShape,EntityX(PlayerEllipsoid,True),EntityY(PlayerEllipsoid,True)-0.25,EntityZ(PlayerEllipsoid,True)) RotateEntity(PlayerShape,EntityPitch(PlayerEllipsoid,True),EntityYaw(PlayerEllipsoid,True),EntityRoll(PlayerEllipsoid,True)) ;retrieve infos about the collisions which happened between Player ellipsoid and others collidables ;count the number of collisions which happened to Player ellipsoid CC% = CountCollisions(PlayerEllipsoid) ;if there was at least one collision (i only consider the first) If( CC > 0 ) EntRef% = CollisionEntity(PlayerEllipsoid,1) : EntName$ = EntityName(EntRef) : EntKind$ = Left(EntName,3) : EntH% = Right(EntName,Len(EntName)-3) CollX# = CollisionX(PlayerEllipsoid,1) : CollY# = CollisionY(PlayerEllipsoid,1) : CollZ# = CollisionZ(PlayerEllipsoid,1) CollNX# = CollisionNX(PlayerEllipsoid,1) : CollNY# = CollisionNY(PlayerEllipsoid,1) : CollNZ# = CollisionNZ(PlayerEllipsoid,1) ;debug collision point and collision normal PositionEntity(CollPoint,CollX,CollY,CollZ) PositionEntity(CollNormal,CollX,CollY,CollZ) : AlignToVector(CollNormal,CollNX,CollNY,CollNZ,3,1.0) ;update Player consequently EndIfEnd FunctionFunction UpdateBotsAC() For bo.Bot = Each Bot ;position rotate bot Shape depending on bot ellipsoid position orientation (-0.25 on the Y axis because of the ellipsoid radius) PositionEntity(bo\Shape,EntityX(bo\Ellipsoid,True),EntityY(bo\Ellipsoid,True)-0.25,EntityZ(bo\Ellipsoid,True)) RotateEntity(bo\Shape,EntityPitch(bo\Ellipsoid,True),EntityYaw(bo\Ellipsoid,True),EntityRoll(bo\Ellipsoid,True)) ;retrieve infos about the collisions which happened between bot ellipsoid and others collidables ;count the number of collisions which happened to bot ellipsoid ;CC% = CountCollisions(bo\Ellipsoid) ;if there was at least one collision (i only consider the first) ;If( CC > 0 ) ;EntRef% = CollisionEntity(bo\Ellipsoid,1) : EntName$ = EntityName(EntRef) : EntKind$ = Left(EntName,3) : EntH% = Right(EntName,Len(EntName)-3) ;CollX# = CollisionX(bo\Ellipsoid,1) : CollY# = CollisionY(bo\Ellipsoid,1) : CollZ# = CollisionZ(bo\Ellipsoid,1) ;CollNX# = CollisionNX(bo\Ellipsoid,1) : CollNY# = CollisionNY(bo\Ellipsoid,1) : CollNZ# = CollisionNZ(bo\Ellipsoid,1) ;update Bot consequently ;EndIf NextEnd FunctionFunction UpdateBulletsAC() For bu.Bullet = Each Bullet ;position rotate bullet Shape depending on bullet ellipsoid position orientation PositionEntity(bu\Shape,EntityX(bu\Ellipsoid,True),EntityY(bu\Ellipsoid,True)-0.25,EntityZ(bu\Ellipsoid,True)) RotateEntity(bu\Shape,EntityPitch(bu\Ellipsoid,True),EntityYaw(bu\Ellipsoid,True),EntityRoll(bu\Ellipsoid,True)) ;retrieve infos about the collisions which happened between Bullet ellipsoid and others collidables ;count the number of collisions which happened to Bullet ellipsoid CC% = CountCollisions(bu\Ellipsoid) ;if there was at least one collision (i only consider the first) If( CC > 0 ) EntRef% = CollisionEntity(bu\Ellipsoid,1) : EntName$ = EntityName(EntRef) : EntKind$ = Left(EntName,3) : EntH% = Right(EntName,Len(EntName)-3) CollX# = CollisionX(bu\Ellipsoid,1) : CollY# = CollisionY(bu\Ellipsoid,1) : CollZ# = CollisionZ(bu\Ellipsoid,1) CollNX# = CollisionNX(bu\Ellipsoid,1) : CollNY# = CollisionNY(bu\Ellipsoid,1) : CollNZ# = CollisionNZ(bu\Ellipsoid,1) ;update bot consequently ;destroy the bullet FreeEntity(bu\Shape) : FreeEntity(bu\Ellipsoid) : 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,CollX,CollY,CollZ,True) AlignToVector(pa\Shape,CollNX,CollNY,CollNZ,3,1.0) : TurnEntity(pa\Shape,Rand(-45,+45),Rand(-45,+45),0) pa\Life# = 1.0 Next EndIf NextEnd FunctionFunction 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 NextEnd Function