A tank that follows the terran

Blitz3D Forums/Blitz3D Beginners Area/A tank that follows the terran

Yahfree(Posted 2006) [#1]
Hey, i have this tank game i'm messing with as my first real 3d project. First of all i'm new to blitz3d, i'v been using the demo for about 5 days before Christmas, then got the real thing on Christmas, so just over a week of experiance.

Anyways my tank can be controled by the player to go around the terrain. i'm using the following code to keep him above the terrain:
ex#=EntityX(player):ez#=EntityZ(player)
PositionEntity player,ex,TerrainY( land,ex,0,ez )+1.5,ez


now then it looks very strange, what i'm looking for is a code that allows the tank or any car, to rotate to the terrain around him in realtime.

heres my complete code:
;Sets the graphics mode and the backbuffer
Graphics3D 1680,1050,16,1
   SetBuffer BackBuffer()

;Global stuff
Global RIGHT_ARR=205, LEFT_ARR=203, UP_ARR=200, DOWN_ARR=208, SPAC_BAR=57, R_CTR=157, N_0=82
Global cam1, player, land, skybox, playerhead
Global velocity#=0
Global x#=0, y#=0, z#=-10

;Makes the camera
cam1=CreateCamera()
   CameraViewport cam1,0,0,1680,1050
   PositionEntity cam1,0,7+40,-35
   ;RotateEntity cam1,0,180,0
;Makes a light
light1=CreateLight

;Calls some functions that dont loop in realtime
maketerrain()
Loadplayer("Models&Textures\warrior\warriorbody.3ds")
makeskybox()


;Bullet type
Type bullet
  Field sprite, timeout
End Type



;!@#@$@#!$@!#$#@%#$%$%^%^&^%*&^(*&()*)*()%^$^%#@
;!@#$!@#$@#%@#$ MAIN GAME LOOP !#$@#$@%#@$^$%@#$
;#@$!@#$@!#$@#%#$%@#$%@$##@!%#$@%#$%@#$%#@$@%@%$
While Not KeyHit(1)

  ;Calls some loop functions
  playermove()
  chasecam()

;Makes it so the skybody is always in the same spot as the player
PositionEntity skybox,EntityX(player),EntityY(player),EntityZ(player)

;this little code translates the raw velocity code into a fake MPH, that will be displayed in the center of the screen
MPH%=velocity#*30
MPH%=MPH%-MPH-MPH


;Updates and renders the world
UpdateWorld
RenderWorld

;2D stuff
;Text, with some maths to show xyz, and the velocity
Color 255,0,0
Text GraphicsWidth()/2,GraphicsHeight()/2,"MPH"+MPH
Text 50,70,"X: "+EntityX(player)+" Y: "+EntityY(player)+" Z: "+EntityZ(player)
Color 255,255,255

;flip the backbuffer stuff onto the front buffer, and end when the ESC key is pressed
  Flip
Wend


;!@#@$@#!$@!#$#@%#$%$%^%^&^%*&^(*&()*)*()%^
;!@#$!@#$@#%@#$ FUNCTIONS !#$@#$@%#@$^$%@#$
;#@$!@#$@!#$@#%#$%@#$%@$##@!%#$@%#$%@#$%#@$


;Loads the player tank both parts, and resizes 'em
Function Loadplayer(file$)
  ;Tanks body
  player=LoadMesh(file$)
  ptex=LoadTexture("Models&Textures\warrior\warrior.jpg")
  EntityTexture player,ptex
  ScaleEntity player,5,5,5
  RotateEntity player,0,180,0
  EntityType player,t_player
  PositionEntity player,x,y,z

  ;Tanks head
  playerhead=LoadMesh("Models&Textures\warrior\warriorhead.3ds")
  EntityTexture playerhead,ptex
  PositionEntity playerhead,0,41.99,-13
  ScaleEntity playerhead,5,5,5
  RotateEntity playerhead,0,180,0
End Function


;All the movement and control factors go here
Function playermove()

  ;Accelerate and if the key isnt down then decelerate
  If KeyDown(UP_ARR) And velocity#>-1.001 Then velocity#=velocity#-0.001 Else If velocity#<0.0 Then velocity#=velocity#+0.001
  

  ;If the speed is 0 then reverse, and if reverse isnt happening decelerate
  If KeyDown(DOWN_ARR) And velocity#>-0.00001 And velocity#<1.0 Then velocity#=velocity#+0.001 Else If velocity#>0.0 Then velocity#=velocity#-0.001

  ;Turn left
  If KeyDown(LEFT_ARR) Then
  TurnEntity player,0,0.5,0
End If

  ;Turn right
  If KeyDown(RIGHT_ARR) Then
  TurnEntity player,0,-0.5,0
End If

  ;Turns the tanks head left
  If KeyDown(R_CTR) Then
  TurnEntity playerhead,0,2,0
End If

  ;Turns the tanks head right
  If KeyDown(N_0) Then
  TurnEntity playerhead,0,-2,0
End If

  ;Instantly stops the tank, NOTE: fix this
  If KeyHit(SPAC_BAR) Then velocity#=0

;Puts the velocity code in motion
MoveEntity player,0,0,velocity#

    ;Make sure the tank stays ontop of the terrain
	ex#=EntityX(player):ez#=EntityZ(player)
	PositionEntity player,ex,TerrainY( land,ex,0,ez )+1.5,ez


;"Glues the tanks top onto the tanks body but not viseversa, so the tank head can move without moving the body
EntityParent playerhead,player



End Function

;Makes the terrain
Function maketerrain()

  land_tex=LoadTexture( "Terrian stuff\terrain_tex.jpg" ) 
  ScaleTexture land_tex,10,10
  land=LoadTerrain( "Terrian stuff\terrain_hmap.jpg" )
  ScaleEntity land,8,100,8
  PositionEntity land,-2048,0,-2048 
  EntityTexture land,land_tex
  TerrainDetail land,1000,True
  EntityType land,t_land

End Function

;makes the camera
Function chasecam()

 EntityParent cam1,player

End Function

;Creates the skybox
Function makeskybox()
   skybox=CreateMesh()
   ;front face
   b=LoadBrush( "Terrian stuff\front.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,-1,+1,-1,0,0:AddVertex s,+1,+1,-1,1,0 
   AddVertex s,+1,-1,-1,1,1:AddVertex s,-1,-1,-1,0,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;left face
   b=LoadBrush( "Terrian stuff\left.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,+1,+1,-1,0,0:AddVertex s,+1,+1,+1,1,0
   AddVertex s,+1,-1,+1,1,1:AddVertex s,+1,-1,-1,0,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;back face
   b=LoadBrush( "Terrian stuff\back.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,+1,+1,+1,0,0:AddVertex s,-1,+1,+1,1,0
   AddVertex s,-1,-1,+1,1,1:AddVertex s,+1,-1,+1,0,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;right face
   b=LoadBrush( "Terrian stuff\right.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,-1,+1,+1,0,0:AddVertex s,-1,+1,-1,1,0
   AddVertex s,-1,-1,-1,1,1:AddVertex s,-1,-1,+1,0,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;top face
   b=LoadBrush( "Terrian stuff\up.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,-1,+1,+1,0,1:AddVertex s,+1,+1,+1,0,0
   AddVertex s,+1,+1,-1,1,0:AddVertex s,-1,+1,-1,1,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;bottom face 
   b=LoadBrush( "Terrian stuff\down.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,-1,-1,-1,1,0:AddVertex s,+1,-1,-1,1,1
   AddVertex s,+1,-1,+1,0,1:AddVertex s,-1,-1,+1,0,0
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ScaleMesh skybox,100,100,100
   FlipMesh skybox
   EntityFX skybox,1
   EntityOrder skybox,10
End Function



Anyone? also i tried using that one guys code in the CA, somthing about making it happen without using child or pivots, i tried incorperating it into my code, didnt work, if any of you know how to incorporate it into my code that'd be great otherwise do you know any other methods mabey ones that use "Pivots and child entitys"

Thanks,

Yahfree


b32(Posted 2006) [#2]
After loading the terrain, use EntityPickMode land, 2.
Then, instead of using TerrainY, first call
LinePick ex, 2000, ez, 0, -4000, 0
And use PickedY() + 1.5 as the y-coordinate of the tank.
To align the tank to the terrain, use
AlignToVector player, PickedNX(), PickedNY(), PickedNZ(), 2, 0.1
after the linepick.
"0.1" means that the Align should be gradually applied. It should be a value between 0.0 and 1.0


Yahfree(Posted 2006) [#3]
THANKS!!!! seriosely i was brainstorming all day for a simple 3 lines of code!! wow thanks!!


Zethrax(Posted 2007) [#4]
There's a demo by the Blitz developer in the Blitd3D samples directory that may be of use to you.

It should be at: C:\Program Files\Blitz3D\Samples\Blitz 3D Samples\mak\driver


Yahfree(Posted 2007) [#5]
Cool, i'll study that, but for now i'll use B32's code, anyways heres a new question, how do i get the top part of a tank (a NPC) to follow the player, heres the code i'm using:

;Sets the graphics mode and the backbuffer
Graphics3D 1680,1050,16,1
   SetBuffer BackBuffer()

;Global stuff
Global RIGHT_ARR=205, LEFT_ARR=203, UP_ARR=200, DOWN_ARR=208, SPAC_BAR=57, R_CTR=157, N_0=82
Global cam1, player, land, skybox, playerhead, bullet_sprite, boom, enemyhead, enemy
Global velocity#=0
Global x#=0, y#=0, z#=-10
Global t_enemy=1, t_enemyhead=2, t_player=3, t_playerhead=4, t_bullet=5
Global timer=MilliSecs()


Collisions t_player,t_enemy,2,1
Collisions t_bullet,t_enemy,2,1

;Makes the cameras
cam1=CreateCamera()
   CameraViewport cam1,0,0,1680,1050
   PositionEntity cam1,0,7+40,-35


;Makes a light
light1=CreateLight


;Bullet type
Type bullet
  Field sprite, time_out
End Type


boom=LoadSound("Music&SFX\gun fire.wav")

;Calls some functions that dont loop in realtime

maketerrain()
Loadplayer("Models&Textures\warrior\warriorbody.3ds")
makeskybox()
Loadbullet()
Loadenemy()

;!@#@$@#!$@!#$#@%#$%$%^%^&^%*&^(*&()*)*()%^$^%#@
;!@#$!@#$@#%@#$ MAIN GAME LOOP !#$@#$@%#@$^$%@#$
;#@$!@#$@!#$@#%#$%@#$%@$##@!%#$@%#$%@#$%#@$@%@%$
While Not KeyHit(1)

  ;Calls some loop functions
  playermove()
  enemymove()
  chasecam()
  updatebullet()
  collision()
;Makes it so the skybody is always in the same spot as the player
PositionEntity skybox,EntityX(player),EntityY(player),EntityZ(player)

;this little code translates the raw velocity code into a fake MPH, that will be displayed in the center of the screen
MPH%=velocity#*30
MPH%=MPH%-MPH-MPH


;Updates and renders the world
UpdateWorld
RenderWorld

;2D stuff
;Text, with some maths to show xyz, and the velocity
Color 255,0,0
Text GraphicsWidth()/2,GraphicsHeight()/2,"MPH: "+MPH
Text 50,65,"TANK X: "+EntityX(player)+" Y: "+EntityY(player)+" Z: "+EntityZ(player)
Text 50,50,"MOUSE X: "+MouseX()+" Y: "+MouseY()
Rect MouseX(),MouseY(),5,5
Color 255,255,255

;flip the backbuffer stuff onto the front buffer, and end when the ESC key is pressed
  Flip
Wend
End

;!@#@$@#!$@!#$#@%#$%$%^%^&^%*&^(*&()*)*()%^
;!@#$!@#$@#%@#$ FUNCTIONS !#$@#$@%#@$^$%@#$
;#@$!@#$@!#$@#%#$%@#$%@$##@!%#$@%#$%@#$%#@$


;Loads the player tank both parts, and resizes 'em
Function Loadplayer(file$)
  ;Tanks body
  player=LoadMesh(file$)
  ptex=LoadTexture("Models&Textures\warrior\warrior.jpg")
  EntityTexture player,ptex
  ScaleEntity player,5,5,5
  RotateEntity player,0,180,0
  EntityType player,t_player
  PositionEntity player,x,y,z
  EntityType player,t_player
  EntityRadius player,6

  ;Tanks head
  playerhead=LoadMesh("Models&Textures\warrior\warriorhead.3ds")
  EntityTexture playerhead,ptex
  PositionEntity playerhead,0,40.5,-13
  ScaleEntity playerhead,5,5,5
  RotateEntity playerhead,0,180,0
  EntityType playerhead,t_playerhead

End Function


;All the movement and control factors go here
Function playermove()

  ;Accelerate and if the key isnt down then decelerate
  If KeyDown(UP_ARR) And velocity#>-1.001 Then velocity#=velocity#-0.001 Else If velocity#<0.0 Then velocity#=velocity#+0.001
  

  ;If the speed is 0 then reverse, and if reverse isnt happening decelerate
  If KeyDown(DOWN_ARR) And velocity#>-0.00001 And velocity#<1.0 Then velocity#=velocity#+0.001 Else If velocity#>0.0 Then velocity#=velocity#-0.001

  ;Turn left
  If KeyDown(LEFT_ARR) Then
  TurnEntity player,0,0.5,0
End If

  ;Turn right
  If KeyDown(RIGHT_ARR) Then
  TurnEntity player,0,-0.5,0
End If

  ;Turns the tanks head left
  If KeyDown(R_CTR) Then
  TurnEntity playerhead,0,2,0
End If

  ;Turns the tanks head right
  If KeyDown(N_0) Then
  TurnEntity playerhead,0,-2,0
End If

  ;Instantly stops the tank, NOTE: fix this
  If KeyHit(SPAC_BAR) Then shootbullet(playerhead)

  If KeyHit(19) Then 
  ShowEntity enemy 
  ShowEntity enemyhead
  End If

 
;Puts the velocity code in motion
MoveEntity player,0,0,velocity#

    ;Make sure the tank stays ontop of the terrain and rotates to the terrain around it
	ex#=EntityX(player):ez#=EntityZ(player)
	LinePick ex, 2000, ez, 0, -4000, 0
	PositionEntity player,ex,PickedY(),ez
	AlignToVector player, PickedNX(), PickedNY(), PickedNZ(), 2, 0.1



;"Glues the tanks top onto the tanks body but not viseversa, so the tank head can move without moving the body
EntityParent playerhead,player



End Function

;Makes the terrain
Function maketerrain()

  land_tex=LoadTexture( "Terrian stuff\terrain_tex.jpg" ) 
  ScaleTexture land_tex,10,10
  land=LoadTerrain( "Terrian stuff\terrain_hmap.jpg" )
  EntityPickMode land, 2
  ScaleEntity land,8,100,8
  PositionEntity land,-2048,0,-2048 
  EntityTexture land,land_tex
  TerrainDetail land,1000,True
  EntityType land,t_land

End Function

;makes the camera
Function chasecam()

 EntityParent cam1,player

End Function

;Creates the skybox
Function makeskybox()
   skybox=CreateMesh()
   ;front face
   b=LoadBrush( "Terrian stuff\front.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,-1,+1,-1,0,0:AddVertex s,+1,+1,-1,1,0 
   AddVertex s,+1,-1,-1,1,1:AddVertex s,-1,-1,-1,0,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;left face
   b=LoadBrush( "Terrian stuff\left.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,+1,+1,-1,0,0:AddVertex s,+1,+1,+1,1,0
   AddVertex s,+1,-1,+1,1,1:AddVertex s,+1,-1,-1,0,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;back face
   b=LoadBrush( "Terrian stuff\back.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,+1,+1,+1,0,0:AddVertex s,-1,+1,+1,1,0
   AddVertex s,-1,-1,+1,1,1:AddVertex s,+1,-1,+1,0,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;right face
   b=LoadBrush( "Terrian stuff\right.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,-1,+1,+1,0,0:AddVertex s,-1,+1,-1,1,0
   AddVertex s,-1,-1,-1,1,1:AddVertex s,-1,-1,+1,0,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;top face
   b=LoadBrush( "Terrian stuff\up.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,-1,+1,+1,0,1:AddVertex s,+1,+1,+1,0,0
   AddVertex s,+1,+1,-1,1,0:AddVertex s,-1,+1,-1,1,1
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ;bottom face 
   b=LoadBrush( "Terrian stuff\down.jpg",49 )
   s=CreateSurface( skybox,b )
   AddVertex s,-1,-1,-1,1,0:AddVertex s,+1,-1,-1,1,1
   AddVertex s,+1,-1,+1,0,1:AddVertex s,-1,-1,+1,0,0
   AddTriangle s,0,1,2:AddTriangle s,0,2,3
   FreeBrush b
   ScaleMesh skybox,100,100,100
   FlipMesh skybox
   EntityFX skybox,1
   EntityOrder skybox,10
End Function

;Loads the bullet sprite and hides it until needed
Function Loadbullet()

   bullet_sprite=LoadSprite("Sprites\bluspark.bmp")
   ScaleSprite bullet_sprite,3,3
   HideEntity bullet_sprite
   EntityRadius bullet_sprite,1.5
   EntityType bullet_sprite,t_bullet

End Function

;The bullets realtime stuff after its fired
Function updatebullet()

   For b.bullet=Each bullet
   b\time_out=b\time_out-1
   If b\time_out=0
      FreeEntity b\sprite
      Delete b
      Return
   EndIf
   MoveEntity b\sprite,0,0,-2
    Next

End Function

;Shoots the bullet when called (called when spacebar is pressed)
Function shootbullet(playerhead)

   b.bullet=New bullet
   b\time_out=150
   b\sprite=CopyEntity( bullet_sprite, playerhead )
   PositionEntity b\sprite,0,0,-1
   EntityParent b\sprite,0
   PlaySound boom
   Return p

End Function

;Loads the enemy (a copy of the players tank)
Function Loadenemy()


 enemy=CopyEntity(player)
  EntityType enemy,t_enemy
  PositionEntity enemy,0,0,25
  EntityRadius enemy,6

 enemyhead=CopyEntity(playerhead)
  EntityType enemyhead,t_enemyhead
  PositionEntity enemyhead,0,40.5,22


End Function

;Enemy movement and realtime stuff
Function enemymove()

   ;MoveEntity enemy,0,0,0.5
   TurnEntity enemyhead,0,EntityZ(player),0

    ;Make sure the tank stays ontop of the terrain and rotates to the terrain around it
	ex#=EntityX(enemy):ez#=EntityZ(enemy)
	LinePick ex, 2000, ez, 0, -4000, 0
	PositionEntity enemy,ex,PickedY(),ez
	AlignToVector enemy, PickedNX(), PickedNY(), PickedNZ(), 2, 0.1

EntityParent enemyhead,enemy

End Function

;Collisions
Function collision()

    ;Deletes the bullet and hides the tank when the bullet and the tank collide
    For b.bullet=Each bullet
		If EntityCollided( b\sprite,t_enemy )
        HideEntity enemy
        HideEntity enemyhead
        FreeEntity b\sprite
        Delete b
        Return
     End If
    Next

End Function


as you can see this is my sad atempt of doign this effect:
TurnEntity enemyhead,0,EntityZ(player),0



Yahfree(Posted 2007) [#6]
Also, i'm still learning types, i tried to match the bullet effect from Mak's Castle demo, so far so good.