January 15, 2021, 02:41:53 PM

Author Topic: How to delete a 3d bullet when it gets a certain range?  (Read 2998 times)

Offline RemiD

  • Hero Member
  • *****
  • Posts: 1126
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #15 on: October 14, 2018, 02:18:27 PM »
well, not sure if it will be understandable enough for you, but here is a way to use linepicks and pickable to detect collisions and reposition turning moving entities...

Code: [Select]
see post #27

From my experience it is more reliable and versatile (and fast enough) to use a collision system with linepicks and pickables, only when necessary, rather than using the Blitz3d collision system (which is restricting and sometimes buggy...)

Anyway, good luck to decipher my code, if you are a noob, :P (i have added some comments)
DualCore AMD E-450, 1646 MHz - 6 Go DDR3 1333 SDRAM - AMD Radeon HD 6320 Graphics (384 Mo) - Windows 7 Home Premium - DirectX 11.0

Offline phodiS

  • Jr. Member
  • **
  • Posts: 52
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #16 on: October 15, 2018, 05:31:49 PM »
HOLY CRAP RemiD!!!!...
          This is AWESOME!!!... I have been having troubles with collisions mainly now, but I am getting better at this. This example...with all the comments is invaluable for my skill level tho, and I am going to spend a LOT of time learning and tinkering with this.. you have mad my day man!!!...
THANK YOU so much!    :D  :D  :D

Offline RemiD

  • Hero Member
  • *****
  • Posts: 1126
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #17 on: October 15, 2018, 06:27:52 PM »
@phodiS>>i hope that it can help you to understand a few things... if i was a beginner again, i would focus on learning how to use linepick and pickables instead of wasting time with the limited, buggy, collision system of Blitz3d.

the code in post #15 is "raw", it is better to use functions to seperate the update of each kind of entity... (easier to navigate in the code)

anyway i plan to add jumping falling landing, and a simple AI, and consequently complexify slightly the collision detection and response, but once you get how it works, it should be clear.

DualCore AMD E-450, 1646 MHz - 6 Go DDR3 1333 SDRAM - AMD Radeon HD 6320 Graphics (384 Mo) - Windows 7 Home Premium - DirectX 11.0

Offline phodiS

  • Jr. Member
  • **
  • Posts: 52
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #18 on: October 16, 2018, 05:43:20 PM »
...Ok, I have had a look at the code... and as much as I appreciate it... i KNOW I am going to take forever to understand it.
   I have kind of managed to accomplish a real dodgy working version of what you posted using my own code... but I know it's all tacked together and has been a good learning experience with the code I am familiar with...currently I am trying to expand on this and your example although way over my head at this stage...has already been printed out and stuck next to my PC here for reference.
Anyways that aside..I LOVE the particle effects on collision...that is terrific!!! and will be messing around with this aspect before I get in too far over my head..one step at at time so to speak.
   I am pretty sure that I will have to use your method of collision as the current way I do it... (I am using Heightmaps) the characters sometimes fall into the ground which is really annoying.
   If you are going to do more on this project... I was hoping IF POSSIBLE...could you please implement a heightmap terrain, or pop in a few notes on how to set it up. I have made a cool little character (been wasting time I guess)... but because I don't really know how to animate yet.. I cheated and made him LOOK like his legs are walking...and...well it's not to bad... This little guy needs no assets (ignore the crap tank and drums).. but would it be possible to use him as the characters in game as well.

Thanks again for you time... this is AWESOME!   
Here's my little animated walking character guy.


Code: BlitzBasic
  1. AppTitle "Player model"
  2. Graphics3D 800,600,32,0
  3. SetBuffer BackBuffer()
  4. ground=CreatePlane () ScaleEntity ground,200,1,200 EntityColor ground,120,180,120
  5. cam = CreateCamera()
  6. PositionEntity cam,-5,15,-25
  7.  
  8. Type fuel
  9. Field fuel
  10. End Type
  11.  
  12.  
  13. ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  14. ;player
  15. player=CreateSphere () PositionEntity player,-.4,1.8,0
  16. ScaleEntity player,1.1,1.5,1.1 EntityColor player,60,170,60
  17. gun=CreateCube() ScaleEntity gun,.2,.2,1 EntityColor gun,20,20,20 PositionEntity gun,.2,2.1,.8
  18. face=CreateSphere() PositionEntity face,-.4,3.5,0 ScaleEntity face,.8,1,.8 EntityColor face,240,210,210
  19. helm=CreateSphere() PositionEntity helm,-.4,3.9,-.2 ScaleEntity helm,.9,.9,1   EntityColor helm,60,170,60
  20. bill=CreateSphere() PositionEntity bill,-.4,4,.7  ScaleEntity bill,.9,.2,.9 EntityColor bill,60,170,60
  21. eyes=CreateSphere() PositionEntity eyes,-.4,3.5,.3  ScaleEntity eyes,.6,.2,.6 EntityColor eyes,20,20,20
  22. backpack=CreateCube() ScaleEntity backpack,.6,.7,.7 PositionEntity backpack,-.4,2.1,-.5 EntityColor backpack,90,90,90
  23. antenna=CreateCube() ScaleEntity antenna,.1,1,.1 PositionEntity antenna,0,3,-1 EntityColor antenna,90,90,90 RotateEntity antenna,-30,0,0
  24. arm=CreateSphere() PositionEntity arm,-1.1,2,0 ScaleEntity arm,.5,.9,.5 EntityColor arm,60,170,60
  25. EntityParent eyes,player EntityParent helm,player EntityParent backpack,player EntityParent face,player EntityParent gun,player
  26. EntityParent arm,player EntityParent bill,helm EntityParent antenna,backpack
  27. ;Left leg
  28. lang=45 lleg = CreateCube() ScaleEntity lleg,.4,1,.4 PositionEntity lleg,-.9,.5,0 EntityColor lleg,50,170,50
  29. ;Right leg
  30. rang=90 rleg = CreateCube() ScaleEntity rleg,.4,1,.4 PositionEntity rleg,rx,.6,0 EntityColor rleg,40,170,40
  31. EntityParent rleg,player EntityParent lleg,player  
  32. l=False EntityParent cam,player
  33. ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  34. ;Tank
  35. tank=CreateCube()  ScaleEntity tank,5,4,10 PositionEntity tank,0,1,20 EntityColor tank,100,100,100
  36. top=CreateSphere() ScaleEntity top,4,4,4 PositionEntity top,0,6,17 EntityColor top,120,120,120
  37. barrel=CreateCylinder(20) ScaleEntity barrel,.7,8,.7 PositionEntity barrel,0,7,24 EntityColor barrel,80,80,80 RotateEntity barrel,90,0,0
  38. EntityParent barrel,top EntityParent top,tank
  39. ;Fuel drum
  40. For f=1 To 8
  41. fuel=CreateCylinder(15) ScaleEntity fuel,1,2,1  PositionEntity fuel,0,0,-5 EntityColor fuel,200,20,20
  42. bb=CreateCylinder(15) ScaleEntity bb,1.1,.1,1.1 PositionEntity bb,0,.2,-5 EntityColor bb,100,20,20
  43. bm=CreateCylinder(15) ScaleEntity bm,1.1,.1,1.1 PositionEntity bm,0,1,-5 EntityColor bm,100,20,20
  44. bt=CreateCylinder(15) ScaleEntity bt,1.1,.1,1.1 PositionEntity bt,0,1.8,-5 EntityColor bt,100,20,20
  45. EntityParent bb,fuel EntityParent bm,fuel EntityParent bt,fuel
  46. PositionEntity fuel,Rnd(-40,40),0,Rnd(-40,40)
  47. Next
  48.  
  49. While Not KeyDown(1)
  50. PointEntity cam,player
  51. ;CONTROLS
  52. If KeyDown(17) MoveEntity player,0,0,+.1 l=True
  53. If KeyDown(31) MoveEntity player,0,0,-.1 l=True
  54. If KeyDown(32) TurnEntity player,0,-.8,0 l=True
  55. If KeyDown(30) TurnEntity player,0,.8,0  l=True
  56. If l=True
  57.    lang=lang+2
  58.    RotateEntity lleg,lang,0,0
  59.    If lang>360 llang=0
  60.    rang=rang+2
  61.    RotateEntity rleg,rang,0,0
  62.    If rang>360 rang=0
  63.    Else lang=-40 rang=40
  64.  
  65. EndIf l=False
  66.  
  67. TurnEntity top,0,.2,0
  68.  
  69. t=t+1 If t>10 TurnEntity tank,0,1,0 t=0
  70. MoveEntity tank,.1,0,.1
  71.  
  72.  
  73. RenderWorld
  74. Flip
  75. Wend
  76.  

Offline RemiD

  • Hero Member
  • *****
  • Posts: 1126
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #19 on: October 16, 2018, 06:57:14 PM »
@Phodis>>i can't promise that i will implement what you need for your project ( because i am working on my own projects... ),
but since i am starting to code again since 7months of pause, i may help a little here and there.

here is a new version :
->i have organised the code into sections depending on the kind of entity with its create / update / destroy functions
->i have added gravity to projectiles
->i have added a way to recognize which kind of entity has been hit (ground or rock or tree or bot or player) and a different particle color depending on the material of the entity hit
->i have added a very primitive AI that make a bot points towards player if he is near enough, and shoot projectiles at him
Code: [Select]
;see last code in latest post



btw, your character made all in code is cool.

Know that you can create joints and animations (made of poses) with Blitz3d. Then it is simpler to animate than to use rotateentity for each joint !
DualCore AMD E-450, 1646 MHz - 6 Go DDR3 1333 SDRAM - AMD Radeon HD 6320 Graphics (384 Mo) - Windows 7 Home Premium - DirectX 11.0

Offline phodiS

  • Jr. Member
  • **
  • Posts: 52
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #20 on: October 16, 2018, 09:46:15 PM »
Thanks again RemniD!!!..
Hey I am sure I have heaps to play with now.... gotta say I like the ~random~ bullet gravity range, how they don't always hit the same spot when shooting... I have been wanting to know how to make arrows in this perspective and you have answered it brilliantly. Cheers again, and thank you for going to all the trouble to do so. I don't know if you have yet written a fully functioning game...but if you haven't you really should... god I don't know how you guys get so good at this..years of practice I guess, it's so freaking cool :)

Offline RemiD

  • Hero Member
  • *****
  • Posts: 1126
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #21 on: October 17, 2018, 06:33:27 AM »
if you want to have "realistic" physics for arrows / projectiles, you will need to learn about the basics of vectors which are usually defined by a direction (also called "normal") and a length (also called "force" /  "velocity" / "speed")

DualCore AMD E-450, 1646 MHz - 6 Go DDR3 1333 SDRAM - AMD Radeon HD 6320 Graphics (384 Mo) - Windows 7 Home Premium - DirectX 11.0

Offline RemiD

  • Hero Member
  • *****
  • Posts: 1126
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #22 on: October 17, 2018, 10:19:57 PM »
updated the code a little :
->added a system to make the movements appear constant, whatever the FPS
->added some mines and explosions
Code: [Select]
;see last code in latest post
DualCore AMD E-450, 1646 MHz - 6 Go DDR3 1333 SDRAM - AMD Radeon HD 6320 Graphics (384 Mo) - Windows 7 Home Premium - DirectX 11.0

Offline RemiD

  • Hero Member
  • *****
  • Posts: 1126
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #23 on: October 20, 2018, 09:42:58 PM »
some updates :
->the bullets behave like real bullets ( they move so fast that you can't see them, but the collision detection using linepicks and pickables seems reliable ! 8) )
->player / bots have life points and can be damaged / destroyed
->life points are displayed above player / bots
->packs (items) are spread on the ground and they can increase life or protection or power or speed or ammo (only life effect is active right now)
Code: [Select]
;see code in last post

the big step will be to code a collisions detection / response system that is compatible with movement on the XZ axises but also with movement on the Y axis (with jumping falling landing)

i also plan to merge player and the bots in the same list so that it is simpler to update them all, the only thing that will differentiate them is that player will be driven by controls (keyboard + mouse) whereas bots will be driven by AI...
DualCore AMD E-450, 1646 MHz - 6 Go DDR3 1333 SDRAM - AMD Radeon HD 6320 Graphics (384 Mo) - Windows 7 Home Premium - DirectX 11.0

Offline RemiD

  • Hero Member
  • *****
  • Posts: 1126
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #24 on: October 21, 2018, 11:00:26 AM »
some updates :
->i have added trails that follow bullets so that it is easier to see where player / bots aim

i think that it is probably time for me to start my own worklog ;D

you can follow the rest of the development here : https://www.syntaxbomb.com/index.php/topic,4975.0.html
DualCore AMD E-450, 1646 MHz - 6 Go DDR3 1333 SDRAM - AMD Radeon HD 6320 Graphics (384 Mo) - Windows 7 Home Premium - DirectX 11.0

Offline phodiS

  • Jr. Member
  • **
  • Posts: 52
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #25 on: October 21, 2018, 08:32:24 PM »
HI RemniD... Your 3d Tutorial is pretty in-depth..... but currently I am trying to easy my way into learning it one step at a time.  I have learned a lot so far, but have been sidetracked a few days on trying something a little different for a 3rd person shooter...Below I am using 2d sprites for my character and enemies in a 3d heightmap world. I am over the moon with how it's coming along.... I can spawn hundreds of enemies :D  :D  and can fire my gun :D  ; I got a lot of help off the http://jnoodle.com/Blitz3D/lesson8.html example here.... but no-matter what I try my bullets won't kill their targets... a collision thing I guess..but I don't know what I have missed, as it looks pretty straight forward!!. I have commented the problem area where the bullets should be hitting
....can you see at a glance...what I have done wrong. I must be so close and it's so frustrating.
               
I am still following your main 3rd person shooter example as well. And really appreciate the time you have already put in to help out on this.


Code: BlitzBasic
  1. AppTitle "3d world 2d Sprites"
  2. Global screen_width = 1024, screen_height = 768
  3. Graphics3D 1024,768,32,0
  4. SetBuffer BackBuffer()
  5.  
  6. ;CAMERA
  7. cam = CreateCamera() CameraViewport cam, 0, 0, screen_width, screen_height
  8. PositionEntity cam,300,25,160 CameraRange cam,0.1,2000
  9. ;LIGHTING
  10. light=CreateLight() AmbientLight 255, 200, 200
  11. Global run_vol#, runchannel
  12. ;TYPES
  13. Global type_player=1
  14. Global type_ground=2
  15. Global Type_camera=4
  16. Global type_sky=5
  17. Global type_enemy=6
  18. Global type_house=7
  19. Global type_tree=8
  20. Global type_scene=9
  21. Global type_windmill=10
  22. Global type_bullet=11
  23. Global type_backcam=12
  24. ;COLLISIONS
  25. Collisions type_player,type_tree,2,2
  26. Collisions type_player,type_scene,2,2
  27. Collisions type_player,type_windmill,2,2
  28. Collisions type_player,type_house,2,2
  29. Collisions type_enemy, type_tree,2,2
  30. Collisions type_enemy, type_scene,2,2
  31. Collisions type_enemy, type_house,2,2
  32. Collisions type_tree,  type_scene,2,2
  33. Collisions type_enemy, type_bullet,2,2
  34. Collisions type_enemy, type_enemy,2,2
  35. Collisions type_house,type_scene,2,1
  36. Collisions type_bullet,type_backcam,2,2
  37. ;SCENE
  38. Global scene=LoadTerrain( "heightmap.bmp" )
  39. TerrainDetail scene,4000,True; Set terrain detail, enable vertex morphing
  40. ScaleEntity scene,10,50,10 PositionEntity scene,-100,-10,-100
  41. texture=LoadTexture("grass.bmp") EntityTexture scene,texture,0,1
  42. EntityType scene,type_scene EntityRadius scene,1
  43. ;SKY
  44. sky=CreateSphere(32) ScaleEntity sky,1500,1500,1500
  45. stex=LoadTexture("sky1.jpg") EntityTexture sky,stex
  46. EntityType sky,type_sky FlipMesh sky EntityType sky,type_sky
  47.  
  48. ;KEY SETUP
  49. Global up_key = 200, down_key=208, left_key=203, right_key=205
  50. Global W_key = 17, S_key=31, A_key=30, D_key=32
  51.  
  52. ;PLAYER
  53. player = CreateSprite()
  54. anim_tex=LoadAnimTexture( "char_back.bmp",7,32,48,0,4 )
  55. ;anim_texf=LoadAnimTexture( "char_front.bmp",7,32,48,0,4 )
  56. EntityTexture player, anim_tex, 1
  57. HandleSprite player,0,-.7 ;sprite height from ground
  58. ScaleSprite player, 2,4 PositionEntity player, 300, 10, 200
  59. EntityType player, type_player EntityParent cam, player
  60. EntityRadius player,1
  61.  
  62. ; ENEMY
  63. model = CreateSprite()
  64. etexture=LoadAnimTexture( "char2.bmp",7,32,48,0,4  )
  65. EntityTexture model, etexture, 1
  66. HandleSprite model,0,-.1 ;sprite height from ground
  67. ScaleSprite model, 2,4
  68. PositionEntity model,50,8,50
  69. EntityType model, type_enemy
  70. EntityRadius model,1
  71.  
  72. ;types
  73. Type bullet
  74. Field shot
  75. End Type
  76.  
  77. Type enemy
  78. Field entity
  79. Field edirection#,movespeed#,entitysize#,enemy2,backcam
  80. End Type
  81.  
  82. spinspeed#=3
  83. movespeed#=.2
  84. HideEntity model
  85.  
  86. ;Duplicate  enemy
  87. For qty = 1 To 400
  88. b.enemy = New enemy
  89. b\entity = CopyEntity(model)
  90. EntityType b\entity,type_enemy EntityRadius b\entity,1
  91. PositionEntity b\entity,Rnd(-20,200),10,Rnd(-20,200)
  92. EntityColor b\entity,Rnd(150),Rnd(120),Rnd (150)
  93. Next
  94. j=0
  95.  
  96. ;START LOOP XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  97. While Not KeyHit(1)
  98.  
  99. ;ENEMY chase player
  100. For b.enemy = Each enemy
  101. t=t+1
  102.   If t>100
  103.     b\edirection#=Rnd(360)
  104.     TurnEntity b\entity, 0,b\edirection#,0
  105.   t=0
  106.   EndIf
  107.  
  108.   If EntityDistance(b\entity,player)>10 Then
  109.       AnimSprite(b\entity, etexture,200,4)
  110.       MoveEntity b\entity ,0,0,movespeed#
  111.       TranslateEntity b\entity,0,-.4,0
  112.       HandleSprite b\entity,0,-.8 ;sprite height from ground
  113.   EndIf    
  114.       If EntityDistance(b\entity,player)<70 And  EntityDistance(b\entity,player)>10 Then
  115.       PointEntity b\entity, player
  116.       MoveEntity b\entity,0,0,movespeed#+.01
  117.   EndIf
  118.      
  119.       If EntityDistance(b\entity,cam)<20 Then
  120.                etexture=LoadAnimTexture( "char_back.bmp",7,32,48,0,4  )
  121.                EntityTexture model, etexture, 1
  122.       EndIf
  123.       If EntityDistance(b\entity,cam)>40 Then
  124.                etexture=LoadAnimTexture( "char2.bmp",7,32,48,0,4  )
  125.                EntityTexture model, etexture, 1
  126.  
  127.  
  128.  
  129.  
  130.  
  131.       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Tried by distance between bullet and entity(enemy)
  132.       if entitydistance(b\entity,type_bullet)<1
  133.           freeentity b\entity
  134.           delete b
  135.       endif                                                          ;;;;; I have tried this code in the bullet update section as well
  136.      ;; Also tried by the collided command                ;;;;; But I can never get it to work ever!!
  137.      ;;;;;;;;;; or this ;;;;;;;;;;;;;;;;;                       ;;;;; Can you see why the enemy won't get deleted?
  138.      if (entitycollided(b\entity,type_bullet)) then
  139.         freeentity b\entity
  140.         delete b
  141.      endif
  142.      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;      
  143.  
  144.  
  145.  
  146.  
  147. EndIf  
  148.        
  149. Next
  150.  
  151.  
  152.  
  153. ; PLAYER ANIMATE WHEN KEYPRESSED
  154.         If run_vol#>0 Then AnimSprite(player, anim_tex,200,4) ;For Animation on/off
  155.         object_key_control( player )
  156.         ChannelVolume runchannel, run_vol#
  157.  
  158. ;GRAVITY
  159. TranslateEntity player,0,-.4,0 ;gravity level?..
  160. object_key_control( player )
  161. ChannelVolume runchannel, run_vol#
  162. TranslateEntity house,0,-.4,0 ;gravity level?..
  163.  
  164.  
  165. ;SHOOT
  166. If KeyHit(57)
  167. bb.bullet=New bullet
  168. bb\shot=CreateSprite()
  169. PositionEntity bb\shot,EntityX(player),EntityY(player)+2,EntityZ(player)+1.5
  170. EntityColor bb\shot,255,0,0:ScaleSprite bb\shot,.5,.5
  171. ;bb\shot=CreateSprite(cube):EntityColor bb\shot,255,0,0 ScaleEntity bb\shot,1,1,2
  172. EntityType bb\shot,type_bullet:EntityRadius bb\shot,1
  173.  
  174. RotateEntity bb\shot,EntityPitch(player),EntityYaw(player),EntityRoll(player)
  175. EndIf
  176.  
  177. ;UPDATE_BULLET
  178. For bb.bullet=Each bullet
  179.     MoveEntity bb\shot,0,0,2
  180.   If (EntityDistance(bb\shot,player)>200)
  181.     FreeEntity bb\shot
  182.     Delete bb
  183.   EndIf  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.   If (Entitycollided(bb\shot,type_enemy));;;;;;;;;;;;;;;;;;;;;;;                   ALSO HERE!... I thought for sure this would have worked on
  190.                FreeEntity bb\shot               ;;;;;;;;;;;;;;;;;;;;;;;                   Killing the bullets... but it doesn't >:(
  191.                Delete bb
  192.   EndIf    
  193. Next
  194.  
  195.  
  196.  
  197.  
  198.  
  199. UpdateWorld
  200. RenderWorld
  201. Flip
  202. Wend
  203. End
  204. ; END LOOP XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  205.  
  206. ;FUNCTIONS
  207. Function AnimSprite(obj, atex, d, f)
  208.         frame=MilliSecs()/d Mod f
  209.         EntityTexture obj,atex,frame
  210. End Function
  211.  
  212. ;CONTROLS
  213. Function object_key_control( obj )
  214.         run_snd = False        
  215.         If KeyDown( up_key )=True Then MoveEntity obj, 0, 0, .2 : run_snd=True
  216.         If KeyDown( down_key )=True Then MoveEntity obj, 0, 0,-.2 : run_snd=True :
  217.         anim_texf=LoadAnimTexture( "char_front.bmp",7,32,48,0,4 )
  218.     If KeyDown( left_key )=True Then TurnEntity obj, 0, 2, 0
  219.         If KeyDown( right_key )=True Then TurnEntity obj, 0,-2, 0
  220.         If run_snd Then run_vol#=.5 Else run_vol#=0
  221.  
  222. End Function
  223.  

Offline RemiD

  • Hero Member
  • *****
  • Posts: 1126
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #26 on: October 21, 2018, 09:48:59 PM »
@Phodis>>i will take a look at your code tomorrow evening, time to go sleep for me...

one thing is sure : if you decide to use the collisions detection system of Blitz3d, you will need 2 different updates for turning moving entities (like characters / vehicles / bullets) : one before updateworld(), and one after updateworld()
(which is not a bad thing, it is just more bloaty and confusing imo)
DualCore AMD E-450, 1646 MHz - 6 Go DDR3 1333 SDRAM - AMD Radeon HD 6320 Graphics (384 Mo) - Windows 7 Home Premium - DirectX 11.0

Offline RemiD

  • Hero Member
  • *****
  • Posts: 1126
Re: How to delete a 3d bullet when it gets a certain range?
« Reply #27 on: October 22, 2018, 04:38:51 PM »
i can't run your code because it uses external files. (and i don't have time to debug it)

so what i will do is convert the code that i have posted in reply #15 (with linepicks and "pickable shapes") to work with the collision system of Blitz3d (with ellipsoids and "collidable shapes") so that you will see how it must be done to work well. (even if it will still be more confusing and unreliable)


ok, i have rewritten the code which uses linepicks and pickables (to make it more clear) :
Code: [Select]
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,VB)
  ;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

and now the same code but using ellipsoids an collidables :
Code: [Select]
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 Ellipsoid
 Field Shape
 Field Life#
 Field PrevMS%
End Type
AddBots()

;player
Global PlayerEllipsoid
Global PlayerShape
Global PlayerYaw#
Global PlayerLife#
Global PlayerPrevMS%
AddPlayer()

;bullets
Type Bullet
 Field Ellipsoid
 Field Shape
 Field Life#
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 collision groups (do not confuse "EntityType()" which define a group of entities and "Type End Type" which define a customtype variable !!! )
Const GShape% = 1
Const GTurningMoving% = 2

EntityType(GroundShape,GShape)
For r.Rock = Each Rock
 EntityType(r\Shape,GShape)
Next
For t.Tree = Each Tree
 EntityType(t\Shape,GShape)
Next
For bo.Bot = Each Bot
 EntityType(bo\Shape,GShape) : EntityType(bo\Ellipsoid,GTurningMoving)
Next
EntityType(PlayerShape,GShape) : EntityType(PlayerEllipsoid,GTurningMoving)

;setup collidables entities and collisions detection / response
Collisions(GTurningMoving,GShape,2,1)


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 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 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 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 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,VB)
  ;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)
  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))
 Next

End Function

Function 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 Function

Function 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 Function

Function UpdateBotsBC()

 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 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

 Next

End Function

Function 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

 EndIf

End Function

Function 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

 Next

End Function

Function 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
 
 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

lol i have found a new way to use the Blitz3d collision detection / reposition system and surprisingly it seems to work...
i bet that you will never see such a short setup in any other Blitz3d code :
Code: [Select]
Const GShape% = 1 ;for collidable shapes like ground, rocks, trees, bots, player, bullets
Const GTurningMoving% = 2 ;for turning moving ellipsoids like bots, player, bullets

;setup collidables entities and collisions detection / response
Collisions(GTurningMoving,GShape,2,1) ;ellipsoid->mesh stop

!!! :D

some notes :
->you have to learn to create shapes / radiuses of a precise units size in order to prevent errors / bugs... (in this case, the ellipsoid within a player/bot is 0.01unit smaller than its associated collidableshape... if it would have the same size, it will be detected as a collision)
->the collisions are detected between a turning moving ellipsoid and a static collidable shape (even if i reposition the collidable shape at the same position than its associated ellipsoid (for player, bots, bullets) it is ocnsidered as static during the collisions calculation.
->an ellipsoid must be smaller and within its associated collidable shape to not cause weird behaviors / bugs (for bots, player, bullets)
->when creating a new bullet, and its ellipsoid and its collidable shape, you want to create it outside any other ellipsoid or collidable shape (so in this case, for a bullet, before i set its radius and entitytype, i position/move the ellipsoid outside of player collidable shape...)
->of course you can create more collisiongroups with different detections / responses, do some tests!
->you can debug visually an ellipsoid by making a sphere of the same radius follow its position...
->in some Blitz3d codes, you will see that the ellipsoid is "merged" with a mesh, and the mesh turns moves with it (like in the markio demo), imo this is a bad approach for several reasons : what if you have a mesh which has not the size of an ellipsoid ? (like a humanoid or a vehicle) in this case you will need to use several ellipsoids to detect the collisions with the environment, and then reposition the mesh accordingly...


I have done another test to compare the 2 collision detection / repositionning systems, and it is clear that using linepicks + pickables is more accurate, reliable, when trying to detect collisions between 2 turning moving entities.
Not sure how the Blitz3d collision system handles that "behind the scene" but sometimes 2 ellipsoids can go one through another... That's why i ended up using linepicks and pickables, if you can't fix a buggy system, you just use another one...
DualCore AMD E-450, 1646 MHz - 6 Go DDR3 1333 SDRAM - AMD Radeon HD 6320 Graphics (384 Mo) - Windows 7 Home Premium - DirectX 11.0

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal