@No Time To Code
Quote: "You could always assemble the whole thing in an external 3d modeller"
Sometimes I forget the obvious!
It's the same principal as adding all the trees as limbs and then creating 1 object. The advantage of using the modeling program, of course, is that in a 3d modeling program, you can place things where and how you want with relative ease and save it all as one object. By setting collision to polygons on the one object, the collision will only occur when those individual faces intersect with another object set for collision or a ray (if you are using Sparky's DLL).
Last year, someone was trying to figure out a way to have hundreds of zombies attack a player and also have hundreds of trees/houses and such while still maintaining playability and still have collision detection. I wrote them up an example of a way to accomplish that which is right along the sames lines as what we've been discussing here.
In the example that follows, there are 300 trees (green boxes), 200 zombies (cones), 1 matrix, and 1 player (sphere). The trees are all made into one object and the collision is set to polygons for that. Now, with so many zombies, having all 200 set up for collision detection can be a real resource eater. So I figured, If I have to have a loop where I need to move each zombie, I can use a single invisible "feeler" to detect collision for each zombie as it's turn comes up in the loop.
This allows me to cut down on the number of collision boxes and collision checks and helps to improve performance. That means instead of 200 collision checks for each movement of a single zombie (200x200) I have 1 collision check for each zombie that moves. Combining this with hiding those zombies that aren't within the camera view, performance improves again. And since all of the trees are 1 object, they don't have to be individually leafed through in the index chain as DB checks to see what needs to be rendered; and as one object, the collision check for polygons is faster than individual box or a sphere collision check if each tree was an individual object.
Anyway, here is that example. Take a careful look through the code and try to see what I did. The program asks you to input a sync rate at the beginning. This was for testing purposes. I wanted to see what the highest rate was I could enter that would be maintained. On my machine, the fastest that this runs is at about 132 FPS. But a sync rate of 60 or even 40 is quite reasonable.
Use the mouse to steer. Use the up and down keys to move the red sphere. The white cones (zombies) will try to swarm you. They will try and avoid trees. If you hit a tree, you will stop, so you'll have to manuever around them.
remstart
==============================================================
= Title : Multiple Collision Objects
= Author : latch
= Date : 07/06/2008
= Update :
= Version:
==============================================================
Comments This demonstrates a method of handling multiple
object collisions using DBC native commands.
This example uses a "feeler" object in front
of each zombie
==============================================================
remend
rem =============================================================
rem = SET UP DISPLAY
rem =============================================================
autocam off
set display mode 800,600,32
sync on
sync rate 0
hide mouse
rem =============================================================
rem = MAIN
rem =============================================================
_main:
gosub _init
do
text 0,0,"Actual FPS "+str$(screen fps())
text 0,20,"Entered Sync Rate "+str$(srate)
text 0,40,"Polygons "+str$(statistic(1))
gosub _move_camera
gosub _move_zombies
sync
loop
end
rem =============================================================
rem = SUBROUTINES - PROCEDURES
rem =============================================================
_init:
randomize timer()
input "Enter Sync Rate :";srate
sync rate srate
gosub _terrain:
gosub _environment_objects
gosub _zombies
gosub _player
gosub _feeler
position camera matx#/2,200,matz#/2
xrotate camera 60
ink rgb(255,255,255),0
return
`----------------------------------------------------------------
_terrain:
mat=1
matx#=3000
matz#=3000
tilex=15
tilez=15
make matrix mat,matx#,matz#,tilex,tilez
randomize matrix mat,20
update matrix mat
return
`----------------------------------------------------------------
_environment_objects:
make object box 1,10,80,10
offset limb 1,0,0,40,0
make mesh from object 1,1
delete object 1
make object 1,1,0
x#=matx#/2
z#=matz#/2
position object 1,x#,0,z#
rem make one solid object out of square pillars
for lm=1 to 300
add limb 1,lm,1
lx#=rnd(int(matx#))-x#
lz#=rnd(int(matz#))-z#
ly#=get ground height(mat,lx#,lz#)
offset limb 1,lm,lx#,ly#,lz#
next lm
make mesh from object 1,1
delete object 1
make object 1,1,0
delete mesh 1
color object 1,rgb(0,100,0)
rem set the object collision status for these pillars
set object collision on 1
set object collision to polygons 1
sync
return
`----------------------------------------------------------------
_zombies:
rem create an array to hold the original starting positions
rem of the zombies so we can move them there if they go
rem out of view or we want to respawn them
totalzom=200
dim zposition(totalzom,2)
rem using cones to represent the zombies
for zomb=3000 to (3000+totalzom)-1
make object cone zomb,25
`make object sphere zomb,25
offset limb zomb,0,0,13,0
make mesh from object zomb,zomb
delete object zomb
make object zomb,zomb,0
delete mesh zomb
set object collision off zomb
`set object collision to boxes zomb
x#=rnd(int(matx#))
z#=rnd(int(matz#))
y#=get ground height(mat,x#,z#)
position object zomb,x#,y#,z#
rem store the zombie position
zposition(zomb-2999,0)=x#
zposition(zomb-2999,1)=y#
zposition(zomb-2999,2)=z#
next zomb
sync
return
`----------------------------------------------------------------
_move_camera:
yang#=wrapvalue(yang#+mousemovex())
yrotate camera yang#
newx#=newxvalue(object position x(pl),yang#,(upkey()-downkey())*3)
newz#=newzvalue(object position z(pl),yang#,(upkey()-downkey())*3)
`position camera newx#,camera position y(),newz#
oldx#=object position x(pl)
oldz#=object position z(pl)
position object pl,newx#,13+(get ground height(mat,newx#,newz#)),newz#
pbang=object collision(pl,1)
if pbang
position object pl,oldx#,13+(get ground height(mat,newx#,newz#)),oldz#
newx#=oldx#
newz#=oldz#
endif
rem position camera with player but a little behind
cx#=newxvalue(newx#,yang#,-80)
cz#=newzvalue(newz#,yang#,-80)
yrotate object pl,yang#
`position object pl,plx#,object position y(pl),plz#
position camera cx#,200+(get ground height(mat,cx#,cz#)),cz#
return
`----------------------------------------------------------------
_player:
pl=2
gosub _red
make object sphere pl,25
set object collision on pl
set object collision to boxes pl
texture object pl,red
position object pl,matx#/2,13,(matz#/2)+50
return
`----------------------------------------------------------------
_red:
red=2
bmp=1
while bitmap exist(bmp)
inc bmp
endwhile
create bitmap bmp,5,5
ink rgb(255,0,0),0
dot 0,0
`dot 1,1
get image red,0,0,1,2
delete bitmap bmp
return
`----------------------------------------------------------------
_move_zombies:
for zomb=3000 to (3000+totalzom)-1
rem check if the zombie is in screen
rem if so show it
rem if not hide it
if object in screen(zomb)=0
hide object zomb
rem reposition the zombie at it's "home" location
position object zomb,zposition(zomb-2999,0),zposition(zomb-2999,1),zposition(zomb-2999,2)
else
if object visible(zomb)=0 and object in screen(zomb)=1
show object zomb
endif
endif
rem check if zombie is hitting something
if object visible(zomb)=1
rem use the feeler object to place in front of a zombie
rem to check for collision - in this case 13 units in front
zyang#=object angle y(zomb)
zombx#=object position x(zomb)
zomby#=object position y(zomb)
zombz#=object position z(zomb)
newx#=newxvalue(zombx#,zyang#,13)
newz#=newzvalue(zombz#,zyang#,13)
position object feeler,newx#,zomby#,newz#
bang=object collision(feeler,0)
rem check against environment
if bang>0
choose=rnd(1)
if choose
yrotate object zomb,(wrapvalue(object angle y(zomb)+90))
else
yrotate object zomb,(wrapvalue(object angle y(zomb)-90))
endif
move object zomb,3
endif
rem point zombie towards player smoothly
zyang#=object angle y(zomb)
point object zomb,object position x(pl),object position y(zomb),object position z(pl)
newyang#=object angle y(zomb)
yrotate object zomb,zyang#
smoothang#=curveangle(newyang#,zyang#,20)
yrotate object zomb,smoothang#
move object zomb,2
position object zomb,object position x(zomb),13+(get ground height(mat,object position x(zomb),object position z(zomb))),object position z(zomb)
endif
next zomb
return
`----------------------------------------------------------------
_feeler:
feeler=3
make object cube feeler,25
hide object feeler
set object collision on feeler
set object collision to boxes feeler
return
`----------------------------------------------------------------
rem =============================================================
rem = FUNCTIONS
rem =============================================================
rem =============================================================
rem = DATA STATEMENTS
rem =============================================================
Enjoy your day.