Ok, I'll try and explain how the radar works.
In Monster Hunt, the radar is like a mini picture of the whole environment of the game. What I mean by that is, the radar is sized to encompass the entire world in one view. The radar doesn't scroll left or right, up or down. Its one view represents the whole world at once.
The radar could be coded to have only a small view, say 50 units in any direction around the player. Then as the player moves, the radar would scroll to reveal more of the "map." We'll stick to how monster hunt has it set up, to display the whole map at once.
Now that we've decided on the view size, we have to decide what we want displayed. When we decided that, we are going to draw shapes on a bitmap offscreen to represent the display. Then, we are going to capture the drawn bitmap as an image with the GET IMAGE command and paste that image as a texture onto a flat 3d object called a Plain in DarkBASIC. In the original Monster Hunt, a bitmap is loaded first that represents the radar's background. Then, only the Player and the Monster are drawn on the radar.
rem Load and create hud bitmaps.
Load Bitmap "Radar.bmp",2
Create Bitmap 1,50,50
These are the commands that load the background radar screen to bitmap screen 2 and create a 50 x 50 bitmap on bitmap screen 1. The 50 x 50 dimensions are important to note because this is the size we have to represent our entire world map on the radar as.
Later in the main loop we see:
Rem make radar
Copy Bitmap 2,1
set current bitmap 1
ink rgb(0,0,255),rgb(0,0,0)
PRX#=X#/200
PRZ#=50-(Z#/200)
Circle PRX#,PRZ#,1
ink rgb(255,0,0),rgb(0,0,0)
MRX#=mX#/200
MRZ#=50-(mZ#/200)
Circle MRX#,MRZ#,1
Get image 200,0,0,50,50
set current bitmap 0
texture object 200,200
rem - add this line to rotate radar for better orientation
zrotate object 200,cay#
ink rgb(255,128,128),rgb(0,0,0)
This first line copies bitmap 2 to bitmap 1 (the radar background onto the bitmap we will draw our circles on).
Next it sets the bitmap we want to draw on (bitmap 1). Then we change the color to blue. The variables PRX# and PRZ# represent the player x and z coordinates for the radar. These coordinates are pulled out of the player's X and Z position in the 3d world. We have to take these coordinates and apply them to our 2d radar so we can draw a circle in the right spot. Since we know the matrix size in 10000, we divide 10000/200 to scale our coordinates down to 50 to fit on our radar bitmap (remember when I said 50 x 50 would be important?). I mentioned in a previous post that the Flip Bitmap command could be used to orient that z position on the radar so it isn't upside down, well, Monster Hunt handles this with
PRZ#=50-(Z#/200)
Because the height of our bitmap goes from the top 0 to the bottom 50, and z in our 3d world goes the opposite from this, the 50-(z#/200) will ensure that the z coordinates from the 3d world will be positioned correctly on the 2d radar map.
Once we have the coordinates of our player object and they are converted to radar size, we draw a circle at the PRX# and PRZ# coordinates. We then change the ink color to red, and do the same exact process for the Monster (MRX# and MRZ#).
I added a line to the original routine :
This line rotates the radar image to maintain the radar orientation with the world.
On to The Demo Code I wrote earlier:
rem ------ RADAR ----------------------
rem ------ Set Up Display -------------
autocam off
set display mode 800,600,16
sync on
randomize timer()
rem ------ Floor
make matrix 1,200,200,20,20
rem ------ Radar Object
make object plain 100,3,3
position object 100,-6,4.5,10
lock object on 100
rem ------ random spheres
x#=0:y#=5:z#=0
for obj = 1 to 6
make object sphere obj,10
position object obj,rnd(150),y#,rnd(150)
next obj
rem ------ position camera
position camera 100,150,-100
point camera 100,0,100
rem ------ Draw bitmap offscreen
create bitmap 1,200,200
set current bitmap 1
ink RGB(255,0,0),0
for obj = 1 to 6
circle object position x(obj), object position z(obj),10
next obj
flip bitmap 1
rem ------ paste bitmap onto plain
get image 1,0,0,200,200
set current bitmap 0
texture object 100,1
sync
This bit of code is an example of how to have multiple items showing up on the radar at once (your original question). I used the same principles as Monster Hunt, but did a little adaptation for demo purposes.
I wanted to make things easier on myself, so I made a matrix that was 200 x 200 and I decided to make my radar bitmap 200 x 200 also so I didn't have to do any conversions for size when I bring over the coordinates of my objects.
So the position of my objects (spheres) would change every time the program was run, I used a random value for my x and z positions after I created the objects. I did this all in one loop:
rem ------ random spheres
x#=0:y#=5:z#=0
for obj = 1 to 6
make object sphere obj,10
position object obj,rnd(150),y#,rnd(150)
next obj
Now, the rest of the code uses the same method as Monster Hunt to set up the radar display; I draw an offscreen bitmap, I point to the bitmap, I create a loop to get all of my spheres x and z, then I draw the circles on the bitmap at the locations of x and z. I use the Flip Bitmap command to turn everything rightside up (remember, the z on the bitmap will be top 0 to bottom 200 which is opposite from my 3d world).
You can apply all this information to modify Alien Hunter.
You wanted to add health packs. Ok, let's say there are ten health packs. First thing to do would be to decide on a range of object numbers that will be health packs. For this example, we'll reserve 1000 to 1009 specifically. So from now on, whenever there is an object with a number from 1000 to 1009, we know that it is a health pack.
Next, we want to either load an .x object for the health pack or we will create it out of a primative. For this example, we'll just create cubes.
We will create a subroutine (procedure) to handle the creation of our helath packs. We want to call this routine from within the PlacePlayer routine. You don't have to do it this way, but I am, because I want everything to be reset every time a new battle begins, and the PlacePlayer routine happens at the start of every battle.
Here is the subroutine:
PlaceHealthPacks:
randomize timer()
for hp=1000 to 1009
if object exist(hp) <> 1
make object cube hp,20
color object hp,RGB(0,255,0)
hpx#=rnd(10000)
hpz#=rnd(10000)
hpy#=get ground height(1,hpx#,hpz#)
while DecoCollide(hpx#,hpy#,hpz#) = 1
hpx#=rnd(10000)
hpz#=rnd(10000)
hpy#=get ground height(1,hpx#,hpz#)
endwhile
position object hp,hpx#,hpy#,hpz#
endif
if object exist(hp) = 1
hpx#=rnd(10000)
hpz#=rnd(10000)
hpy#=get ground height(1,hpx#,hpz#)
while DecoCollide(hpx#,hpy#,hpz#) = 1
hpx#=rnd(10000)
hpz#=rnd(10000)
hpy#=get ground height(1,hpx#,hpz#)
endwhile
position object hp,hpx#,hpy#,hpz#
endif
next hp
return
This code is just a variation of my demo code. I just had to add a reference to the collision routine that is setup inside Monster Hunt so the health packs don't appear in the middle of the pillars. I just did it the same way it's done in the PlacePlayer routine. Once DecoCollide is called and the HPX# HPZ# and HPY# are ok, then we can position the object.
This routine also does the initial creation of all the health packs. There are 2 checks to see whether the healthpack exists or not. If it doesn't exist (it's either being created for the first time, or maybe it disappears after the player uses it), it will be created. If it does exist, it will just be repositioned.
Now the only thing to do is to draw the health packs on the radar:
Rem make radar
Copy Bitmap 2,1
set current bitmap 1
ink rgb(0,0,255),rgb(0,0,0)
PRX#=X#/200
PRZ#=50-(Z#/200)
Circle PRX#,PRZ#,1
ink rgb(255,0,0),rgb(0,0,0)
MRX#=mX#/200
MRZ#=50-(mZ#/200)
Circle MRX#,MRZ#,1
rem add health packs to radar
ink RGB(0,255,0),0
for hp = 1000 to 1009
hpx#=object position x(hp)/200
hpz#=50-(object position z(hp)/200)
circle hpx#,hpz#,1
next hp
Get image 200,0,0,50,50
set current bitmap 0
texture object 200,200
zrotate object 200,cay#
ink rgb(255,128,128),rgb(0,0,0)
That small section in the middle does it. We just set up a loop to cycle through the health packs and draw the circles just like we did for the Player and the Monster.
Here's the complete modified Monster Hunt code. You should already have all of the media:
Rem * Title : Monster AI
Rem Setup sync
rem -----------------------------------
rem - Monster Hunt Tutorial
rem - modified radar
rem - Modified by Latch Grapple
rem - August 28,2006
rem -----------------------------------
Sync On
Sync Rate 30
Draw to front
Backdrop on
Set camera range 1,3000
Autocam off
Hide mouse
Fog on
Fog distance 3000
Fog color RGB(128,128,128)
Color Backdrop RGB(128,128,128)
Rem make matrix
Make matrix 1,10000,10000,20,20
Rem texture matrix
Load image "grass09.bmp",1
Prepare matrix texture 1,1,1,1
Fill matrix 1,0,1
rem Make Gun
Make object cylinder 1,2
XRotate Object 1,90
Fix object pivot 1
Scale object 1,100,100,500
position object 1,0,-7,15
Lock object on 1
rem make HUD
Make object Plain 200,1,1
position object 200,-2.7,1.9,4
Lock object on 200
ghost object on 200
Make object Plain 201,1,1
position object 201,2.7,1.9,4
Lock object on 201
ghost object on 201
Load image "score.bmp",201
Texture object 201,201
rem Load and create hud bitmaps.
Load Bitmap "Radar.bmp",2
Create Bitmap 1,50,50
rem fire texture
Load Image "fire.bmp",2
rem Make Bullet
Make Object Sphere 2,2
texture object 2,2
Hide Object 2
rem Make MonsterBullet
Make Object Sphere 102,2
texture object 102,2
Hide Object 102
rem Make Explosion
Make Object Sphere 30,20
texture object 30,2
ghost object on 30
Hide Object 30
Make Object Sphere 31,20
texture object 31,2
ghost object on 31
Hide Object 31
rem Make Monster Explosion
Make Object Sphere 130,20
texture object 130,2
ghost object on 130
Hide Object 130
Make Object Sphere 131,20
texture object 131,2
ghost object on 131
Hide Object 131
rem load particles
For x = 0 to 10
Make object plain x+10,5,5
Texture object x+10,2
Set object x+10,1,0,0
Ghost object on x+10
Hide object x+10
Next x
rem load Monsterparticles
Load Image "fire.bmp",2
For x =100 to 110
Make object plain x+10,5,5
Texture object x+10,2
Set object x+10,1,0,0
Ghost object on x+10
Hide object x+10
Next x
rem intialize particle counter
Pn=10
MPn=110
rem load sounds
Load sound "crickets.wav",1
Loop sound 1
Load 3Dsound "fireball2.wav",2
Load 3Dsound "fireball2.wav",102
Load 3Dsound "Explode.wav",3
Load 3Dsound "Explode.wav",103
rem Randomize the matrix
randomize matrix 1,125
rem create decorative objects
load image "cottag02.bmp",300
t=300
For x = 1 to 9
For z = 1 to 9
Make object cube t,100
Scale object t,100,600,100
y = get ground height(1,x*1000,z*1000)
position object t,x*1000,y+275,z*1000
texture object t,300
scale object texture t,1,-6
inc t
next z
next x
Rem Load Target
Load object "idle.x",3
Append Object "Walk.x",3,21
Yrotate object 3,180
Fix Object Pivot 3
Loop Object 3
mX# = 5000
mZ# = 5000
mY# = Get Ground Height(1,5000,5000)
X# = 5500
Y# = Get Ground Height(1,5500,5500)
Z# = 5500
MonsterScore=0
PlayerScore=0
Gosub PlaceMonster
Gosub PlacePlayer
Rem Main loop
Do
set cursor 550,20
print "MScore: ",MonsterScore
set cursor 550,40
print "PScore: ",PlayerScore
print total object frames(3)
oldcAY# = cAY#
oldcAX# = cAX#
oldX#=X#
oldY#=Y#
oldZ#=Z#
cAY# = WrapValue(cAY#+MousemoveX()*0.2)
cAX# = WrapValue(cAX#+MousemoveY()*0.2)
caZ# = Camera angle Z()
Rem Control input for camera
If Upkey()=1
XTest# = Newxvalue(X#,cAY#,7)
ZTest# = Newzvalue(Z#,cAY#,7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
If Downkey()=1
XTest# = Newxvalue(X#,Wrapvalue(cAY#-180),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#-180),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
If Leftkey()=1
XTest# = Newxvalue(X#,Wrapvalue(cAY#-90),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#-90),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
If Rightkey()=1
XTest# = Newxvalue(X#,Wrapvalue(cAY#+90),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#+90),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
Rem Rotate camera
cTestX#=WrapValue(cAX#-180)
if cTestX# > 225 then cAX#=45
if cTestX# < 135 then cAX#=315
YRotate camera CurveAngle(cAY#,oldcAY#,24)
XRotate camera CurveAngle(cAX#,oldcAX#,24)
Y# = Get ground height(1,X#,Z#)+35
rem collision detection
if DecoCollide(X#,Y#,Z#) = 1
X#=oldX#
Y#=oldY#
Z#=oldZ#
Endif
Rem Position Camera
Position Camera X#,Y#,Z#
Rem Position Listener
Position Listener X#,Y#,Z#
Rotate Listener 0,cAY#,0
Rem Shoot bullet
if Mouseclick()=1 and Explode =0
if BulletLife=0 or BulletLife<50
Position object 2,X#,Y#-7,Z#
Set object to camera orientation 2
BulletLife =120
show object 2
Loop sound 2
Endif
Endif
If BulletLife > 0 then Gosub ShootBullet
If MonsterBulletLife > 0 then Gosub MonsterShootBullet
If Explode > 0 then Gosub ExplodeRocket
If MonsterExplode > 0
Gosub MonsterExplodeRocket
else
Gosub MonsterAI
Endif
Rem make radar
Copy Bitmap 2,1
set current bitmap 1
ink rgb(0,0,255),rgb(0,0,0)
PRX#=X#/200
PRZ#=50-(Z#/200)
Circle PRX#,PRZ#,1
ink rgb(255,0,0),rgb(0,0,0)
MRX#=mX#/200
MRZ#=50-(mZ#/200)
Circle MRX#,MRZ#,1
rem add health packs to radar
ink RGB(0,255,0),0
for hp = 1000 to 1009
hpx#=object position x(hp)/200
hpz#=50-(object position z(hp)/200)
circle hpx#,hpz#,1
next hp
Get image 200,0,0,50,50
set current bitmap 0
texture object 200,200
zrotate object 200,cay#
ink rgb(255,128,128),rgb(0,0,0)
Rem Refresh Screen
Sync
Loop
Rem check for collision with wall decorations
Function DecoCollide(X#,Y#,Z#)
for u = 1 to 9
for v = 1 to 9
if X#>u*1000-60
if X#<u*1000+60
if Z#>v*1000-60
if Z#<v*1000+60
if Y# < Get ground height(1,u*1000,v*1000)+575
Collide=1
Exitfunction Collide
endif
endif
endif
endif
endif
next v
next u
Collide=0
Endfunction Collide
Rem Shoot player bullet
ShootBullet:
Dec BulletLife
Move object 2,12
bX#=Object position X(2)
bY#=Object position Y(2)
bZ#=Object position Z(2)
inc Pn
if Pn=21 then Pn=10
Scale object Pn,100,100,100
Position object Pn,bX#,bY#,bZ#
point object Pn,X#,Y#,Z#
Zrotate object Pn,rnd(180)
Show object Pn
for x = 1 to 10
scale object int((Wrapvalue((Pn-9+x)*36))/36)+10,100+x*25,100+x*25,100+x*25
set cursor 10,10
next x
if bY# < Get Ground height(1,bX#,bZ#) then BulletLife=0
Position sound 2,bX#,bY#,bZ#
set cursor 10,10
if Sqrt((mX# - bX#)^2 + (mY#+25 - bY#)^2 + (mZ# - bZ#)^2) <20
Gosub PlaceMonster
inc PlayerScore
MonsterBulletLife = 1
BulletLife=0
endif
if DecoCollide(bX#,bY#,bZ#) = 1 then BulletLife = 0
if BulletLife = 0
Hide object 2
stop sound 2
for x=10 to 20
hide object x
next x
Explode = 20
endif
Return
Rem Explode bullet
ExplodeRocket:
Position object 30,bX#,bY#,bZ#
Show object 30
Position object 31,bX#,bY#,bZ#
Show object 31
EScale=20*(30-Explode)
Scale object 30,EScale,EScale,EScale
Yrotate object 30,WrapValue(Explode*37)
Scale object 31,EScale/1.5,EScale/1.5,EScale/1.5
Yrotate object 31,WrapValue(359-Explode*37)
Dec Explode
If Explode = 0 then hide object 30: Hide object 31
If Explode=18
position sound 3,bX#,bY#,bZ#
play sound 3
endif
If Explode < 15 then position sound 3,X#,Y#,Z#
Return
Rem Explode monster bullet
MonsterExplodeRocket:
Position object 130,MbX#,MbY#,MbZ#
Show object 130
Position object 131,MbX#,MbY#,MbZ#
Show object 131
EScale=20*(30-MonsterExplode)
Scale object 130,EScale,EScale,EScale
Yrotate object 130,WrapValue(MonsterExplode*37)
Scale object 131,EScale/1.5,EScale/1.5,EScale/1.5
Yrotate object 131,WrapValue(359-MonsterExplode*37)
Dec MonsterExplode
If MonsterExplode = 0 then hide object 130: Hide object 131
If MonsterExplode=18
position sound 103,X#,Y#,Z#
play sound 103
endif
If MonsterExplode < 15 then position sound 103,X#,Y#,Z#
Return
Rem Simple AI for guided monster misile
MonsterAI:
Point object 3,X#,Y#,Z#
If AvoidDeco >0
mA# = Object Angle Y(3)
Dec AvoidDeco
Yrotate object 3,WrapValue(mA#+AvoidDeco*60)
endif
Rem Position Monster at new location
Position Object 3,mX#,mY#,mZ#
Rem check distance from player
PDist=Sqrt((mX# - X#)^2 + (mY#+25 - Y#)^2 + (mZ# - Z#)^2)
Rem If the player is within range shoot bullet
if PDist<1500
if MonsterBulletLife=0 or MonsterBulletLife < 500-Pdist/10
Point object 3,X#,Y#-25,Z#
If BulletAvoidDeco > 0
CornerAim = Rnd(1)
mA# = object angle Y(3)
if CornerAim = 0 then Yrotate Object 3,WrapValue(mA#+BulletAvoidDeco*10)
if CornerAim = 1 then Yrotate Object 3,WrapValue(mA#+BulletAvoidDeco*-16)
Dec BulletAvoidDeco
Endif
If ShootUp > 0
mA# = object angle X(3)
XRotate Object 3,WrapValue(mA#+ShootUp*-8)
Dec ShootUp
Endif
Position object 102,mX#,mY#+25,mZ#
Set object to object orientation 102,3
MonsterBulletLife =500
show object 102
Loop sound 102
Rem Play idle animation
Loop Object 3,0,20
Endif
Endif
if PDist>1000
Rem Store old location
OldmX# = mX#
OldmZ# = mZ#
OldmY# = mY#
Rem Play walking animation
Loop Object 3,21,46
Rem Move monster
Move Object 3,7
Rem Get new position
mX# = Object Position X(3)
mZ# = Object Position Z(3)
mY# = Get Ground Height(1,mX#,mZ#)
Rem Check for Decoration collision
If DecoCollide(mX#,mY#,mZ#) = 1 and AvoidDeco = 0
mX# = OldmX#
mZ# = OldmZ#
mY# = OldmY#
AvoidDeco = 3
Endif
Endif
Return
Rem Shoot Monster bullet
MonsterShootBullet:
Dec MonsterBulletLife
Move object 102,12
MbX#=Object position X(102)
MbY#=Object position Y(102)
MbZ#=Object position Z(102)
inc MPn
if MPn=121 then MPn=110
Scale object MPn,100,100,100
Position object MPn,MbX#,MbY#,MbZ#
Position sound 102,MbX#,MbY#,MbZ#
point object MPn,X#,Y#,Z#
Zrotate object MPn,rnd(180)
Show object MPn
for x = 1 to 10
scale object int((Wrapvalue((MPn-9+x)*36))/36)+110,100+x*25,100+x*25,100+x*25
next x
if MbY# < Get Ground height(1,MbX#,MbZ#)
MonsterBulletLife=0
ShootUp=3
endif
Pdist=Sqrt((X# - MbX#)^2 + (Y#+25 - MbY#)^2 + (Z# - MbZ#)^2)
if Pdist<50
GoSub PlacePlayer
MonsterBulletLife = 0
inc MonsterScore
endif
Rem guided missile
if Pdist <500+PlayerScore*100 and Pdist>250 then Point object 102,X#,Y#,Z#
if Pdist < 100 then point object 102,X#,Y#,Z#
if DecoCollide(MbX#,MbY#,MbZ#) = 1
MonsterBulletLife = 0
BulletAvoidDeco = BulletAvoidDeco + 2
Endif
if MonsterBulletLife = 0
Hide object 102
stop sound 102
for x=110 to 120
hide object x
next x
MonsterExplode = 20
endif
Return
PlaceMonster:
mX#=X#
mY#=Y#
mZ#=Z#
While Sqrt((X# - MX#)^2 + (Y#+25 - MY#)^2 + (Z# - MZ#)^2)<1000
mX#=rnd(10000)
mZ#=rnd(10000)
mY#= get ground height(1,mX#,mZ#)
If DecoCollide(mX#,mY#,mZ#) = 1
mX#=X#
mY#=Y#
mZ#=Z#
endif
EndWhile
Position object 3,mX#,mY#,mZ#
Return
PlacePlayer:
X#=mX#
Y#=mY#
Z#=mZ#
While Sqrt((X# - mX#)^2 + (Y#+25 - mY#)^2 + (Z# - mZ#)^2)<1000
X#=rnd(10000)
Z#=rnd(10000)
Y#= get ground height(1,X#,Z#)
If DecoCollide(X#,Y#,Z#) = 1
X#=mX#
Y#=mY#
Z#=mZ#
endif
EndWhile
Position camera X#,Y#,Z#
Point camera mX#,mY#,mZ#
rem add health packs
gosub PlaceHealthPacks
Return
PlaceHealthPacks:
randomize timer()
for hp=1000 to 1009
if object exist(hp) <> 1
make object cube hp,20
color object hp,RGB(0,255,0)
hpx#=rnd(10000)
hpz#=rnd(10000)
hpy#=get ground height(1,hpx#,hpz#)
while DecoCollide(hpx#,hpy#,hpz#) = 1
hpx#=rnd(10000)
hpz#=rnd(10000)
hpy#=get ground height(1,hpx#,hpz#)
endwhile
position object hp,hpx#,hpy#,hpz#
endif
if object exist(hp) = 1
hpx#=rnd(10000)
hpz#=rnd(10000)
hpy#=get ground height(1,hpx#,hpz#)
while DecoCollide(hpx#,hpy#,hpz#) = 1
hpx#=rnd(10000)
hpz#=rnd(10000)
hpy#=get ground height(1,hpx#,hpz#)
endwhile
position object hp,hpx#,hpy#,hpz#
endif
next hp
return
Enjoy your day.