You can use the following as a scaffold for your program:
gosub init_Xcol
Do
`monster AI
gosub monster_AI
`monster collision
grav# = XCol(monster,ground,50.0,50.0,grav#)
`player controls
gosub control_player
`player collision
grav2# = XCol(player,ground,50.0,50.0,grav2#)
sync
Loop
control_player:
set cursor 0,0
print "Player Health: ",playerhealth
print "Monster mode: ",bmode
`check keyboard / joystick
If upkey() or joystick up() then move object player,playerspeed#
If downkey() or joystick down() then move object player,-playerspeed#
If leftkey() or joystick left() then turn object left player,0.5
If rightkey() or joystick right() then turn object right player,0.5
if (spacekey()=1 or joystick fire D()) and jumping=0
grav2#=5
jumping=1
endif
`get player position
px# = object position x(player)
py# = object position y(player)
pz# = object position z(player)
`orient camera for 3rd person view
position camera px#,py#,pz#
set camera to object orientation player
`comment out this line for 1st person view
move camera -100
return
monster_AI:
`get player and monster locations
mx# = object position x(monster)
my# = object position y(monster)
mz# = object position z(monster)
px# = object position x(player)
py# = object position y(player)
pz# = object position z(player)
radius# = 300
`enter battle mode if the monster and player are close enough
If (mx#-px#)*(mx#-px#)+(my#-py#)*(my#-py#)+(mz#-pz#)*(mz#-pz#)<=(radius#*radius#)
print "Battle mode"
gosub battle_mode
else
print "Quiescent state"
bmode = 0
EndSequence = 1
endif
return
battle_mode:
If EndSequence = 1
`Progress in flowchart
stat = rnd(99)+1
bmode2 = bmode
`bmode = 0 - Just entered battle mode
`bmode = 1 - attack
`bmode = 2 - run
`bmode = 3 - dodge
If bmode2 = 0 and stat>40 then bmode = 2 : waypoint = 0
If bmode2 = 0 and stat<=40 then bmode = 1
If bmode2 = 1 then bmode = 3 : grav# = 5
If bmode2 = 2 and stat>50 then bmode = 1
If bmode2 = 2 and stat<=50 then bmode = 3 : grav# = 5
If bmode2 = 3 then bmode = 2 : waypoint = 0
EndSequence = 0
else
If bmode = 1
`configure bullet
If shoot = 0 then show object bullet : position object bullet,mx#,my#,mz# : point object bullet,px#,py#,pz# : shoot = 100
If shoot > 0 then dec shoot : move object bullet,BulletSpeed#
bx# = object position x(bullet)
by# = object position y(bullet)
bz# = object position z(bullet)
`If the bullet collides with the player
If (bx#-px#)*(bx#-px#)+(by#-py#)*(by#-py#)+(bz#-pz#)*(bz#-pz#)<=(2500) then shoot = 0 : dec playerhealth,damage
`If the bullet expires
If shoot = 0 then EndSequence = 1 : hide object bullet : position object bullet,0,-1000000,0
endif
If bmode = 2
`find next waypoint
wx# = waypoints(waypoint,1)
wy# = waypoints(waypoint,2)
wz# = waypoints(waypoint,3)
point object monster,wx#,wy#,wz#
`select next waypoint
If (mx#-wx#)*(mx#-wx#)+(my#-wy#)*(my#-wy#)+(mz#-wz#)*(mz#-wz#)<=(runspeed#*runspeed#) then inc waypoint
move object monster,runspeed#
`finish running
If waypoint = maxpts then EndSequence = 1
endif
If bmode = 0 then EndSequence = 1
endif
return
init_Xcol:
`create level
set camera range 10,100000
global monster
playerhealth = 100
ground = 1
player = 2
monster = 3
bullet = 4
make object sphere ground,10000
position object ground,0,0,0
make object cube player,50
make object sphere monster,50
make object sphere bullet,100
scale object bullet,50,5,50
position object player,1000,5000,1000
position object monster,1000,5000,1000
maxpts = 10
DIM waypoints(maxpts,3)
`set waypoints here
global endsequence
global bmode
bulletspeed# = 5
runspeed# = 1.6
playerspeed# = 1
damage = 10
`number of checks
`the lower this number is, the more off the collisions will be vs. any rotated object.
`also, the lower the number, the more speed it runs at.
`lowest for rotated collision is 4(non rotated/box collision) max is 360, but 360 is WAAAY slow
`I'd advide is you play with this number to keep with a multiple of 4
global checks as integer
global angwidth as integer
global jumping as integer
checks=12
if checks<4 then checks=4
if checks>360 then checks=360
`width of the angles
angwidth=360/checks
`make arrays for collision data
dim ang#(checks-1,2)
dim sort#(checks-1,2)
return
function Xcol(c as integer, testobj as integer , charht as float , radius as float, grav#)
`XCollision - by Kensupen and Lodikecat
`Edited by Calcyman to work as a function
`get positions again
cx#=object position x(c)
cz#=object position z(c)
`Get your old height
oldht#=object position y(c)
`calc new height using intersect object from the old height down charht# units
sub#=intersect object(testobj,cx#,oldht#,cz#,cx#,oldht#-(charht*2.0),cz#)
ht#=(oldht#+charht)-sub#
if sub#=0 then ht#=charht
`do some gravity
grav#=grav#-0.05
`if you are going up a ramp
if oldht#+grav#<ht#
`end jump
If bmode = 3 and c = monster then endsequence = 1
grav#=0.0
jumping=0
position object c,cx#,ht#,cz#
else
`if you are falling
ht#=oldht#+grav#
position object c,cx#,ht#,cz#
endif
If grav#>0
`get positions again
cx#=object position x(c)
cz#=object position z(c)
`Get your old height
oldht#=object position y(c)
`calc new height using intersect object from the old height up charht# units
sub#=intersect object(testobj,cx#,oldht#,cz#,cx#,oldht#+(charht*2.0)+(grav#),cz#)
ht#=(oldht#-charht)+sub#
`if you are hitting a ceiling
if oldht#+grav#<ht#
grav#=-2.0
jumping=0
position object c,cx#,ht#-charht,cz#
else
`if you are flying
ht#=oldht#+grav#
position object c,cx#,ht#,cz#
endif
endif
`make 72 collision points. You can use more or less, but this number seems to work good.
`These are vectors every 5 degrees from the camera position out.
`They return the distance when they hit an object
cy# = object position y(c)
for x=0 to checks-1
chx#=newxvalue(cx#,x*angwidth,100)
chz#=newzvalue(cz#,x*angwidth,100)
ang#(x,1)=intersect object(testobj,cx#,cy#,cz#,chx#,cy#,chz#)
if ang#(x,1)=0 then ang#(x,1)=999999
ang#(x,2)=x*angwidth
sort#(x,1)=ang#(x,1)
sort#(x,2)=ang#(x,2)
next x
`sort the array to find the closest object and it's degrees
for x=0 to checks-2
for y=x+1 to checks-1
if ang#(x,1)>ang#(y,1)
temp#=ang#(x,1)
temp2#=ang#(x,2)
ang#(x,1)=ang#(y,1)
ang#(x,2)=ang#(y,2)
ang#(y,1)=temp#
ang#(y,2)=temp2#
endif
next x
next y
`This is the closest wall and what degrees you would face to see it
`find +-90 degrees from the closest one for when you walk into a corner so it doesn't shake
prev=wrapvalue(ang#(0,2)-90)/angwidth
nxt=wrapvalue(ang#(0,2)+90)/angwidth
newd#=radius-ang#(0,1)
newa#=wrapvalue(ang#(0,2)-180)
newd1#=radius-sort#(prev,1)
newa1#=wrapvalue(sort#(prev,2)-180)
newd2#=radius-sort#(nxt,1)
newa2#=wrapvalue(sort#(nxt,2)-180)
`if you are less than radius from a wall, push you out to 20 from it
if ang#(0,1)<radius and ang#(0,1)>0.0
repx#=newxvalue(cx#,newa#,newd#)
repz#=newzvalue(cz#,newa#,newd#)
position object c,repx#,cy#,repz#
endif
cx#=object position x(c)
cz#=object position z(c)
`this is if you are coming into a corner, this pushes you sideways
if sort#(prev,1)<radius and sort#(prev,1)>0.0
repx1#=newxvalue(cx#,newa1#,newd1#)
repz1#=newzvalue(cz#,newa1#,newd1#)
position object c,repx1#,cy#,repz1#
endif
cx#=object position x(c)
cz#=object position z(c)
`and the other way. above is left, this is right
if sort#(nxt,1)<radius# and sort#(nxt,1)>0.0
repx2#=newxvalue(cx#,newa2#,newd2#)
repz2#=newzvalue(cz#,newa2#,newd2#)
position object c,repx2#,cy#,repz2#
endif
`terminal velocity
IF ABS(grav#)=>20 then grav#=SGN(grav#)*20
endfunction grav#
It handles your flowchart, bullet control, movement, jumping and collision.
I've commented every few lines of code, so you should be able to understand it.
Set the waypoints in the array to set the monster's path.
Load an object instead of making a large sphere to use custom terrain.
Controls:
Arrowkeys - move player
Spacebar - jump
Good luck,
Calcyman
The optomist's right, The pessimist's right.