This is a little FPS game I wrote. Ok it's 1600 lines long but then I did program my own models and animations.
It's a relatively straight forward FPS game. Shoot the guards before they kill you.
The guards wander around the map, if they see you they'll shoot you but you can dodge out the way pretty easily.
Controls are shown on the screen when you play the game.
Here's a screeny and then the code:
For those who have stumbled on to this but don't have access to DBC, I've attached an exe.
`Puprple Simplex - an FPS demo
`By 29 Games
`07 october 2010
`this program is an FPS style demo
`controls:
`mouse to look, wasd to move and strafe
`r to toggle run/walk, c to toggle crouch/stand, spacebar to jump
`lmb to shoot, press and hold rmb to reload
`+++++ GLOBAL ARRAYS
`map
dim blk#(1000,10) :`the vertex positions for the blocks that make up the map (block number, corners and top and btm sufaces)
dim blk_col(1000,3) :`colour of block, (block number, rgb colour)
dim table_data(4,4,11) :`array used to hold database information for map (row, column, block number)
`player
dim ply_pos#(2,3) :`old and new x, y, z positions of player
dim ply_fac#(2) :`direction player is facing: left and right and up and down
`enemies
dim way_points#(5,10,2) :`way point coordinates (figure number, way point number, coordinates)
dim f_c_wp(5) :`the current way point the figure is walking toward (figure number)
dim f_los(5) :`hold value for whether there is a line of sight between player and enemy
dim f_life(5) :`this is the life of the figure (figure number).
dim b_life(5) :`current life of bullet fired by enemy (each figure fires a sigle bullet at a time)
`++++++ SET UP
gosub GENERAL_SET_UP :`screen resolution, sync rate, camera range etc
gosub CONSTANTS :`sets any variable used that remain unchanged through out the games
gosub CREATE_MAP :`creates the map and writes map data to arrays
gosub CREATE_OBJECTS :`create and texture the various objects used in the game (except the map)
gosub STARTING_VARIABLES :`set the values of any variables that change through out the game
`++++++ MAIN LOOP
a_main_loop:
do
repeat
gosub ENEMY_ACTION :`deals with top level enemy AI and top level bullet
gosub OTHER_CONTROLS :`run, jump, crouch, shooting and reload
gosub MOVE_PLAYER :`forward, back, strafe and turn
gosub PLACE_CAMERA :`positions camera
gosub PRINT_STUFF :`prints information to screen
sync
until ply_life =< 0 or kills = num_figures
if kills = num_figures then gosub SUCCESS_OUTRO
if ply_life =< 0 then gosub FAILED_OUTRO
loop
end
`+++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++ SUB ROUTINES +++++++++++++++++++++++++++++++
`+++++++++++++++++++++++++++++++++++++++++++++++++++
GENERAL_SET_UP:
` set display mode 1024,768,16
sync on
sync rate 65
hide mouse
set camera range 1, 3000
fog on :`for fog distance and colour see STARTING_VARIABLES sub routine
randomize timer()
cls
return
CONSTANTS:
`map
usi = 30 :`unit size of map
num_blocks_max = 1000 :`maximum number of walls that make up the map
num_mtrx = 4 :`number of squares in matrix
num_rows = 4 :`size of database for map
num_cols = 4 :`size of database for map
num_items = 11 :`max number of walls etc allowed in each square
`gravity
grav# = 0.02
`player
`psiz# = player size as represented by a radius
`wspd# = walking speed, rspd# = running speed, mspd# = current forward movement speed, sspd# = strafe and back movement speed
`tspd# = turning speed, pspd# = pitching speed, jspd# = initial jump speed, step_up_spd# = like jump speed but for going up a step
`psht# = (standing height of player)/3
wspd# = 0.15
rspd# = 0.35
tspd# = 0.2
pspd# = 0.2
jspd# = 0.45
step_up_spd# = 0.125
psiz# = 1.5 :`note psiz# needs to be greater than 1.5, but needs to be scaled with movement so that camera does not go through a wall
psht# = 1.8 :`this is a value for when the player is standing. The actual height of the player is 3*psht#
pcht# = 0.9 :`this is a value for when the player is crouching. The actual height of the player is 3*pcht#
ply_f_view = 30 :`this is the player's feild of view, 30 degree left and right
cross_x# = screen width() / 2 :`screen x coordinate of cross hair
cross_y# = screen height() / 2 :`screen y coordinate of cross hair
max_ammo = 30 :`maximum ammo the player is allowed
max_ply_life = 100 :`maximum life (health of the player)
ply_dam = 21 :`damage the player does to the enemy
`figures (i.e. enemies)
num_figures = 4 :`number of enemy figures
f_hgt = 4 :`height of enemy figures
f_spd# = 0.07 :`speed with which enemy figures move
num_wp = 10 :`the number of way points in the enemy figure's patrol path
r_wp# = f_hgt :`if the figure is this distance from the cuurent way point, go to the next way point
f_f_view = 70 :`this is the enemies field of view, 60 degree left and right
restore _way_point_data :`write way point data for enemy figures to array
for i = 1 to num_figures
for j = 1 to num_wp
read x_w_p#, z_w_p# :`read way point data
way_points#(i,j,1) = x_w_p#*usi :`scale way point data (x coordinate)
way_points#(i,j,2) = z_w_p#*usi :`scale way point data (z coordinate)
next j
next i
max_b_life = 100 :`maximum life of each bullet fired by the enemy
b_size# = 3 :`radius of the bullet
b_spd# = 1.5 :`speed the bullet moves
b_dam = 26 :`damage bullet does to player
num_lp = 12 :`this is number divisions used when determining line of sight.
return
STARTING_VARIABLES:
`put here because fog is modified in FAILED_OUTRO sub routine
fog distance 200
fog color rgb(0, 0, 0)
`player
ply_pos#(2,1) = usi*0.10 :`starting x position
ply_pos#(2,2) = 0 :`starting y position
ply_pos#(2,3) = usi*3.1 :`starting z position
ply_fac#(1) = 0.0 :`starting mouse look direction (left right)
ply_fac#(2) = 0.0 :`starting mouse look direction (up down
mspd# = wspd# :`current foward and strafe speed
cur_jspd# = 0 :`current jump speed
cur_pht# = psht# :`current player height value
cur_ammo = max_ammo :`current ammo held by the player
ply_life = max_ply_life :`life (health) of the player
`flags
jump = 0 :`whether or not the player is jumping / falling
hit_surface = 0 :`whether or not the player has hit a top or bottom surface
sees = 0 :`whether or not an enemy can see the player
kills = 0 :`the number of enemy killed
`set enemy values
for i = 1 to num_figures
f_life(i) = 100 :`life (health)
f_c_wp(i) = rnd(9) + 1 :`starting way point
position object i, way_points#(i,f_c_wp(i),1),0.6*f_hgt,way_points#(i,f_c_wp(i),2) :`starting position of figures
b_life(i) = max_b_life :`set current bullet life to maximum
next i
return
DETERMINE_LINE_OF_SIGHT:
f_los(i) = 0 :`reset line of sight to zero (ie assume there is no line of sight)
`calculate perpendicular distances from player to enemy
distx# = ( object position x(i) - ply_pos#(2,1) ) / (num_lp-1)
disty# = ( object position y(i) + 0.4*f_hgt - ply_pos#(2,2)+2*cur_pht# ) / (num_lp-1)
distz# = ( object position z(i) - ply_pos#(2,3) ) / (num_lp-1)
los_point = 0
repeat
inc los_point :`move point along line of sight then determine collision with map
lpx# = (distx#*los_point) + ply_pos#(2,1)
lpy# = (disty#*los_point) + (ply_pos#(2,2)+2*cur_pht#)
lpz# = (distz#*los_point) + ply_pos#(2,3)
`determine which grid square point is in
pointcol = int(lpx#/usi) + 1
pointrow = int(lpz#/usi) + 1
`determine if point is within block
j = 0 : k = 0
`loop to check if there are any blocks to collide with in same square as point
repeat
inc k
`exit loop if square is empty (exit if datbase field is equal to zero)
if table_data(pointcol,pointrow,k) = 0 then exit
j = table_data(pointcol,pointrow,k) :`block ident (block that makes up the map)
`this determines if the point is within a block
if lpy# <= blk#(j,9) and lpy# => blk#(j,10)
if POINT_IN_ABCD(lpx#,lpz#, blk#(j,1),blk#(j,2), blk#(j,3),blk#(j,4), blk#(j,7),blk#(j,8), blk#(j,5),blk#(j,6)) = 1
f_los(i) = 0 :`point is within a block therefore there is no line of sight
exit :`exit inner loop if point is within block
else
f_los(i) = 1 :`there is a line of sight between enemy and player
endif
else
f_los(i) = 1 :`there is a line of sight between enemy and player
endif
until k => num_items
if f_los(i) = 0 then exit :`exit outer loop if point is within block
until los_point => num_lp - 1
return
ENEMY_ACTION:
for i = 1 to num_figures
`figure
if f_life(i) > 0
`if the player is within line of sight of the enemy then determine if the player is within the enemy's field of view
gosub DETERMINE_IF_ENEMY_SEES_PLAYER :`this determines if the player is within the enemy's field of view
if sees = 0
gosub MOVE_ENEMY :`move the enemy along it's "patrol" path
else
stop object i :`stop animation
point object i, ply_pos#(2,1), 0.6*f_hgt, ply_pos#(2,3) :`point figure at player
POSE_FIGURE(i,3) :`pose figure for shooting
`if bullet has maximum life then it is ready to be fired
if b_life(i) = max_b_life
gosub ENEMY_SHOOTS :`if the enemy sees the player then they will shoot
endif
endif
endif
`bullets
`if bullet life is zero or less, reset and hide bullet
if b_life(i) <= 0
b_life(i) = max_b_life
position object i+10, 0, 0, 0
hide object i+10
endif
if b_life(i) < max_b_life
b_life(i) = b_life(i) - 1
gosub MOVE_BULLETS
endif
next i
return
DETERMINE_IF_ENEMY_SEES_PLAYER:
`this determines if the player is within the enemie's field of view
`calculate angle between player and figure
opp# = ply_pos#(2,1) - object position x(i)
adj# = ply_pos#(2,3) - object position z(i)
angle = ACR_TAN(opp#,adj#)
`caculate difference between angle and facing of player
diff_angle_cw = wrapvalue(angle - object angle y(i)) :`clockwise
diff_angle_acw = wrapvalue(360 - (angle - object angle y(i))) :`anti clockwise
if diff_angle_cw < diff_angle_acw
diff_angle_smallest = diff_angle_cw
else
diff_angle_smallest = diff_angle_acw
endif
if diff_angle_smallest > f_f_view
sees = 0 :`player is not in enemy's field of view
else
gosub DETERMINE_LINE_OF_SIGHT
if f_los(i) = 1
sees = 1
else
sees = 0
endif
endif
return
MOVE_ENEMY:
`calculate range between object and way point
ran_to_way_p# = ( object position x(i) - way_points#(i,f_c_wp(i),1) )^2 + ( object position z(i) - way_points#(i,f_c_wp(i),2) )^2
`if figure is near way point go to the next way point
if ran_to_way_p# < r_wp# then f_c_wp(i) = f_c_wp(i) + 1
if f_c_wp(i) > num_wp then f_c_wp(i) = 1
`point figure at current way point and move toward figure it
point object i, way_points#(i,f_c_wp(i),1), 0.6*f_hgt, way_points#(i,f_c_wp(i),2)
move object i, f_spd#
loop object i, 1,61
return
ENEMY_SHOOTS:
position object i+10, limb position x(i,12), limb position y(i,12), limb position z(i,12) :`position bullet on gun
point object i+10, ply_pos#(2,1), ply_pos#(2,2)+2*cur_pht#, ply_pos#(2,3) :`point bullet at player
b_life(i) = b_life(i) - 1 :`reduce bullet life by 1
show object i+10 :`show the bullet
return
MOVE_BULLETS:
`reduce bullet life
move object i+10, b_spd# :`move bullet
bx# = object position x(i+10) :`determine bullets position x
by# = object position y(i+10) :`determine bullets position y
bz# = object position z(i+10) :`determine bullets position z
`determine which grid square point is in
bcol = int(bx#/usi) + 1
brow = int(bz#/usi) + 1
`determine if bullet has hit a wall
j = 0 : k = 0
`loop to check if there are any blocks to collide with in same square as point
repeat
inc k
`exit loop if square is empty (exit if datbase field is equal to zero)
if table_data(bcol,brow,k) = 0 then exit
j = table_data(bcol,brow,k) :`block ident (block that makes up the map)
`this determines if the point is within a block
if by# <= blk#(j,9) and by# => blk#(j,10)
if POINT_IN_ABCD(bx#,bz#, blk#(j,1),blk#(j,2), blk#(j,3),blk#(j,4), blk#(j,7),blk#(j,8), blk#(j,5),blk#(j,6)) = 1
b_life(i) = 0 :`bullet has hit a block, set bullet life to zero
exit :`exit loop
endif
endif
until k => num_items
`determine if bullet has hit player (treat player like a cylinder)
if by# < 3*cur_pht#
` b_distance# = sqrt( ( ply_pos#(2,1) - bx# )^2 + ( ply_pos#(2,2) - by# )^2 + ( ply_pos#(2,3) - bz# )^2 )
b_distance# = sqrt( ( ply_pos#(2,1) - bx# )^2 + ( ply_pos#(2,3) - bz# )^2 )
if b_distance# < b_size#
ply_life = ply_life - b_dam :`reduce player's life
b_life(i) = 0 :`set bullet life to zero
hide object i+10
endif
endif
return
OTHER_CONTROLS:
`press r to toggle walk or run
if run = 0
if keystate(19)=1
run = 1
if mspd# = rspd# then mspd# = wspd# else mspd# = rspd#
if sspd# = rspd# then sspd# = wspd# else sspd# = rspd#
endif
endif
if keystate(19)=0 then run = 0
`press c to toggle standing and crouching
if crouch = 0
if keystate(46)=1
crouch = 1
if cur_pht# = psht# then cur_pht# = pcht# else cur_pht# = psht#
endif
endif
if keystate(46)=0 then crouch = 0
`press LMB to shoot
hide object 102 :`gun flash
hide object 103 :`gun flash
hide object 105 :`red suqare for when enemy is hit
if mouseclick() <> 2
if cur_ammo > 0
if mouseclick() = 1
cur_ammo = cur_ammo - 1
if cur_ammo < 0 then cur_ammo = 0
show object 102 : roll object left 102, 10
show object 103 : roll object right 103, 7
gosub PLAYER_SHOOTS
endif
endif
endif
`press p to reload
if mouseclick() = 2
cur_ammo = cur_ammo + 1
if cur_ammo > max_ammo then cur_ammo = max_ammo
endif
if keystate(16) = 1 then end :`press q to quit
return
PLAYER_SHOOTS:
`change ply_f_view value depending on how far the enemy is away from the character
for i = 1 to num_figures
if f_life(i) > 0
`calculate angle between player and figure
opp# = object position x(i) - ply_pos#(2,1)
adj# = object position z(i) - ply_pos#(2,3)
angle = ACR_TAN(opp#,adj#)
`caculate difference between angle and facing of player
diff_angle_cw = wrapvalue(angle - ply_fac#(1)) :`clockwise
diff_angle_acw = wrapvalue(360 - (angle - ply_fac#(1))) :`anti clockwise
if diff_angle_cw < diff_angle_acw
diff_angle_smallest = diff_angle_cw
else
diff_angle_smallest = diff_angle_acw
endif
`can only score a hit if the enemy figure is on screen
if diff_angle_smallest < ply_f_view
gosub DETERMINE_LINE_OF_SIGHT
if f_los(i) = 1
stop object i
point object i, ply_pos#(2,1), 0.6*f_hgt, ply_pos#(2,3)
POSE_FIGURE(i,3)
if CURSOR_0N_OBJECT(i, 1001, cross_x#,cross_y#) = 1
`player has shot enemy figure
f_life(i) = f_life(i) - ply_dam
show object 105
roll object left 105, 1
if f_life(i) <= 0
kills = kills + 1
f_los(i) = 0
f_dead_x = object position x(i)
f_dead_z = object position z(i)
f_dead_face = object angle y(i)
stop object i
yrotate object i, 0
xrotate object i, 90
fix object pivot i
POSE_FIGURE(i,4)
position object i, f_dead_x, 0.1*f_hgt, f_dead_z
yrotate object i, rnd(360)
endif
endif
endif
endif
endif
next i
return
MOVE_PLAYER:
`save old position
ply_pos#(1,1) = ply_pos#(2,1)
ply_pos#(1,2) = ply_pos#(2,2)
ply_pos#(1,3) = ply_pos#(2,3)
`use mouse to look left, right, up and down
ply_fac#(1) = wrapvalue(ply_fac#(1) + mousemovex()*tspd#) :`rotate left and right
ply_fac#(2) = wrapvalue(ply_fac#(2) + mousemovey()*pspd#) :`pitch camera up and down
`this restricts the look up and down angle
campitchtest# = wrapvalue(ply_fac#(2)+180)
if campitchtest# < 90 then ply_fac#(2) = 270
if campitchtest# > 270 then ply_fac#(2) = 90
`press w to move forward
if keystate(17) = 1
ply_pos#(2,1) = newxvalue(ply_pos#(2,1), ply_fac#(1), mspd#)
ply_pos#(2,3) = newzvalue(ply_pos#(2,3), ply_fac#(1), mspd#)
endif
`press s to move backward
if keystate(31) = 1
ply_pos#(2,1) = newxvalue(ply_pos#(2,1), wrapvalue(ply_fac#(1)+180), wspd#)
ply_pos#(2,3) = newzvalue(ply_pos#(2,3), wrapvalue(ply_fac#(1)+180), wspd#)
endif
`press a to strafe left
if keystate(30) = 1
ply_pos#(2,1) = newxvalue(ply_pos#(2,1), wrapvalue(ply_fac#(1)-90), mspd#)
ply_pos#(2,3) = newzvalue(ply_pos#(2,3), wrapvalue(ply_fac#(1)-90), mspd#)
endif
`press d to strafe right
if keystate(32) = 1
ply_pos#(2,1) = newxvalue(ply_pos#(2,1), wrapvalue(ply_fac#(1)+90), mspd#)
ply_pos#(2,3) = newzvalue(ply_pos#(2,3), wrapvalue(ply_fac#(1)+90), mspd#)
endif
`jumping
`jump
if jump = 0 and cur_jspd# = 0
if spacekey()=1
jump = 1
cur_jspd# = jspd#
endif
endif
`jumping and falling
ply_pos#(2,2) = ply_pos#(2,2) + cur_jspd#
cur_jspd# = cur_jspd# - grav#
if cur_jspd# < -5.0 then cur_jspd# = -5.0 :`limit falling speed to -5
if ply_pos#(2,2) <= 0
jump = 0
ply_pos#(2,2) = 0
cur_jspd# = 0
endif
gosub COLLISION_WITH_MAP
return
PLACE_CAMERA:
yrotate camera ply_fac#(1)
xrotate camera ply_fac#(2)
position camera ply_pos#(2,1), ply_pos#(2,2)+2*cur_pht#, ply_pos#(2,3)
return
PRINT_STUFF:
set text to bold
text 5,5, "PURPLE SIMPLEX - by 29 games (07 oct 2010)"
text 5,25, "mouse to look, wasd to move and strafe"
text 5,40, "r to toggle run/walk, c to toggle crouch/stand, spacebar to jump"
text 5,55, "lmb to shoot, press and hold rmb to reload"
text 5,70, "q to quit"
text 5,85, "fps : " + str$( screen fps() )
text 5,120, "AMMO : " + str$(cur_ammo)
text 5,135, "HEALTH : " + str$(ply_life)
return
SUCCESS_OUTRO:
for i = 1 to num_figures
delete object i+10 :`delete all bullets as well (these are created again in the CREATE_ENEMY_FIGURES sub routine)
next i
repeat
gosub OTHER_CONTROLS :`run, jump, crouch, shooting and reload
gosub MOVE_PLAYER :`forward, back, strafe and turn
gosub PLACE_CAMERA :`positions camera
gosub PRINT_STUFF :`prints information to screen
center text cross_x#, cross_y#-25, "MISSION COMPLETE"
center text cross_x#, cross_y#+10, "PRESS P TO PLAY AGAIN OR Q TO QUIT"
if keystate(16) = 1 then gosub CLEAN_END :`quit
sync
until keystate(25) = 1 :`play again
for i = 1 to num_figures
delete object i :`delete all figure objects (required for any figures that are dead as their pivot was fixed)
next i
gosub CREATE_ENEMY_FIGURES
gosub STARTING_VARIABLES
return
FAILED_OUTRO:
fog_range = 200
for i = 1 to num_figures
delete object i+10 :`delete all bullets as well (these are created again in the CREATE_ENEMY_FIGURES sub routine)
next i
hide object 102 :`gun flash
hide object 103 :`gun flash
hide object 105 :`red suqare for when enemy is hit
repeat
ply_fac#(1) = wrapvalue(ply_fac#(1) + 0.2)
ply_fac#(2) = wrapvalue(ply_fac#(2) - 0.2)
gosub PLACE_CAMERA
fog_range = fog_range - 1 :`fade to black
if fog_range < 0 then fog_range = 0
fog distance fog_range
center text cross_x#, cross_y#-25, "MISSION FAILED"
center text cross_x#, cross_y#+10, "PRESS P TO PLAY AGAIN OR Q TO QUIT"
if keystate(16) = 1 then gosub CLEAN_END :`quit
sync
until keystate(25) = 1 :`play again
for i = 1 to num_figures
delete object i :`delete all figure objects (required for any figures that are dead as their pivot was fixed)
next i
gosub CREATE_ENEMY_FIGURES
gosub STARTING_VARIABLES
return
CLEAN_END:
`delete any temp files / directories if they exist
sdir$=left$(windir$(), 3)+"dbTemp\"
if file exist(sdir$+"_virtual.bmp")=1 then delete file sdir$+"_virtual.bmp"
if file exist(sdir$+"_virtual.dat")=1 then delete file sdir$+"_virtual.dat"
if file exist(sdir$+"_virtual.jpg")=1 then delete file sdir$+"_virtual.jpg"
if path exist(sdir$)=1 then delete directory sdir$
`end program
end
return
COLLISION_WITH_MAP:
pcol = int(ply_pos#(2,1)/usi) + 1 :`column player is in
prow = int(ply_pos#(2,3)/usi) + 1 :`row player is in
i = 0
k = 0
`loop to check if there are any blocks to collide with in same square as player
repeat
inc k
`exit loop if square is empty (exit if datbase field is equal to zero)
if table_data(pcol,prow,k) = 0
col_calcs = k - 1
exit
endif
i = table_data(pcol,prow,k)
gosub COLLISION_WITH_BLOCK
until k => num_items
return
COLLISION_WITH_BLOCK:
if ply_pos#(2,2) <= blk#(i,9) and ply_pos#(2,2)+3*cur_pht# > blk#(i,10)
if POINT_IN_ABCD(ply_pos#(2,1),ply_pos#(2,3), blk#(i,1),blk#(i,2), blk#(i,3),blk#(i,4), blk#(i,7),blk#(i,8), blk#(i,5),blk#(i,6)) = 1
gosub COLLIDE_WITH_TOP_OR_BOTTOM
else
if ply_pos#(2,2)+cur_pht# < blk#(i,9)
gosub COLLIDE_WITH_SIDE
endif
endif
endif
return
COLLIDE_WITH_TOP_OR_BOTTOM:
if ply_pos#(2,2)+cur_pht# > blk#(i,10)
`hit top surface
ply_pos#(2,2) = blk#(i,9)
cur_jspd# = 0
jump = 0
else
`hit bottom surface
ply_pos#(2,2) = blk#(i,10) - 3*(cur_pht#)
cur_jspd# = 0
endif
return
COLLIDE_WITH_SIDE:
for j = 1 to 7 step 2
sx = j
sz = j+1
ex = j+2
ez = j+3
if ex > 7 then ex = 1
if ez > 8 then ez = 2
`calculate the perpendicula intersect point with wall
pdx# = XD_ON_LINE(ply_pos#(2,1),ply_pos#(2,3), blk#(i,sx),blk#(i,sz),blk#(i,ex),blk#(i,ez))
pdz# = ZD_ON_LINE(ply_pos#(2,1),ply_pos#(2,3), blk#(i,sx),blk#(i,sz),blk#(i,ex),blk#(i,ez))
`calculate the distance from the point to the wall
u# = sqrt( (pdx# - ply_pos#(2,1))^2 + (pdz# - ply_pos#(2,3))^2 )
v# = V_ALONG_LINE(pdx#,pdz#, blk#(i,sx),blk#(i,sz),blk#(i,ex),blk#(i,ez))
`this calculates half the length of the line
h_len# = sqrt( (blk#(i,sx) - blk#(i,ex))^2 + (blk#(i,sz) - blk#(i,ez))^2 ) / 2
`smooth out step down
mod_psiz# = 2*(psiz#*(blk#(i,9)-ply_pos#(2,2)+cur_pht#)) / cur_pht#
if mod_psiz# < 0 then mod_psiz# = 0
if mod_psiz# > psiz# then mod_psiz# = psiz#
if u# <= mod_psiz# and v# <= h_len#
`calculate new coordinates if p in within wall boundary
pddx# = PDDX_FROM_POINT(ply_pos#(2,1),ply_pos#(2,3), pdx#,pdz#, mod_psiz#,u#)
pddz# = PDDZ_FROM_POINT(ply_pos#(2,1),ply_pos#(2,3), pdx#,pdz#, mod_psiz#,u#)
else
`calculate distance of p from the end point of the wall
ap# = sqrt( (ply_pos#(2,1) - blk#(i,sx))^2 + (ply_pos#(2,3) - blk#(i,sz))^2 )
if ap# <= psiz#
`calculate the new coordinates if the point is within the circle
pddx# = PDDX_FROM_POINT(ply_pos#(2,1),ply_pos#(2,3), blk#(i,sx),blk#(i,sz), mod_psiz#,ap#)
pddz# = PDDZ_FROM_POINT(ply_pos#(2,1),ply_pos#(2,3), blk#(i,sx),blk#(i,sz), mod_psiz#,ap#)
else
`this outcome if the point is not within the boundary of the line
pddx# = ply_pos#(2,1)
pddz# = ply_pos#(2,3)
endif
endif
ply_pos#(2,1) = pddx#
ply_pos#(2,3) = pddz#
next j
return
CREATE_OBJECTS:
gosub CREATE_ENEMY_FIGURES :`subroutine to make enemy figures (helpful for the outro)
`create cross hair
`make texture for the cross hair
create bitmap 1, 31,31
set current bitmap 1
ink rgb(250,250,0),0
line 0,15, 31,15
line 15,0, 15,31
ink 0,0
box 14,14,16,16
ink rgb(255,255,255),0
get image 1, 0,0, 31, 31
set current bitmap 0
delete bitmap 1
`create and texture plain for cross hair
make object plain 101, 6,6
texture object 101,1
set object 101, 1, 0, 1
position object 101, 0,0,100
lock object on 101
ghost object on 101
`make obejcts for "gun flash
for i = 102 to 103
make object plain i, 10, 10
color object i, rgb(200,200,0)
set object ambient i, rgb(20,20,20)
position object i, 0,0,105
lock object on i
ghost object on i
hide object i
next i
make object plain 105, 5,5
color object 105, rgb(250,0,0)
ghost object on 105
position object 105, 0,0,90
lock object on 105
hide object 105
`make marker plains (require for cursor on object)
for i = 1001 to 1003
make object plain i,1,1
hide object i
next i
return
CREATE_ENEMY_FIGURES:
`make figure and bullets for figure
for i = 1 to num_figures
MAKE_OBJECT_FIGURE_WITH_GUN(i,f_hgt) :`make figure
ANIMATE_FIGURE(i)
set object speed i, 30
color object i, rgb(100,0,80)
color limb i,12, rgb(50,50,50) :`make gun different colour (gun is made from two limbs 12 and 13)
color limb i,13, rgb(50,50,50) :`make gun different colour
set object ambient i, rgb(60,0,40)
make object sphere i+10, b_size#/2 :`make bullets
color object i+10, rgb(0,0,250)
set object ambient i+10, rgb(50,50,50)
ghost object on i+10
hide object i+10
next i
return
CREATE_MAP:
` make matrix 1, usi*num_mtrx, usi*num_mtrx, num_mtrx, num_mtrx
`write map database to array
restore _map_database
for j = 1 to num_cols :`column
for i = 1 to num_rows :`row
for k = 1 to num_items :`item in row and column
read block_number
table_data(i,j,k) = block_number
next k
next i
next j
`write block data to array
restore _block_data
num_blocks = 0
repeat :`mesh numbers
read blk_col(num_blocks+1,1)
read blk_col(num_blocks+1,2)
read blk_col(num_blocks+1,3)
if blk_col(num_blocks+1,1) + blk_col(num_blocks+1,2) + blk_col(num_blocks+1,3) = 0 then exit
inc num_blocks
`write block data to array
for j = 1 to 10
read blk#(num_blocks,j)
blk#(num_blocks,j) = blk#(num_blocks,j)*usi
next j
until num_blocks > num_blocks_max
`create static objects of blocks
for i = 1 to num_blocks
MAKE_MESH_BLOCK_XZ(1, blk#(i,1),blk#(i,2), blk#(i,3),blk#(i,4), blk#(i,7),blk#(i,8), blk#(i,5),blk#(i,6), blk#(i,9),blk#(i,10))
make object 1,1,0
color object 1, rgb(blk_col(i,1), blk_col(i,2), blk_col(i,3))
make static object 1
delete object 1
delete mesh 1
next num_blocks
undim blk_col(1000,3)
return
`+++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++ FUNCTION +++++++++++++++++++++++++++++++++++
`+++++++++++++++++++++++++++++++++++++++++++++++++++
``++++++++++ MAKE OBJECTS FUNCTIONS ++++++++++++++++++
function MAKE_OBJECT_FIGURE_WITH_GUN(num,size)
`the bottom of the figure's feet are 0.6*size from the object position of the figure
dim p#(10,24)
`write figure vertex data to array
restore _figure_part_data
for i = 1 to 10
for j = 1 to 24
read p#(i,j)
p#(i,j) = p#(i,j)*size
next j
next i
`create meshes for body parts
for i = 1 to 10
MAKE_MESH_8_POINTS(i, p#(i,1),p#(i,2),p#(i,3), p#(i,4),p#(i,5),p#(i,6), p#(i,7),p#(i,8),p#(i,9), p#(i,10),p#(i,11),p#(i,12), p#(i,13),p#(i,14),p#(i,15), p#(i,16),p#(i,17),p#(i,18), p#(i,19),p#(i,20),p#(i,21), p#(i,22),p#(i,23),p#(i,24))
next i
`create object and add limbs limb numbers
make object num,1,0 :` 0 lo_body1
add limb num,1,2 :` 1 mid_body
add limb num,2,3 :` 2 up_body
add limb num,3,4 :` 3 head
add limb num,4,5 :` 4 up_arm left
add limb num,5,5 :` 5 up_arm right
add limb num,6,6 :` 6 lo_arm left
add limb num,7,6 :` 7 lo_arm right
add limb num,8,7 :` 8 up_leg left
add limb num,9,7 :` 9 up_leg right
add limb num,10,8 :` 10 lo_leg left
add limb num,11,8 :` 11 lo_leg right
add limb num,12,9 :` 12 gun body
add limb num,13,10 :` 13 gun magazine
`delete meshes
for i = 1 to 8
delete mesh i
next i
`position limbs and link limbs
offset limb num,1, 0*size,0.148*size,0*size :` 1 mid_body
link limb num,2,1: offset limb num,2, 0*size,0.106*size,0*size :` 2 up_body
link limb num,3,2: offset limb num,3, 0*size,0.052*size,0*size :` 3 head
link limb num,4,2: offset limb num,4, -0.18*size,0.0*size,0*size :` 4 up_arm left
link limb num,5,2: offset limb num,5, 0.18*size,0.0*size,0*size :` 5 up_arm right
link limb num,6,4: offset limb num,6, 0*size,-0.148*size,-0.03*size :` 6 lo_arm left
link limb num,7,5: offset limb num,7, 0*size,-0.148*size,-0.03*size :` 7 lo_arm right
offset limb num,8, -0.075*size,-0.04*size,0*size :` 8 up_leg left
offset limb num,9, 0.075*size,-0.04*size,0*size :` 9 up_leg right
link limb num,10,8: offset limb num,10, 0*size,-0.21*size,0.03*size :` 10 lo_leg left
link limb num,11,9: offset limb num,11, 0*size,-0.21*size,0.03*size :` 11 lo_leg right
link limb num,12,7: offset limb num,12, 0*size,-0.12*size,0.08*size :` 12 gun body
link limb num,13,12: offset limb num,13, 0*size,-0.1*size,-0.04*size :` 13 gun magazine
`delete array from memory
undim p#(8,24)
`data
_figure_part_data:
`vertex data lower body:
data 0.03,-0.08,0.03, -0.03,-0.08,0.03, 0.03,0.09,0.03, -0.03,0.09,0.03
data 0.03,-0.04,-0.06, -0.03,-0.04,-0.06, 0.03,0.09,-0.03, -0.03,0.09,-0.03
`vertex data mid body:
data 0.03,-0.043,0.03, -0.03,-0.043,0.03, 0.1,0.053,0.045, -0.1,0.053,0.045
data 0.03,-0.043,-0.03, -0.03,-0.043,-0.03, 0.1,0.053,-0.045, -0.1,0.053,-0.045
`vertex data upper body:
data 0.135,-0.047,0.045, -0.135,-0.047,0.045, 0.135,0.037,0.045, -0.135,0.037,0.045
data 0.135,-0.047,-0.053, -0.135,-0.047,-0.053, 0.135,0.037,-0.1, -0.135,0.037,-0.1
`vertex data head:
data 0.03,0.0,0.03, -0.03,0.0,0.03, 0.03,0.094,0.03, -0.03,0.094,0.03
data 0.03,0.015,-0.03, -0.03,0.015,-0.03, 0.03,0.094,-0.06, -0.03,0.094,-0.06
`vertex data upper arm:
data 0.03,-0.083,0.03, -0.03,-0.083,0.03, 0.03,0.027,0.03, -0.03,0.027,0.03
data 0.03,-0.143,-0.03, -0.03,-0.143,-0.03, 0.03,0.027,-0.03, -0.03,0.027,-0.03
`vertex data lower arm:
data 0.03,-0.175,0.06, -0.03,-0.175,0.06, 0.03,-0.065,0.06, -0.03,-0.065,0.06
data 0.03,-0.175,0.00, -0.03,-0.175,0.00, 0.03,-0.005,0.00, -0.03,-0.005,0.00
`vertex data upper leg:
data 0.03,-0.205,0.03, -0.03,-0.205,0.03, 0.03,0.04,0.03, -0.03,0.04,0.03
data 0.03,-0.145,-0.03, -0.03,-0.145,-0.03, 0.03,0.04,-0.03, -0.03,0.04,-0.03
`vertex data lower leg:
data 0.060,-0.35,-0.00, -0.060,-0.35,-0.00, 0.060,-0.005,-0.00, -0.060,-0.005,-0.00
data 0.060,-0.35,-0.14, -0.060,-0.35,-0.14, 0.060,-0.065,-0.07, -0.060,-0.065,-0.07
`vertex data for gun body
data 0.020,-0.30,0.020, -0.02,-0.30,0.020, 0.020,0.000,0.020, -0.02,0.000,0.020
data 0.020,-0.30,-0.02, -0.02,-0.30,-0.02, 0.020,0.020,-0.02, -0.02,0.020,-0.02
`vertex data for gun magazine
data 0.020,-0.20,0.020, -0.02,-0.20,0.020, 0.020,0.050,0.020, -0.02,0.050,0.020
data 0.020,-0.23,-0.02, -0.02,-0.23,-0.02, 0.020,0.000,-0.02, -0.02,0.000,-0.02
endfunction
function ANIMATE_FIGURE(n):
`walking animation
POSE_FIGURE(n,1) : set object keyframe n,1 :`full run right foot forward
POSE_FIGURE(n,2) : set object keyframe n,31 :`half run right foot forward
POSE_FIGURE(n,1) : set object keyframe n,61 :`half run right foot down
endfunction
function POSE_FIGURE(num,p)
if p = 0 then restore _pose_data_00 :`standing
`poses for walking
if p = 1 then restore _pose_data_01 :`full walk right foot forward
if p = 2 then restore _pose_data_02 :`full walk left foot forward
if p = 3 then restore _pose_data_03 :`standing with gun across chest
if p = 4 then restore _pose_data_04 :`lying on front dead
`rotate limbs
for i = 1 to 11
read ax,ay,az
rotate limb num,i, wrapvalue(ax),wrapvalue(ay),wrapvalue(az)
next i
`standing
_pose_data_00:
data 0, 0, 0 :` 1 mid_body
data 0, 0, 0 :` 2 up_body
data 0, 0, 0 :` 3 head
data 0, 0, 0 :` 4 up_arm left
data 0, 0, 0 :` 5 up_arm right
data 0, 0, 0 :` 6 lo_arm left
data 0, 0, 0 :` 7 lo_arm right
data 0, 0, 0 :` 8 up_leg left
data 0, 0, 0 :` 9 up_leg right
data 0, 0, 0 :` 10 lo_leg left
data 0, 0, 0 :` 11 lo_leg right
`full walk right foot forward
_pose_data_01:
data 0, 15, 0 :` 1 mid_body
data 0, 5, 0 :` 2 up_body
data 0, -20, 0 :` 3 head
data 0, 20, 0 :` 4 up_arm left
data -30, -90, 0 :` 5 up_arm right
data -45, 0, 0 :` 6 lo_arm left
data -70, 20, 0 :` 7 lo_arm right
data 10, 0, 0 :` 8 up_leg left
data -20, 0, 0 :` 9 up_leg right
data 20, 0, 0 :` 10 lo_leg left
data 0, 0, 0 :` 11 lo_leg right
`full walk left foot forward
_pose_data_02:
data 0, -15, 0 :` 1 mid_body
data 0, -5, 0 :` 2 up_body
data 0, 20, 0 :` 3 head
data 0, 20, 0 :` 4 up_arm left
data -30, -90, 0 :` 5 up_arm right
data -45, 0, 0 :` 6 lo_arm left
data -70, 20, 0 :` 7 lo_arm right
data -20, 0, 0 :` 8 up_leg left
data 10, 0, 0 :` 9 up_leg right
data 0, 0, 0 :` 10 lo_leg left
data 20, 0, 0 :` 11 lo_leg right
`standing with gun, firing from hip
_pose_data_03:
data -10, 55, 0 :` 1 mid_body
data 10, 0, 0 :` 2 up_body
data 10, -55, 20 :` 3 head
data -30, 30, 0 :` 4 up_arm left
data 0, -55, 0 :` 5 up_arm right
data -45, 0, 0 :` 6 lo_arm left
data -90, 0, 0 :` 7 lo_arm right
data 0, 0, -20 :` 8 up_leg left
data 0, 0, 20 :` 9 up_leg right
data 0, 0, 0 :` 10 lo_leg left
data 0, 0, 0 :` 11 lo_leg right
`lying on front dead
_pose_data_04:
data 0, 0, 10 :` 1 mid_body
data 0, 0, 10 :` 2 up_body
data 0, 45, 0 :` 3 head
data -90, 30, -90 :` 4 up_arm left
data -90, -60, 90 :` 5 up_arm right
data -30, 0, 0 :` 6 lo_arm left
data -30, 0, 0 :` 7 lo_arm right
data 0, 0, -20 :` 8 up_leg left
data 0, 0, 20 :` 9 up_leg right
data 0, 0, 0 :` 10 lo_leg left
data 0, 0, 0 :` 11 lo_leg right
endfunction
`++++++++++ MAKE MESHES FUNCTIONS ++++++++++++++++++
function MAKE_MESH_BLOCK_XZ(num, ax#,az#, bx#,bz#, cx#,cz#, dx#,dz#, ty#,uy#)
`a = front right, b = front left, c = back right, d = back left, t = top surface, u = underside
MAKE_MESH_8_POINTS(num, ax#,uy#,az#, bx#,uy#,bz#, ax#,ty#,az#, bx#,ty#,bz#, cx#,uy#,cz#, dx#,uy#,dz#, cx#,ty#,cz#, dx#,ty#,dz#)
endfunction
function MAKE_MESH_8_POINTS(num, ax#,ay#,az#, bx#,by#,bz#, cx#,cy#,cz#, dx#,dy#,dz#, ex#,ey#,ez#, fx#,fy#,fz#, gx#,gy#,gz#, hx#,hy#,hz#)
`a = front right bottom, b = front left bottom, c = front right top, d = front left top
`e = back right bottom, f = back left bottom, g = back right top, h = back left top
`there are six sides to a box
num_sides = 6
`memblock number
mem = 1
`header values
num_verts = num_sides * 4
pos_verts = 32
num_norms = num_verts
pos_norms = num_verts*12 + pos_verts
num_faces = num_sides*2
pos_faces = pos_norms + num_norms*12
size_faces = num_faces*7
pos_uv = pos_faces + size_faces*4
`calculate size of memblock
size_mem = 32 + (num_verts + num_norms)*12 + size_faces*4 + num_sides*32
`create the memblock
make memblock mem, size_mem
`write header values to memblock
write memblock dword mem, 0, num_verts
write memblock dword mem, 4, pos_verts
write memblock dword mem, 8, num_norms
write memblock dword mem, 12, pos_norms
write memblock dword mem, 16, num_faces
write memblock dword mem, 20, pos_faces
write memblock dword mem, 24, size_faces
write memblock dword mem, 28, pos_uv
`write vertext data to memblock
`front face
write memblock float mem, 32, ax# : write memblock float mem, 36, ay# : write memblock float mem, 40, az# : `0 vertex
write memblock float mem, 44, bx# : write memblock float mem, 48, by# : write memblock float mem, 52, bz# : `1 vertex
write memblock float mem, 56, cx# : write memblock float mem, 60, cy# : write memblock float mem, 64, cz# : `2 vertex
write memblock float mem, 68, dx# : write memblock float mem, 72, dy# : write memblock float mem, 76, dz# : `3 vertex
`back face
write memblock float mem, 80, fx# : write memblock float mem, 84, fy# : write memblock float mem, 88, fz# : `4 vertex
write memblock float mem, 92, ex# : write memblock float mem, 96, ey# : write memblock float mem, 100, ez# : `5 vertex
write memblock float mem, 104, hx# : write memblock float mem, 108, hy# : write memblock float mem, 112, hz# : `6 vertex
write memblock float mem, 116, gx# : write memblock float mem, 120, gy# : write memblock float mem, 124, gz# : `7 vertex
`left face
write memblock float mem, 128, bx# : write memblock float mem, 132, by# : write memblock float mem, 136, bz# : `8 vertex
write memblock float mem, 140, fx# : write memblock float mem, 144, fy# : write memblock float mem, 148, fz# : `9 vertex
write memblock float mem, 152, dx# : write memblock float mem, 156, dy# : write memblock float mem, 160, dz# : `10 vertex
write memblock float mem, 164, hx# : write memblock float mem, 168, hy# : write memblock float mem, 172, hz# : `11 vertex
`right face
write memblock float mem, 176, ex# : write memblock float mem, 180, ey# : write memblock float mem, 184, ez# : `12 vertex
write memblock float mem, 188, ax# : write memblock float mem, 192, ay# : write memblock float mem, 196, az# : `13 vertex
write memblock float mem, 200, gx# : write memblock float mem, 204, gy# : write memblock float mem, 208, gz# : `14 vertex
write memblock float mem, 212, cx# : write memblock float mem, 216, cy# : write memblock float mem, 220, cz# : `15 vertex
`top face
write memblock float mem, 224, hx# : write memblock float mem, 228, hy# : write memblock float mem, 232, hz# : `16 vertex
write memblock float mem, 236, gx# : write memblock float mem, 240, gy# : write memblock float mem, 244, gz# : `17 vertex
write memblock float mem, 248, dx# : write memblock float mem, 252, dy# : write memblock float mem, 256, dz# : `18 vertex
write memblock float mem, 260, cx# : write memblock float mem, 264, cy# : write memblock float mem, 268, cz# : `19 vertex
`bottom face
write memblock float mem, 272, bx# : write memblock float mem, 276, by# : write memblock float mem, 280, bz# : `20 vertex
write memblock float mem, 284, ax# : write memblock float mem, 288, ay# : write memblock float mem, 292, az# : `21 vertex
write memblock float mem, 296, fx# : write memblock float mem, 300, fy# : write memblock float mem, 304, fz# : `22 vertex
write memblock float mem, 308, ex# : write memblock float mem, 312, ey# : write memblock float mem, 316, ez# : `23 vertex
`write normal data to memblock
restore _normdata
for pos = pos_norms to pos_norms+(num_norms*12)-12 step 12
read x,y,z
write memblock float mem, pos, x
write memblock float mem, pos+4, y
write memblock float mem, pos+8, z
next pos
`write face data to memblock
restore _facedata
for pos = pos_faces to pos_faces+(num_faces*28)-28 step 28
read nvf, va,na, vb, nb, vc,nc
write memblock dword mem, pos, nvf
write memblock dword mem, pos+4, va
write memblock dword mem, pos+8, na
write memblock dword mem, pos+12, vb
write memblock dword mem, pos+16, nb
write memblock dword mem, pos+20, vc
write memblock dword mem, pos+24, nc
next pos
`write UV data to memblock
restore _uvdata
for pos = pos_uv to pos_uv+(num_sides*32)-32 step 32
read ua#,va#, ub#,vb#, uc#,vc#, ud#,vd#
write memblock float mem, pos, ua#
write memblock float mem, pos+4, va#
write memblock float mem, pos+8, ub#
write memblock float mem, pos+12, vb#
write memblock float mem, pos+16, uc#
write memblock float mem, pos+20, vc#
write memblock float mem, pos+24, ud#
write memblock float mem, pos+28, vd#
next pos
`create mesh then create object, delete mesh and memblock
make mesh from memblock num, mem
delete memblock 1
_normdata:
data 0,1,1, 0,1,1, 0,1,1, 0,1,1 :`front
data 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1 :`back
data -1,0,0, -1,0,0, -1,0,0, -1,0,0 :`left
data 1,0,0, 1,0,0, 1,0,0, 1,0,0 :`right
data 0,1,0, 0,1,0, 0,1,0, 0,1,0 :`top
data 0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0 :`bottom
_facedata:
data 3, 0,0, 3,3, 1,1 :`front face 0
data 3, 3,3, 0,0, 2,2 :`front face 1
data 3, 4,4, 7,7, 5,5 :`back face 2
data 3, 7,7, 4,4, 6,6 :`back face 3
data 3, 8,8, 11,11, 9,9 :`left face 4
data 3, 11,11, 8,8, 10,10 :`left face 5
data 3, 12,12, 15,15, 13,13 :`right face 6
data 3, 15,15, 12,12, 14,14 :`right face 7
data 3, 16,16, 19,19, 17,17 :`top face 8
data 3, 19,19, 16,16, 18,18 :`top face 9
data 3, 20,20, 23,23, 21,21 :`bottom face 10
data 3, 23,23, 20,20, 22,22 :`bottom face 11
_uvdata:
data 0.03,0.47, 0.30,0.47, 0.03,0.03, 0.30,0.03 :`front
data 0.03,0.97, 0.30,0.97, 0.03,0.53, 0.30,0.53 :`back
data 0.36,0.47, 0.63,0.47, 0.36,0.03, 0.63,0.03 :`left
data 0.36,0.97, 0.63,0.97, 0.36,0.53, 0.63,0.53 :`right
data 0.69,0.47, 0.97,0.47, 0.69,0.03, 0.97,0.03 :`top
data 0.69,0.97, 0.97,0.97, 0.69,0.53, 0.97,0.53 :`bottom
endfunction
`+++++++++++++ FUNCTIONS FOR POINT IN SHAPE +++++++++++++++
function POINT_IN_ABCD(px#,pz#, ax#,az#, bx#,bz#, cx#,cz#, dx#,dz#)
`this function determines if a point is inside a four sided shape
if POINT_IN_ABC(px#,pz#, ax#,az#, dx#,dz#, bx#,bz#) = 1
inside = 1
else
if POINT_IN_ABC(px#,pz#, dx#,dz#, ax#,az#, cx#,cz#) = 1
inside = 1
else
inside = 0
endif
endif
endfunction inside
function POINT_IN_ABC(px#,pz#, ax#,az#, bx#,bz#, cx#,cz#)
`this function determines if a point is inside a triangle
if SAME_SIDE(px#,pz#, cx#,cz#, ax#,az#,bx#,bz#) = 1
if SAME_SIDE(px#,pz#, ax#,az#, bx#,bz#,cx#,cz#) = 1
if SAME_SIDE(px#,pz#, bx#,bz#, cx#,cz#,ax#,az#) = 1
inside = 1
else
inside = 0
endif
else
inside = 0
endif
else
inside = 0
endif
endfunction inside
function SAME_SIDE(px#,pz#, rx#,rz#, sx#,sz#,fx#,fz#)
`this function determines if point p is on same side of line sf as point r
psi# = px# - sx#: psj# = pz# - sz# :`vector ps
fsi# = fx# - sx#: fsj# = fz# - sz# :`vector fs
rsi# = rx# - sx#: rsj# = rz# - sz# :`vector rs
fs_cross_ps# = fsi#*psj# - psi#*fsj# :`cross product of vectors fs and ps
fs_cross_rs# = fsi#*rsj# - rsi#*fsj# :`cross product of vectors fs and rs
if fs_cross_ps# > 0 then fs_cross_ps# = 1 else fs_cross_ps# = -1
if fs_cross_rs# > 0 then fs_cross_rs# = 1 else fs_cross_rs# = -1
if fs_cross_ps# = fs_cross_rs# then yes = 1 else yes = 0
endfunction yes
`++++++ FUNCTIONS FOR CIRCLE ON LINE COLLISION +++++++++++++++++++++++++++++++++++++++++++++
function XD_ON_LINE(px#,pz#, ax#,az#,bx#,bz#)
`line parallel with x axis
if az# = bz#
pdx# = px#
endif
`line parallel with z axis
if ax# = bx#
pdx# = ax#
endif
`line is not parallel to either x or z axis
if az# <> bz# and ax# <> bx#
mab# = (bx# - ax#)/(bz# - az#)
aaa# = (ax#/mab#) + (mab#*px#)
bbb# = pz# - az#
ccc# = mab# + (1/mab#)
pdx# = (aaa# + bbb#) / ccc#
endif
endfunction pdx#
function ZD_ON_LINE(px#,pz#, ax#,az#,bx#,bz#)
`line parallel with x axis
if az# = bz#
pdz# = az#
endif
`line parallel with z axis
if ax# = bx#
pdz# = pz#
endif
`line is not parallel to either x or z axis
if az# <> bz# and ax# <> bx#
mab# = (bx# - ax#)/(bz# - az#)
aaa# = (pz#/mab#) + mab#*az#
bbb# = px# - ax#
ccc# = mab# + (1/mab#)
pdz# = (aaa# + bbb#) / ccc#
endif
endfunction pdz#
function V_ALONG_LINE(pdx#,pdz#, ax#,az#,bx#,bz#)
gx# = (bx# + ax#) / 2
gz# = (bz# + az#) / 2
v# = sqrt( (gx# - pdx#)^2 + (gz# - pdz#)^2 )
endfunction v#
function PDDX_FROM_POINT(px#,pz#, ex#,ez#, s#,u#)
pddx_p# = (s#*(px#-ex#)/u#) + ex#
endfunction pddx_p#
function PDDZ_FROM_POINT(px#,pz#, ex#,ez#, s#,u#)
pddz_p# = ez# - (s#*(ez#-pz#)/u#)
endfunction pddz_p#
function CURSOR_0N_OBJECT(obj1,obj2, cursor_x#,cursor_y#)
dim v#(1000,3,3) :`coordinates of vertex (face, vertex, xyz)
dim s#(1000,3,2) :`screen coordinates of the vertex (vertex, xy)
yes = 0 :`set default return value to zero
`initial values for left, right, top and btm extremes of box
left# = object screen x(obj1)
right# = left#
top# = object screen y(obj1)
btm# = top#
mes = 0
repeat
inc mes
until mesh exist(mes) = 0
mem = 0
repeat
inc mem
until memblock exist(mem) = 0
`make memblock and extact header info
make mesh from object mes,obj1
make memblock from mesh mem, mes
num_verts = memblock dword(mem,0)
pos_verts = memblock dword(mem,4)
num_norms = memblock dword(mem,8)
pos_norms = memblock dword(mem,12)
num_faces = memblock dword(mem,16)
pos_faces = memblock dword(mem,20)
siz_faces = memblock dword(mem,24)
pos_uv = memblock dword(mem,28)
`extract the vertext data for each face of the model
for face = 0 to num_faces - 1
pos = face*28 + pos_faces
`extract the face data
fa = memblock dword(mem,pos+4)
fb = memblock dword(mem,pos+12)
fc = memblock dword(mem,pos+20)
`extract the vertex data for the face
v#(face,1,1) = memblock float(mem,fa*12 + pos_verts)
v#(face,1,2) = memblock float(mem,fa*12 + pos_verts+4)
v#(face,1,3) = memblock float(mem,fa*12 + pos_verts+8)
v#(face,2,1) = memblock float(mem,fb*12 + pos_verts)
v#(face,2,2) = memblock float(mem,fb*12 + pos_verts+4)
v#(face,2,3) = memblock float(mem,fb*12 + pos_verts+8)
v#(face,3,1) = memblock float(mem,fc*12 + pos_verts)
v#(face,3,2) = memblock float(mem,fc*12 + pos_verts+4)
v#(face,3,3) = memblock float(mem,fc*12 + pos_verts+8)
`this puts an invisible 2D box, project onto the screen, around the object
for i = 1 to 3
`position "marker object" at vertex
position object obj2, v#(face,i,1),v#(face,i,2),v#(face,i,3)
s#(face,i,1) = object screen x(obj2) :`x coordinate
s#(face,i,2) = object screen y(obj2) :`y coordinate
if s#(face,i,1) < left# then left# = s#(face,i,1)
if s#(face,i,1) > right# then right# = s#(face,i,1)
if s#(face,i,2) < btm# then btm# = s#(face,i,2)
if s#(face,i,2) > top# then top# = s#(face,i,2)
next i
next face
`only do precise detection if the cursor coordiantes are within the invisible box
if cursor_x# => left# and cursor_x# < right#
if cursor_y# > btm# and cursor_y# < top#
face = 0
repeat
`determine if three points are in a straight line, use dot product to do this
`if the dot product is equal to 1 or -1 then then three points of the triangle are in line with each other
a1# = s#(face,2,1) - s#(face,1,1)
c1# = s#(face,2,2) - s#(face,1,2)
a2# = s#(face,3,1) - s#(face,1,1)
c2# = s#(face,3,2) - s#(face,1,2)
ab# = sqrt(a1#^2 + c1#^2)
cd# = sqrt(a2#^2 + c2#^2)
ab_cd# = ab#*cd#
`if ab_cd# = 0 then it means that at least two of the points have the same coordinates
if ab_cd# <> 0
dot_prod# = (a1#*a2# + c1#*c2#) / (ab_cd#)
else
dot_prod# = 1 :`stricly speaking, I don't think it does but it helps in the next part of the function
endif
`if the three poinst make a triangle
if abs(dot_prod#) <> 1
yes = POINT_IN_ABC(cursor_x#,cursor_y#, s#(face,1,1),s#(face,1,2), s#(face,2,1),s#(face,2,2), s#(face,3,1),s#(face,3,2))
if yes = 1 then exit :`if cursor is within projected triangle then exit the loop
endif
inc face
until face = num_faces - 1
endif
endif
`delete the mesh and the memblock
delete mesh mes
delete memblock mem
dim v#(1000,3,3)
dim s#(1000,3,2)
endfunction yes
function ACR_TAN(opp#,adj#)
if adj# <> 0
angle# = wrapvalue(atan(opp#/adj#))
if adj# < 0 then angle# = wrapvalue(angle#+180)
else
if opp# > 0 then angle# = 90.0 else angle# = 270.0
endif
endfunction angle#
`+++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++ MAP DATA +++++++++++++++++++++++++++++++++++
`+++++++++++++++++++++++++++++++++++++++++++++++++++
_map_database:
` row 1
data 03,06,07,08,00,00,00,00,00,00,00 :`col 1
data 06,08,09,18,19,00,00,00,00,00,00 :`col 2
data 06,09,10,11,18,19,32,33,35,36,00 :`col 3
data 04,06,10,11,00,00,00,00,00,00,00 :`col 4
`row 2
data 03,07,26,27,28,29,30,45,00,00,00 :`col 1
data 19,31,00,00,00,00,00,00,00,00,00 :`col 2
data 19,20,21,34,32,33,35,36,37,38,00 :`col 3
data 04,11,12,21,34,00,00,00,00,00,00 :`col 4
`row 3
data 03,13,14,27,30,00,00,00,00,00,00 :`col 1
data 14,15,19,00,00,00,00,00,00,00,00 :`col 2
data 15,16,17,19,20,21,00,00,00,00,00 :`col 3
data 04,12,17,21,00,00,00,00,00,00,00 :`col 4
`row 4
data 03,05,13,14,36,37,38,39,40,41,42 :`col 1
data 05,14,15,24,25,41,42,00,00,00,00 :`col 2
data 05,15,16,17,43,44,00,00,00,00,00 :`col 3
data 04,05,17,22,23,00,00,00,00,00,00 :`col 4
_block_data:
`one, two, three and four are the four corners of the block
`they must be specified in an anticlockwise direction as viewed from the top
` red, grn, blu, onex,onez, twox,twoz, threex,threez, fourx,fourz, top,btm
data 100, 0, 80, 4.0,4.0, 0.0,4.0, 0.0,0.0, 4.0,0.0, 0.0,-0.5 :`1 floor
data 100, 0, 80, 4.0,4.0, 0.0,4.0, 0.0,0.0, 4.0,0.0, 1.0,0.5 :`2 ceiling
data 100, 0, 80, 0.0,4.0, -1.0,4.0, -1.0,0.0, 0.0,0.0, 0.5,0.0 :`3 west wall
data 100, 0, 80, 5.0,4.0, 4.0,4.0, 4.0,0.0, 5.0,0.0, 0.5,0.0 :`4 east wall
data 100, 0, 80, 5.0,5.0, -1.0,5.0, -1.0,4.0, 5.0,4.0, 1.0,-0.5 :`5 north wall
data 100, 0, 80, 5.0,0.0, -1.0,0.0, -1.0,-1.0, 5.0,-1.0, 1.0,-0.5 :`6 south wall
`walls
data 100, 0, 80, 0.50,0.75, 0.00,1.25, 0.00,0.00, 0.50,0.00, 0.5,0.0 :`7
data 100, 0, 80, 1.25,0.75, 0.75,0.75, 0.75,0.50, 1.25,0.50, 0.5,0.0 :`8
data 100, 0, 80, 2.50,0.75, 1.50,0.75, 1.50,0.50, 2.50,0.50, 0.5,0.0 :`9
data 100, 0, 80, 3.25,0.75, 2.75,0.75, 2.75,0.50, 3.25,0.50, 0.5,0.0 :`10
data 100, 0, 80, 3.25,1.00, 3.00,0.75, 3.25,0.50, 3.55,0.80, 0.5,0.0 :`11
data 100, 0, 80, 4.00,2.75, 3.25,2.25, 3.25,1.50, 4.00,1.00, 0.5,0.0 :`12
data 100, 0, 80, 0.50,3.00, 0.00,3.00, 0.00,2.00, 0.50,2.50, 0.5,0.0 :`13
data 100, 0, 80, 1.00,3.00, 0.50,3.00, 0.50,2.70, 1.00,2.70, 0.5,0.0 :`14
data 100, 0, 80, 2.25,3.00, 1.25,3.00, 1.25,2.70, 2.25,2.70, 0.5,0.0 :`15
data 100, 0, 80, 2.95,3.00, 2.50,3.00, 2.50,2.70, 2.95,2.70, 0.5,0.0 :`16
data 100, 0, 80, 3.35,3.40, 2.75,3.00, 2.95,2.70, 3.55,3.10, 0.5,0.0 :`17
data 100, 0, 80, 2.00,0.15, 1.75,0.15, 1.75,0.00, 2.00,0.00, 0.5,0.0 :`18
data 100, 0, 80, 2.00,2.00, 1.75,2.00, 1.75,0.35, 2.00,0.35, 0.5,0.0 :`19
data 100, 0, 80, 2.25,2.00, 2.00,2.00, 2.00,1.75, 2.25,1.75, 0.5,0.0 :`20
data 100, 0, 80, 3.25,2.00, 2.50,2.00, 2.50,1.75, 3.25,1.75, 0.5,0.0 :`21
data 100, 0, 80, 3.55,3.50, 3.30,3.50, 3.30,3.10, 3.55,3.10, 0.5,0.0 :`22
data 100, 0, 80, 3.55,4.00, 3.30,4.00, 3.30,3.75, 3.55,3.75, 0.5,0.0 :`23
data 100, 0, 80, 1.75,3.25, 1.50,3.25, 1.35,3.00, 1.90,3.00, 0.5,0.0 :`24
data 100, 0, 80, 1.90,4.00, 1.35,4.00, 1.50,3.75, 1.75,3.75, 0.5,0.0 :`25
data 100, 0, 80, 0.15,1.50, 0.00,1.50, 0.00,1.10, 0.15,1.10, 0.5,0.0 :`26
data 100, 0, 80, 0.15,2.25, 0.00,2.25, 0.00,1.75, 0.15,1.75, 0.5,0.0 :`27
`furniture
data 70, 0, 60, 0.60,1.50, 0.50,1.40, 0.75,1.15, 0.85,1.25, 0.10,0.0 :`28
data 70, 0, 60, 0.60,1.85, 0.50,1.85, 0.50,1.40, 0.60,1.40, 0.10,0.0 :`29
data 70, 0, 60, 0.75,2.10, 0.50,1.85, 0.60,1.75, 0.85,2.00, 0.10,0.0 :`30
data 70, 0, 60, 1.35,1.75, 1.25,1.75, 1.25,1.50, 1.35,1.50, 0.10,0.0 :`31
data 70, 0, 60, 2.25,1.10, 2.10,1.10, 2.10,1.00, 2.25,1.00, 0.10,0.0 :`32
data 70, 0, 60, 2.35,1.00, 2.25,1.10, 2.25,0.75, 2.35,0.75, 0.10,0.0 :`33
data 70, 0, 60, 3.00,1.60, 2.65,1.60, 2.75,1.50, 3.00,1.50, 0.10,0.0 :`34
data 70, 0, 60, 2.75,1.75, 2.65,1.75, 2.65,1.60, 2.75,1.60, 0.10,0.0 :`35
data 70, 0, 60, 0.30,3.25, 0.20,3.25, 0.20,3.00, 0.30,3.00, 0.30,0.0 :`36
data 70, 0, 60, 0.30,3.75, 0.20,3.75, 0.20,3.50, 0.30,3.50, 0.30,0.0 :`37
data 70, 0, 60, 0.55,3.25, 0.45,3.25, 0.45,3.00, 0.55,3.00, 0.30,0.0 :`38
data 70, 0, 60, 0.55,3.75, 0.45,3.75, 0.45,3.50, 0.55,3.50, 0.30,0.0 :`39
data 70, 0, 60, 0.80,3.25, 0.70,3.25, 0.70,3.00, 0.80,3.00, 0.30,0.0 :`40
data 70, 0, 60, 1.00,3.85, 0.80,3.65, 0.90,3.55, 1.10,3.75, 0.10,0.0 :`41
data 70, 0, 60, 1.10,4.00, 1.00,4.00, 1.00,3.75, 1.10,3.75, 0.10,0.0 :`42
data 70, 0, 60, 2.50,3.60, 2.20,3.60, 2.10,3.50, 2.60,3.50, 0.10,0.0 :`43
data 70, 0, 60, 2.60,3.50, 2.10,3.50, 2.20,3.40, 2.50,3.40, 0.10,0.0 :`44
data 50, 0, 30, 0.10,1.75, 0.00,1.75, 0.00,1.50, 0.10,1.50, 0.5,0.0 :`45
`end of block data
data 0, 0, 0, 0.0,0.0, 0.0,0.0, 0.0,0.0, 0.0,0.0, 0.0,0.0
_way_point_data:
` 1x, 1z, 2x, 2z, 3x, 3z, 4x, 4z, 5x, 5z, 6x, 6z, 7x, 7z, 8x, 8z, 9x, 9z, 10x, 10z
data 3.60,3.65, 3.00,3.65, 2.75,3.75, 2.00,3.75, 1.75,3.50, 1.00,3.50, 1.75,3.50, 2.00,3.25, 2.75,3.25, 3.00,3.65
data 0.50,1.00, 0.30,1.50, 0.30,2.00, 0.75,2.50, 1.50,2.50, 1.50,1.25, 1.40,1.00, 1.35,0.25, 0.65,0.25, 0.60,0.75
data 3.00,2.50, 2.40,2.50, 2.35,1.40, 2.60,0.85, 2.65,0.25, 3.75,0.25, 3.75,0.80, 3.25,1.25, 2.50,1.25, 2.35,2.15
data 1.10,3.40, 1.94,3.40, 2.35,3.10, 2.40,2.40, 2.40,1.30, 2.70,0.25, 1.40,0.25, 1.30,1.00, 1.10,1.25, 1.10,1.50
data 1.00,1.00, 1.00,2.00, 1.75,2.50, 3.10,2.50, 3.75,3.00, 3.75,3.25, 3.75,3.00, 3.10,2.50, 1.25,2.50, 1.00,2.00
data 0.00,0.00, 0.00,0.00, 0.00,0.00, 0.00,0.00, 0.00,0.00, 0.00,0.00, 0.00,0.00, 0.00,0.00, 0.00,0.00, 0.00,0.00
You might get some slow down if there is more than three enemies on screen at the same time (I'm on a 1.5 GHz, 1 Gig ram laptop). I'm currently seeing if I can sort out the shooting code to make it quicker but this is more an experiment at the moment so I thought I'd post it as is.
Comments welcome. Enjoy.