[PB5.00 b5] Aéroglisseur + terrain + physique
Publié : jeu. 18/oct./2012 13:22
Salut tout le monde!
Pour tester un peu la v5.00, je me suis fait ce petit test. Il s'agit d'un petit aéroglisseur à déplacer sur un terrain, avec gestion de la physique.
C'est là que je me rends compte que je ne suis pas très bon, avec la physique.
Bon, ça marche, ça pourrait suffire pour un petit jeu d'arcade, mais c'est loin d'être parfait.
En fait, le principal truc qui me chiffonne, c'est que je n'ai pas réussi à déterminer avec précision quand le vaisseau touche le sol => sur les pentes élevées, le contact n'est pas détecté et le vaisseau ne s'adapte plus à l'angle du terrain (je n'arrive pas à m'expliquer clairement; voyez par vous-même).
Merci à tout ceux à qui j'ai chipé des bouts de code (Comtois, principalement). Par ailleurs, je suis ouvert à toute amélioration, alors n'hésitez pas
!
[EDIT] grosse mise à jour: des arbres, des adversaires, et des checkpoints auxquels il faut arriver avant les adversaires!
Prenez le zip (il y a pleins de fichiers en plus), et surtout effacez le "fichier cache du terrain" (hovercraft_00000000.dat, dans le répertoire "meshes") parce que ce n'est plus le même.
[EDIT] Possibilité d'avoir plus de 3 adversaires. Ils sont réparties entre les trois équipes adverses et vous êtes seul contre tous...
Code + médias: http://keleb.free.fr/codecorner/downloa ... rcraft.zip
Pour tester un peu la v5.00, je me suis fait ce petit test. Il s'agit d'un petit aéroglisseur à déplacer sur un terrain, avec gestion de la physique.
C'est là que je me rends compte que je ne suis pas très bon, avec la physique.

Bon, ça marche, ça pourrait suffire pour un petit jeu d'arcade, mais c'est loin d'être parfait.
En fait, le principal truc qui me chiffonne, c'est que je n'ai pas réussi à déterminer avec précision quand le vaisseau touche le sol => sur les pentes élevées, le contact n'est pas détecté et le vaisseau ne s'adapte plus à l'angle du terrain (je n'arrive pas à m'expliquer clairement; voyez par vous-même).
Merci à tout ceux à qui j'ai chipé des bouts de code (Comtois, principalement). Par ailleurs, je suis ouvert à toute amélioration, alors n'hésitez pas

[EDIT] grosse mise à jour: des arbres, des adversaires, et des checkpoints auxquels il faut arriver avant les adversaires!
Prenez le zip (il y a pleins de fichiers en plus), et surtout effacez le "fichier cache du terrain" (hovercraft_00000000.dat, dans le répertoire "meshes") parce que ce n'est plus le même.
[EDIT] Possibilité d'avoir plus de 3 adversaires. Ils sont réparties entre les trois équipes adverses et vous êtes seul contre tous...

Code + médias: http://keleb.free.fr/codecorner/downloa ... rcraft.zip
Code : Tout sélectionner
;************************************************************************************
; Hovercraft race (inspired by the Binary Moon tutorials for DarkBasic)
; PB version: 5.00 b6
; Date: October, 23, 2012
;- F1 -> Change camera view
;- F2 -> Change camera target
;- F5 : Display physic body
;- F6 : Wireframe mode
;************************************************************************************
;************************************************************************************
;- ---- Constants and structure ----
;************************************************************************************
#NUMTERRAIN = 0
#TerrainMiniX = 0
#TerrainMiniY = 0
#TerrainMaxiX = 0
#TerrainMaxiY = 0
#CAMERA = 0
#NB_HOVERCRAFT = 6 ; Nb hovercrafts (except you)
#NB_TEAMS = 3 ; Nb teams (except yours)
#NB_CRATESTACKS = 20
#NB_TREES = 100
Enumeration
#RearView
#SideView
#FrontView
#TopView
#END_VIEWLIST
EndEnumeration
Structure hover_struct
node.i
frontNode.i
backNode.i
leftNode.i
rightNode.i
cameraNode.i
hovercraftMesh.i
hovercraftEntity.i
physicsEntity.i
physicsMesh.i
mass.f
restitution.f
friction.f
radius.f
centerHeight.f
thrust.f
EndStructure
Global Dim hovercraft.hover_struct(#NB_HOVERCRAFT+1)
Structure checkpoint_struct
node.i
x.f
y.f
z.f
radius.f
EndStructure
Global currentCheckpoint.checkpoint_struct
Global Dim treeMesh.i(4)
Global Dim scoreSprite.i(4)
Global Dim score.i(4)
Global Dim scoreColor.i(4)
scoreColor(0) = $0000FF
scoreColor(1) = $FF0000
scoreColor(2) = $00FF00
scoreColor(3) = $00FFFF
Global Dim nomMatAi.s(4)
nomMatAi(0) = "hoverblue"
nomMatAi(1) = "hovergreen"
nomMatAi(2) = "hoveryellow"
Global arrowMesh.i,arrowEntity.i
EnableExplicit
;************************************************************************************
;- ---- Macros ----
;************************************************************************************
; Les deux macros ci-dessous sont de Comtois. Merci Comtois !
Macro NEWXVALUE(x, Angle, Distance)
((x) + Cos(Radian(Angle+90)) * (Distance))
EndMacro
Macro NEWZVALUE(z, Angle, Distance)
((z) - Sin(Radian(Angle+90)) * (Distance))
EndMacro
Macro ANGLE2CHECKPOINT(idHovercraft)
Degree(ATan2(NodeZ(hovercraft(idHovercraft)\node) - currentCheckpoint\z , NodeX(hovercraft(idHovercraft)\node) - currentCheckpoint\x ))
EndMacro
;************************************************************************************
;- ---- Procedures ----
;************************************************************************************
; Gestion des blendmaps du terrain, par Comtois
Procedure Clamp(*var.float, min.f, max.f)
If *var\f < min
*var\f = min
ElseIf *var\f > max
*var\f = max
EndIf
EndProcedure
Procedure InitBlendMaps()
Protected minHeight1.f,fadeDist1.f,minHeight2.f,fadeDist2.f
Protected x.i,y.i,tx.i,ty.i,size.i
Protected height.f, val.f
minHeight1 = 0
fadeDist1 = 15
minHeight2 = 25
fadeDist2 = 15
For ty = #TerrainMiniY To #TerrainMaxiY
For tx = #TerrainMiniX To #TerrainMaxiX
Size = TerrainTileLayerMapSize(#NUMTERRAIN, tx, ty)
For y = 0 To Size-1
For x = 0 To Size-1
Height = TerrainTileHeightAtPosition(#NUMTERRAIN, tx, ty, 1, x, y)
val = (Height - minHeight1) / fadeDist1
Clamp(@val, 0, 1)
SetTerrainTileLayerBlend(#NUMTERRAIN, tx, ty, 1, x, y, val)
val = (Height - minHeight2) / fadeDist2
Clamp(@val, 0, 1)
SetTerrainTileLayerBlend(#NUMTERRAIN, tx, ty, 2, x, y, val)
Next
Next
UpdateTerrainTileLayerBlend(#NUMTERRAIN, tx, ty, 1)
UpdateTerrainTileLayerBlend(#NUMTERRAIN, tx, ty, 2)
Next
Next
EndProcedure
; ************** end of terrain procs *************
; Keep angle in the 0-360 range
Procedure.f wrapValue(angle.f)
If angle < 0
angle + 360
ElseIf angle >=360
angle-360
EndIf
ProcedureReturn angle
EndProcedure
; La procédure ci-dessous est de Comtois. Merci Comtois !
; Calcule une valeur progressive allant de la valeur actuelle à la valeur cible
Procedure.f curveValue(actuelle.f, Cible.f, P.f)
If P > 1000.0
P = 1000.0
EndIf
ProcedureReturn (actuelle + ( (Cible - actuelle) * P / 1000.0))
EndProcedure
Procedure createTrees(nbTrees.i)
Protected i.i,tree.i,numMesh.i
Protected posX.f,posY.f,posZ.f
treeMesh(0) = LoadMesh(#PB_Any,"arbol_mort.mesh")
treeMesh(1) = LoadMesh(#PB_Any,"arbol_sec.mesh")
treeMesh(2) = LoadMesh(#PB_Any,"arbol.mesh")
treeMesh(3) = LoadMesh(#PB_Any,"sapin.mesh")
BuildMeshShadowVolume(treeMesh(0))
BuildMeshShadowVolume(treeMesh(1))
BuildMeshShadowVolume(treeMesh(2))
BuildMeshShadowVolume(treeMesh(3))
For i= 1 To nbTrees
posX = Random(900) - 450
posZ = Random(900) - 450
posY = TerrainHeight(#NUMTERRAIN,posX,posZ)-0.2
numMesh = Round(posY / 10, #PB_Round_Down)
Clamp(@numMesh,0,3)
If numMesh > 3
numMesh = 3
EndIf
tree = CreateEntity(#PB_Any,MeshID(treeMesh(numMesh)),#PB_Material_None,posX,posY,posZ)
RotateEntity(tree,-90,Random(360),0)
ScaleEntity(tree,(70 + Random(60))/100.0,(70 + Random(60))/100.0,(70 + Random(60))/100.0)
EntityRenderMode(tree,#PB_Entity_CastShadow)
EntityPhysicBody(tree,#PB_Entity_StaticBody,99,1.0,1.0)
Next i
EndProcedure
Procedure createCrates(nbStacks.i)
Protected i.i,j.i,temp.i
Protected cubeMesh.i,txCrate.i,mtCrate.i
Protected oriX.f,oriZ.f,posX.f,posY,posZ.f
cubeMesh = CreateCube(#PB_Any,1)
txCrate = LoadTexture(#PB_Any,"crate.png")
mtCrate = CreateMaterial(#PB_Any,TextureID(txCrate))
For j=1 To nbStacks
posX = Random(900) - 450
oriZ = Random(900) - 450
For i = 1 To 3
temp = CreateEntity(#PB_Any, MeshID(cubeMesh), MaterialID(mtCrate))
posZ = oriZ + (i*1.1)
EntityLocate(temp,posX,TerrainHeight(#NUMTERRAIN,posX,posZ)+0.5,posZ)
EntityPhysicBody(temp, #PB_Entity_BoxBody, 0.25)
Next i
For i = 1 To 2
temp = CreateEntity(#PB_Any, MeshID(cubeMesh), MaterialID(mtCrate))
posZ = oriZ + 0.5 + (i*1.1)
EntityLocate(temp,posX,TerrainHeight(#NUMTERRAIN,posX,posZ)+1.5,posZ)
EntityPhysicBody(temp, #PB_Entity_BoxBody, 0.25)
Next i
temp = CreateEntity(#PB_Any, MeshID(cubeMesh), MaterialID(mtCrate))
posZ = oriZ + 1 + 1.1
EntityLocate(temp,posX,TerrainHeight(#NUMTERRAIN,posX,posZ)+2.5,posZ)
EntityPhysicBody(temp, #PB_Entity_BoxBody, 0.25)
Next j
EndProcedure
; Créer un hovercraft et initialise ses paramètres: position, friction, hauteur de son pivot, accélération...
Procedure createHovercraft(id.i,nomMesh.s,posX.f, posZ.f, mass.f, restitution.f, friction.f, thrust.f, centerHeight.f)
Protected numMat.i
; Material
If id = 0
numMat = GetScriptMaterial(#PB_Any,"hoverred")
Else
numMat = GetScriptMaterial(#PB_Any,nomMatAi((id-1) % #NB_TEAMS))
EndIf
; Hovercraft entity
hovercraft(id)\hovercraftMesh = LoadMesh(#PB_Any,"hovercraft.mesh")
hovercraft(id)\hovercraftEntity = CreateEntity(#PB_Any,MeshID(hovercraft(id)\hovercraftMesh),MaterialID(numMat))
EntityRenderMode(hovercraft(id)\hovercraftEntity,#PB_Entity_CastShadow)
EntityPhysicBody(hovercraft(id)\hovercraftEntity,#PB_Entity_None)
; Hovercraft parameters
hovercraft(id)\thrust = thrust
hovercraft(id)\radius = MeshRadius(hovercraft(id)\hovercraftMesh)*1.33
hovercraft(id)\centerHeight = centerHeight
hovercraft(id)\mass = mass
hovercraft(id)\restitution = restitution
hovercraft(id)\friction = friction
; Main node
hovercraft(id)\node = CreateNode(#PB_Any)
AttachNodeObject(hovercraft(id)\node,EntityID(hovercraft(id)\hovercraftEntity))
; These nodes are used to get terrain height at different points of the hovercraft, according to its rotation
hovercraft(id)\frontNode = CreateNode(#PB_Any,0,0,-hovercraft(id)\radius)
hovercraft(id)\backNode = CreateNode(#PB_Any,0,0,hovercraft(id)\radius)
hovercraft(id)\leftNode = CreateNode(#PB_Any,-hovercraft(id)\radius,0,0)
hovercraft(id)\rightNode = CreateNode(#PB_Any,hovercraft(id)\radius,0,0)
AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\frontNode))
AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\backNode))
AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\leftNode))
AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\rightNode))
; Camera Node
hovercraft(id)\cameraNode = CreateNode(#PB_Any,0,1,5)
AttachNodeObject(hovercraft(id)\node,NodeID(hovercraft(id)\cameraNode))
; Physics entity for the hovercraft
hovercraft(id)\physicsMesh = CreateSphere(#PB_Any,hovercraft(id)\radius * 0.8)
hovercraft(id)\physicsEntity = CreateEntity(#PB_Any,MeshID(hovercraft(id)\physicsMesh),MaterialID(999),posX,TerrainHeight(#NUMTERRAIN,posX,posZ)+1,posZ)
EntityRenderMode(hovercraft(id)\physicsEntity,0)
EntityPhysicBody(hovercraft(id)\physicsEntity,#PB_Entity_SphereBody,hovercraft(id)\mass,hovercraft(id)\restitution,hovercraft(id)\friction)
HideEntity(hovercraft(id)\physicsEntity,#True)
EndProcedure
; Apply thrust and steering, and reposition the hovercraft
Procedure moveHovercraft(id.i ,forward.i, backward.i, left.i, right.i)
Protected xPos.f, yPos.f, zPos.f
Protected frontHeight.f,backHeight.f,leftHeight.f,rightHeight.f
Protected xAng.f,yAng.f, zAng.f
Protected xSlide.f,zSlide.f
Protected thrustAngle.f, thrust.f
; Position the hovercraft and get its yaw
xPos = EntityX(hovercraft(id)\physicsEntity)
yPos = EntityY(hovercraft(id)\physicsEntity) - hovercraft(id)\radius
zPos = EntityZ(hovercraft(id)\physicsEntity)
yAng = NodeYaw(hovercraft(id)\node)
; The hovercraft can rotate left/right, even in the air
If left = #True
RotateNode(hovercraft(id)\node,0,wrapvalue(yAng+4),0)
ElseIf right = #True
RotateNode(hovercraft(id)\node,0,wrapvalue(yAng-4),0)
EndIf
; If the player is on ground:
; - its rotation must change according to terrain slope;
; - it can accelerate / deccelerate;
ClearDebugOutput()
If yPos < TerrainHeight(#NUMTERRAIN,xPos,zPos)
; Friction
; J'aimerais bien que la friction soit plus importante, mais avec un body "Sphere", on ne peut pas (?)
; Put the hovercraft on the ground
yPos = TerrainHeight(#NUMTERRAIN,xPos,zPos)
; Positions of the front, back, left and right nodes
frontHeight = TerrainHeight(#NUMTERRAIN,NodeX(hovercraft(id)\frontNode),NodeZ(hovercraft(id)\frontNode))
backHeight = TerrainHeight(#NUMTERRAIN,NodeX(hovercraft(id)\backNode),NodeZ(hovercraft(id)\backNode))
leftHeight = TerrainHeight(#NUMTERRAIN,NodeX(hovercraft(id)\leftNode),NodeZ(hovercraft(id)\leftNode))
rightHeight = TerrainHeight(#NUMTERRAIN,NodeX(hovercraft(id)\rightNode),NodeZ(hovercraft(id)\rightNode))
; Quick hack to estimate hovercraft's angle
xAng = (frontHeight - backHeight) * 30
zAng = (rightHeight - leftHeight) * 30
; Update the vehicle rotation
RotateEntity(hovercraft(id)\hovercraftEntity,xAng,0,0,#PB_Absolute)
RotateEntity(hovercraft(id)\hovercraftEntity,0,0,zAng,#PB_Relative)
; apply forward/backward movement
If forward = #True
thrustAngle = 270 - NodeYaw(hovercraft(id)\node)
thrust = hovercraft(id)\thrust
ElseIf backward = #True
thrustAngle = 270 - NodeYaw(hovercraft(id)\node)
thrust = -hovercraft(id)\thrust
EndIf
; Adjust thrust according to front/back angle
thrust * (1 - (xAng/30))
;Debug StrF(xpos,2)+" , "+StrF(zpos,2)
;Debug "Angle = " + StrF(xAng,2) + "° | Thrust factor = " + StrF((1 - (xAng/30)),2)
; Move the hovercraft
DisableEntityBody(hovercraft(id)\physicsEntity,#False)
ApplyEntityForce(hovercraft(id)\physicsEntity,thrust * Cos(Radian(thrustAngle)),0,thrust * Sin(Radian(thrustAngle)) )
SetEntityAttribute(hovercraft(id)\physicsEntity, #PB_Entity_MaxVelocity, hovercraft(id)\thrust)
EndIf
; Reposition the player object
NodeLocate(hovercraft(id)\node,xPos,yPos + hovercraft(id)\centerHeight,zPos)
; xang = Degree(ATan2(NodeZ(hovercraft(id)\node) - currentCheckpoint\z , NodeX(hovercraft(id)\node) - currentCheckpoint\x ) )
; Debug wrapValue(xang - NodeYaw(hovercraft(id)\node))
EndProcedure
Procedure moveAiHovercraft()
Protected id.i
Protected forward.b = #True, backward.b, left.b, right.b
Protected angle.f
For id = 1 To #NB_HOVERCRAFT
If wrapValue(ANGLE2CHECKPOINT(id) - NodeYaw(hovercraft(id)\node)) < 180
left=#True
right=#False
Else
left=#False
right=#True
EndIf
moveHovercraft(id,forward,backward,left,right)
Next id
EndProcedure
Procedure manageCheckpoint(*ptrCheckPoint.checkpoint_struct)
Protected x.f = *ptrCheckPoint\x + *ptrCheckPoint\radius * Cos(Radian(ElapsedMilliseconds()*2))
Protected z.f = *ptrCheckPoint\z + *ptrCheckPoint\radius * Sin(Radian(ElapsedMilliseconds()*2))
Protected i.i, team.i
NodeLocate(*ptrCheckPoint\node,x,TerrainHeight(#NUMTERRAIN,x,z)+ *ptrCheckPoint\y,z)
; If an hovercraft reach the checkpoint, change its position
For i=0 To #NB_HOVERCRAFT
If (*ptrCheckPoint\x - NodeX(hovercraft(i)\node)) * (*ptrCheckPoint\x - NodeX(hovercraft(i)\node)) + (*ptrCheckPoint\z - NodeZ(hovercraft(i)\node)) * (*ptrCheckPoint\z - NodeZ(hovercraft(i)\node)) < *ptrCheckPoint\radius * *ptrCheckPoint\radius
*ptrCheckPoint\x = Random(900) - 450
*ptrCheckPoint\z = Random(900) - 450
If i > 0
team = 1 + ((i-1) % #NB_TEAMS)
EndIf
score(team) + 10
StartDrawing(SpriteOutput(scoreSprite(team)))
Box(0,0,20,20,scoreColor(team))
DrawText(32,2,RSet(Str(score(team)),3,"0"))
StopDrawing()
EndIf
Next i
EndProcedure
; Position the camera
Procedure manageCamera(mode.i,id.i)
Protected Px.f, Py.f, Pz.f
Static cameraAngle.f
Select Mode
Case #FrontView
cameraAngle = CurveValue(cameraAngle, NodeYaw(hovercraft(id)\node), 100)
Px = CurveValue(CameraX(#CAMERA), NEWXVALUE(NodeX(hovercraft(id)\node), cameraAngle, 6), 100)
Py = CurveValue(CameraY(#CAMERA), NodeY(hovercraft(id)\node) + 3, 100)
Pz = CurveValue(CameraZ(#CAMERA), NEWZVALUE(NodeZ(hovercraft(id)\node), cameraAngle, 6), 100)
Case #TopView
cameraAngle = CurveValue(cameraAngle, NodeYaw(hovercraft(id)\node) + 180, 100)
Px = CurveValue(CameraX(#CAMERA), NEWXVALUE(NodeX(hovercraft(id)\node), cameraAngle, 4), 30)
Py = CurveValue(CameraY(#CAMERA), NodeY(hovercraft(id)\node) + 100, 30)
Pz = CurveValue(CameraZ(#CAMERA), NEWZVALUE(NodeZ(hovercraft(id)\node), cameraAngle, 4), 30)
Case #RearView
cameraAngle = CurveValue(cameraAngle, NodeYaw(hovercraft(id)\node) + 180, 100)
Px = CurveValue(CameraX(#CAMERA), NodeX(hovercraft(id)\cameraNode), 100)
Pz = CurveValue(CameraZ(#CAMERA), NodeZ(hovercraft(id)\cameraNode), 100)
Py = CurveValue(CameraY(#CAMERA), NodeY(hovercraft(id)\node) + 1, 100)
If Py < TerrainHeight(#NUMTERRAIN,Px,Pz) + 1
Py = TerrainHeight(#NUMTERRAIN,Px,Pz) + 1
EndIf
Case #SideView
cameraAngle = CurveValue(cameraAngle, NodeYaw(hovercraft(id)\node) + 90, 100)
Px = CurveValue(CameraX(#CAMERA), NEWXVALUE(NodeX(hovercraft(id)\node), cameraAngle, 8), 100)
Py = CurveValue(CameraY(#CAMERA), NodeY(hovercraft(id)\node) + 4, 100)
Pz = CurveValue(CameraZ(#CAMERA), NEWZVALUE(NodeZ(hovercraft(id)\node), cameraAngle, 8), 100)
EndSelect
CameraLocate(#CAMERA, Px, Py, Pz)
CameraLookAt(#CAMERA, NodeX(hovercraft(id)\node), NodeY(hovercraft(id)\node), NodeZ(hovercraft(id)\node))
EndProcedure
DisableExplicit
;************************************************************************************
;- ---- Main program ----
;************************************************************************************
If InitEngine3D() = 0
MessageRequester( "Error" , "Can't initialize 3D, check if engine3D.dll is available" , 0 )
End
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
MessageRequester( "Error" , "Can't find DirectX 7.0 or above" , 0 )
End
EndIf
OpenWindow(0,0, 0, 800 , 500 ,"Hovercraft")
OpenWindowedScreen(WindowID(0),0,0, 800, 500,0,0,0,#PB_Screen_SmartSynchronization)
;- 3d archives
Add3DArchive("meshes/", #PB_3DArchive_FileSystem)
Add3DArchive("materials/", #PB_3DArchive_FileSystem)
Add3DArchive("textures/", #PB_3DArchive_FileSystem)
Add3DArchive("medias/", #PB_3DArchive_FileSystem)
Parse3DScripts()
;- Lighting
light = CreateLight(#PB_Any ,$FFFFFF, 500, 1000, 500,#PB_Light_Directional)
LightColor(light, $555555, #PB_Light_SpecularColor)
LightDirection(light, 0.55, -0.5, -0.75)
AmbientColor($222222)
; light = CreateLight(#PB_Any ,$FFFFFF, 500, 750, 500)
; AmbientColor($333333)
WorldShadows(#PB_Shadow_Modulative)
Fog($C2AF80,20,10,1000)
;- Camera
CreateCamera(#CAMERA, 0, 0, 100, 100)
CameraBackColor(#CAMERA,$FF7755)
; Arrow
arrowMesh = LoadMesh(#PB_Any,"arrow.mesh")
arrowEntity = CreateEntity(#PB_Any,MeshID(arrowMesh),#PB_Material_None)
ScaleEntity(arrowEntity,0.5,0.5,0.5)
;- Terrain definition
SetupTerrains(LightID(light), 3000, #PB_Terrain_NormalMapping)
CreateTerrain(#NUMTERRAIN, 1025, 1000, 50, 3, "hovercraft", "dat")
AddTerrainTexture(#NUMTERRAIN, 0, 10, "sand.jpg", "sand_n.jpg")
AddTerrainTexture(#NUMTERRAIN, 1, 20, "grass.jpg", "grass_n.jpg")
AddTerrainTexture(#NUMTERRAIN, 2, 30, "rock.jpg", "rock_n.jpg")
; Build terrains
For ty = #TerrainMiniY To #TerrainMaxiY
For tx = #TerrainMiniX To #TerrainMaxiX
imported = DefineTerrainTile(#NUMTERRAIN, tx, ty, "heightmap_2.png", ty % 2, tx % 2)
Next
Next
BuildTerrain(#NUMTERRAIN)
TerrainPhysicBody(#NUMTERRAIN,0.1,2.0)
If imported = #True
InitBlendMaps()
UpdateTerrain(#NUMTERRAIN)
SaveTerrain(#NUMTERRAIN, #False)
EndIf
;- Wireframe material
; (used To display the hovercraft's physics entity)
CreateTexture(999,16,16)
StartDrawing(TextureOutput(999))
Box(0,0,16,16,$FFFF00)
StopDrawing()
CreateMaterial(999,TextureID(999))
DisableMaterialLighting(999, State)
MaterialShadingMode(999, #PB_Material_Wireframe)
;- Hovercrafts
createHovercraft(0,"hovercraft.mesh",0,150,1,0.1,2.0,15,0.4) ; player
numLine = 0
For i=1 To #NB_HOVERCRAFT
; Put them in lines of 20
If i % 20 = 0
numLine + 1
EndIf
; One to the left, one to the right
If i % 2 = 0
posX = (-(i - numLine *20) * 5)
Else
posX = ((i - numLine *20) * 5)
EndIf
createHovercraft(i,"hovercraft.mesh",posX,160 + numLine * 10,1,0.1,2.0,14.5,0.4) ; opponents (slightly slower)
Next i
;- Crates
cubeMesh = CreateCube(#PB_Any,1)
createCrates(#NB_CRATESTACKS)
;- Trees
createTrees(#NB_TREES)
;- Checkpoint
ringsParticle = GetScriptParticleEmitter(#PB_Any,"flareFountain")
currentCheckpoint\x = 0
currentCheckpoint\z = 0
currentCheckpoint\radius = 3
currentCheckpoint\node = CreateNode(#PB_Any)
AttachNodeObject(currentCheckpoint\node,ParticleEmitterID(ringsParticle))
; Score sprites
For i = 0 To #NB_TEAMS
scoreSprite(i) = CreateSprite(#PB_Any,64,20)
StartDrawing(SpriteOutput(scoreSprite(i)))
Box(0,0,20,20,scoreColor(i))
DrawText(32,2,"000")
DrawingMode(#PB_2DDrawing_Outlined)
Box(0,0,64,20,scoreColor(i))
StopDrawing()
Next i
;- Main loop
hidePhysicBody = #True
wireframe = #False
cameraMode = #rearView
Repeat
While WindowEvent()
Wend
forward = #False:backward=#False:left=#False:right=#False
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Up)
forward = #True
ElseIf KeyboardPushed(#PB_Key_Down)
backward=#True
EndIf
If KeyboardPushed(#PB_Key_Left)
left = #True
ElseIf KeyboardPushed(#PB_Key_Right)
right=#True
EndIf
;Change camera view
If KeyboardReleased(#PB_Key_F1)
cameraMode = (cameraMode + 1) % #END_VIEWLIST
EndIf
If KeyboardReleased(#PB_Key_F2)
cameraTarget = (cameraTarget + 1) % (#NB_HOVERCRAFT + 1)
EndIf
; Display physic body
If KeyboardReleased(#PB_Key_F5)
hidePhysicBody = 1 - hidePhysicBody
HideEntity(hovercraft(0)\physicsEntity, hidePhysicBody)
EndIf
; Display physic body
If KeyboardReleased(#PB_Key_F6)
wireframe = 1 - wireframe
If wireframe = #True
CameraRenderMode(#CAMERA,#PB_Camera_Wireframe)
Else
CameraRenderMode(#CAMERA,#PB_Camera_Textured)
EndIf
EndIf
EndIf
;- Checkpoints
manageCheckpoint(@currentCheckpoint)
;- Move the hovercrafts
moveHovercraft(0,forward,backward,left,right)
moveAiHovercraft()
;- Move the camera
ManageCamera(cameraMode,cameraTarget)
;- Hud
MoveCamera(#CAMERA,0,1.60,-5)
EntityLocate(arrowEntity,CameraX(#CAMERA),CameraY(#CAMERA),CameraZ(#CAMERA))
RotateEntity(arrowEntity,30,ANGLE2CHECKPOINT(cameraTarget),0)
MoveCamera(#CAMERA,0,-1.60,5)
RenderWorld()
;- Scores
For i = 0 To #NB_TEAMS
DisplayTransparentSprite(scoreSprite(i),i*80,8)
Next i
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)