using the method that i
suggested before:
// Project: Tap Tower
// Created: 2022-01-23
// By: Virtual Nomad
// show all errors
SetErrorMode(2)
// set window properties
SetWindowTitle( "Tap Tower" )
SetWindowSize( 1280,720, 1 )
SetWindowAllowResize( 1 )
// set display properties
SetVirtualResolution( 1280,720)
SetOrientationAllowed( 1, 1, 1, 1 )
SetSyncRate( 30, 0 )
SetScissor( 0,0,0,0 )
UseNewDefaultFonts( 1 )
Create3DPhysicsWorld()
SetShadowMappingMode(3)
SetSunActive( 1)
Type Tower
ID, NextShot#, RateOfFire#
EndType
GLOBAL Towers as Tower []
Type Enemy
ID, Health
EndType
GLOBAL Enemies as Enemy []
GLOBAL LastSpawn#, Cash
Cash = 50
GLOBAL Board as Integer [9,4]
MakeBoard()
GLOBAL Shots as Integer []
SetCameraPosition(1,144,150,-220) : SetCameraLookAt(1,144,0,96,0)
do
If GetRawKeyState(27) then End
If LastSpawn# + 2.0 <= Timer()
SpawnEnemy()
LastSpawn# = Timer()
Endif
DoTowers()
DoShots()
If Enemies.Length > -1 then DoEnemies()
Print( "Cash: " + STR(Cash) )
If Cash >= 10 and Towers.Length < 14 then Print("Tap to Build Tower")
Step3DPhysicsWorld()
Sync()
loop
Function SpawnEnemy()
ThisEnemy = CreateObjectBox(10,10,10) : SetObjectColor(ThisEnemy,255,0,0,255)
SetObjectCastShadow(ThisEnemy,1)
SetObjectPosition(ThisEnemy,300,10,Random(0,4)*32)
Create3DPhysicsKinematicBody(ThisEnemy)
AddEnemy as Enemy
AddEnemy.Health = 30 : AddEnemy.ID = ThisEnemy
Enemies.Insert(AddEnemy)
EndFunction
Function DoEnemies()
For x = Enemies.Length to 0 Step -1
ThisEnemy = Enemies[x].ID
MoveObjectLocalX(ThisEnemy,-1)
If GetObjectX(ThisEnemy) <= -16.0
If Cash >= 10 then DEC Cash, 10
Delete3DPhysicsBody(ThisEnemy)
DeleteObject(ThisEnemy)
Enemies.Remove(x)
EndIf
Next X
EndFunction
Function DoTowers()
If GetPointerPressed() and Towers.Length < 14 and Cash >= 10
DEC Cash, 10
ThisTower = CreateObjectSphere(20,10,10)
SetObjectCastShadow(ThisTower,1)
Empty = 0
Repeat //Random Placement into empty Tile
ThisX = Random(0,2) : ThisZ = Random(0,4)
If Board[ThisX,ThisZ] = 0
Empty = 1
Board[ThisX,ThisZ] = ThisTower
EndIf
Until Empty = 1
SetObjectPosition(ThisTower,ThisX*32,10,ThisZ*32)
AddTower as Tower
AddTower.ID = ThisTower
AddTower.RateOfFire# = 5.0
AddTower.NextShot# = Timer()
Towers.Insert(AddTower)
EndIf
If Towers.Length > -1
For x = 0 to Towers.Length
If Towers[x].NextShot# <= Timer()
ThisTower = Towers[x].ID
ThisShot = CreateObjectSphere(5,5,5)
Create3DPhysicsKinematicBody(ThisShot)
SetObjectShapeSphere(ThisShot)
SetObjectCastShadow(ThisShot,1)
SetObjectPosition(ThisShot,GetObjectX(ThisTower),GetobjectY(ThisTower),GetObjectZ(ThisTower))
Towers[x].NextShot# = Timer() + Towers[x].RateOfFire#
Shots.Insert(ThisShot)
Endif
Next x
EndIf
EndFunction
Function DoShots()
Vec3 = CreateVector3()
For x = Shots.Length to 0 Step -1
ThisShot = Shots[x]
MoveObjectLocalX(ThisShot,0.5)
If GetObjectX(ThisShot) >= 300
Delete3DPhysicsBody(ThisShot)
DeleteObject(ThisShot)
Shots.Remove(x)
ElseIf Enemies.Length > -1
For Enemy = Enemies.Length to 0 Step -1
ThisEnemy = Enemies[Enemy].ID
If GetObjects3DPhysicsContactPositionVector( ThisShot, ThisEnemy, Vec3 ) = 1
Enemies[Enemy].Health = Enemies[Enemy].Health-10
If Enemies[Enemy].Health <= 0
INC Cash, 10
Delete3DPhysicsBody(ThisEnemy)
DeleteObject(ThisEnemy)
Enemies.Remove(Enemy)
EndIf
Delete3DPhysicsBody(ThisShot)
DeleteObject(ThisShot)
Shots.Remove(x)
Exit
EndIf
Next Enemy
EndIf
Next x
EndFunction
Function MakeBoard()
Toggle = 1
For x = 0 to 9
For z = 0 to 4
Tile = CreateObjectBox(32,4,32) : SetObjectPosition(Tile,x*32,-2,z*32)
SetObjectReceiveShadow(Tile,1)
If Toggle = 1 Then SetObjectColor(Tile,0,255,0,255) Else SetObjectColor(Tile,0,192,0,255)
Toggle = -Toggle
Next z
Next x
EndFunction
If you make the Towers Kinematic Bodies, you can use a similar "collision" routine for Enemy vs Towers (in DoEnemies()). Ie, that part...
For Enemy = Enemies.Length to 0 Step -1
ThisEnemy = Enemies[Enemy].ID
If GetObjects3DPhysicsContactPositionVector( ThisShot, ThisEnemy, Vec3 ) = 1
Enemies[Enemy].Health = Enemies[Enemy].Health-10
If Enemies[Enemy].Health <= 0
INC Cash, 10
Delete3DPhysicsBody(ThisEnemy)
DeleteObject(ThisEnemy)
Enemies.Remove(Enemy)
EndIf
Delete3DPhysicsBody(ThisShot)
DeleteObject(ThisShot)
Shots.Remove(x)
Exit
EndIf
Next Enemy
...using the almighty
GetObjects3DPhysicsContactPositionVector().
otherwise, sorry i didn't try your method. once i find something that works, i tend to stick with it
meanwhile, that would be considered "brute force" in checking each shot vs all enemies (until it hits one). the whole thing can be simplified setting linear velocities for enemies and shots (once) vs MoveObjectLocalX() each frame and simply checking for Contact(s).
alas, i wanted this to remain similar to what i think you were doing. lucky for us, Brute Force works fine for smaller stuff like this