Rem Project: desperado
Rem Created: Saturday, December 14, 2013

Rem ***** Main Source File *****


global scrw as integer
global scrh as integer
scrw = desktop width()
scrh = desktop height()

scrw = 1024
scrh = 768


set display mode scrw, scrh, 32, 1
sync on
sync rate 65
sync

cls 0

media_init()
SetupIntroScreen()
FinishIntroScreen()

cls 0
ink 0xFFFFFFFF,0
center text scrw/2, scrh*0.4, "Loading, Please Wait..." : sync

disable escapekey

load music "media/song.mp3", 1
set music volume 1, 70
loop music 1

rem Load Media Stuff
set image colorkey 255, 0, 255
rem Rendering
global render_groundTarget = 1
ik create render target render_groundTarget, 1024, 1024
global render_heightmap as integer
render_heightmap = media_loadImage("media/heightmap.png")
global render_mapping as integer
render_mapping = media_loadImage("media/coords.png")
global render_texture as integer
render_texture = media_loadImage("media/texture.png")
global render_view as integer
render_view = media_loadImage("media/view.png")
ik load effect "media/displace.fx", 1
ik set effect technique 1, "Displace"
ik set effect texture 1, "g_Map", render_mapping
global render_textureTrg as integer : render_textureTrg = media_freeImage()
ik create render target render_textureTrg, 1024, 1024
clearLevel()

rem Init Stuff
d3d_init
d3d_font 1, "Verdana", 36, 1, 0, 1
txh_init()
cam_init()
logics_init()
layer_init()
mark_init()
weapon_init()
fx_init()
sound_init()
draw_init(scrh,200)


hide mouse

set text font "Verdana"
set text size 80
set text to bold
ink 0xFF602810,0
txtspr = txh_prepare(0,"DESPERADO")
global sprite_titleText
sprite_titleText = txtspr
set text size 24
set text to normal


rem Init Stuff that needs media
level_init(render_heightmap, render_view)
unit_init()

rem Units
global spr_Player
global spr_Hat
global spr_Foot
global spr_Foot1
global spr_Enemy
global spr_Shadow
spr_Player = media_loadAnimationOff("media/player.bmp", 2, 1, 0.5, 1.0)
spr_Enemy = media_loadAnimationOff("media/enemy.bmp", 2, 1, 0.5, 1.0)
spr_Foot = media_loadSpriteOff("media/foot.bmp", 0.5, 0.7) : set sprite diffuse spr_Foot, 0, 0, 255
spr_Foot1 = media_loadSpriteOff("media/foot.bmp", 0.5, 0.7) : set sprite diffuse spr_Foot1, 0,0,0
spr_Hat = media_loadSpriteOff("media/hat.png", 0.5, 1.1)
spr_Shadow = media_loadSprite("media/shadow.png")
rem Decals
global spr_Blood
global spr_stomp
global spr_Corpse
spr_Blood = media_loadSprite("media/blood.png") : set sprite diffuse spr_Blood, 160, 15, 3
spr_stomp = media_loadSprite("media/crack.png") : set sprite diffuse spr_Stomp, 0,0,0 
spr_Corpse = media_loadSprite("media/blood.png") : set sprite diffuse spr_Corpse, 0,0,255 : scale sprite spr_Corpse, 70

logics_nextRound()


t0 = timer()
global game_runtime as integer
global mouse_worldX as integer = 512
global mouse_worldY as integer = 512
global mouse_worldZ as float = 1.0

#constant STATE__PLAY = 0
#constant STATE__LOST = 1

escPressed as integer = 1

global game_paused as boolean = 0
global game_state as integer = STATE__PLAY

rem ** MAIN LOOP **
do

cls 0xFFFFFF

if game_paused = 0
game_runtime = timer() - t0
endif

if escapekey()
if escPressed = 0
escPressed = 1
game_Paused = 1 - game_Paused
if game_Paused = 0 then t0 = timer() - game_runtime
endif
else
escPressed = 0
endif

update()
drawGround()
drawTop()

scr_update()

remstart
print "FPS: ", screen fps()
print "Unit: ", unit(1).x, ",", unit(1).y, ",", unit(1).z
remend

sync
loop




function update()
if game_paused
if returnkey() then endGame()
else
if game_state = STATE__PLAY
updateMouse()
logics_update()
unit_control(1)
unit_update()
mark_update()
weapon_updateBullets()
endif
endif
endfunction


function drawGround()
rem First: Draw to Render Target
draw to image render_groundTarget
rem Cls
ink 0xFF000000,0
box 0,0,1024,1024
rem Base Texture
paste image render_textureTrg, 0, 0
layer_draw()
rem Test
rem y# = 1024*(0.5 + 0.3*sin(game_runtime*0.1))
ang# = game_runtime*0.1 `30*sin(timer()*0.1) + 20*sin(timer()*0.06)
spr = txh_Buffer(sprite_titleText).spr
rotate sprite spr, ang#
x# = 512 - 320*sin(ang#)
y# = 512 + 320*cos(ang#)
paste sprite spr, x#, y#
logics_drawTime()
weapon_drawGround()
mark_draw()
unit_drawGround()
rem Black Stripes
ink 0xFF000000,0
box 0,0,1025,1
box 0,1023,1024,1025
draw to bitmap 0
rem Second: Draw Render Target to Screen
x = scrw*0.5 - 512
y = scrh*0.5 - 512
if keystate(20) = 0 or 1
ik paste image render_groundTarget, x, y, 1
else
paste image render_groundTarget, x, y
endif
endfunction

function drawTop()
draw_clear()
unit_draw()
weapon_drawBullets()
fx_draw()
draw_render()
rem Help Text
if game_runtime < 3000
centerText(scrh*0.1, "Press H for Help", 0xFFFFD030)
endif
if game_state = STATE__LOST    
media_cls(0,0,0,40)
col = 0xFFFFFF + (int(180 + 75*sin(timer()*0.16 + 90)) << 24)
centerText(scrh*0.25, "You made it to round " + str$(logics.round) + "!", col)
centerText(scrh*0.45, "Your Highscore: " + str$(logics.highscore), col)
centerText(scrh*0.8, "Press Return to Play Again", col)
if returnkey() then logics_restart() : game_state = STATE__PLAY
endif
if game_paused
media_cls(0,0,0,120)
col = 0xFFD030 + (int(180 + 75*sin(timer()*0.16))<< 24)
centerText(scrh*0.1, "- GAME PAUSED -", col)
centerText(scrh*0.62, "ESC to Continue      Return to Quit", col)
endif
if game_state = STATE__PLAY
if keystate(35)
col = 0xFFFFFFFF
centerText(scrh*0.1, "- How To Play -", col)
centerText(scrh*0.22, "You're the Sombrero Guy", col)
centerText(scrh*0.32, "You want to be King of the Hill", col)
centerText(scrh*0.42, "Banish the Blue Guys to win a round", col)
centerText(scrh*0.54, "WASD to Move", col)
centerText(scrh*0.64, "Mouse to use Weapon", col)
centerText(scrh*0.74, "Space to Jump/Stomp", col)
centerText(scrh*0.86, "ESC to Pause/Leave", col)
endif
endif
endfunction


function drawShadow(x#, y#, z#)
dec z#, level_getHeight(x#,y#)
p# = z#/3.0 : if p# < 0 then p# = 0 else if p# > 1 then p# = 1
set sprite alpha spr_Shadow, 255-255*sqrt(p#)
sf# = 1.0 + 0.8*p#
size sprite spr_Shadow, 64*sf#, 32*sf#
offset sprite spr_Shadow, 32*sf#, 16*sf#
paste sprite spr_Shadow, x#, y#
endfunction

function updateMouse()
inc mouse_worldX, mousemovex()
inc mouse_worldY, mousemovey()
if mouse_worldX < 0 then mouse_worldX = 0 else if mouse_worldX > 1024 then mouse_worldX = 1024
if mouse_worldY < 0 then mouse_worldY = 0 else if mouse_worldY > 1024 then mouse_worldY = 1024
mouse_worldZ = level_getHeight(mouse_worldX, mouse_worldY)
position mouse 512,384
endfunction



function clearLevel()
rem Texture
ik paste image on image render_texture, render_textureTrg, 0, 0
rem Bullets
bullet_count = 0
rem Layer
layer_count = 0
endfunction



function scr_update()
if keystate(183)
takeScreenshot()
while keystate(183) : endwhile
endif
endfunction

function takeScreenshot()
img = media_freeImage()
get image img, 0,0,scrw,scrh, 1
set dir "screens"
i = 0
repeat
inc i
f$ = "screen" + fillNum$(i,3) + ".png"
until file exist(f$)=0
save image f$, img
set dir ".."
delete image img
endfunction

function fillNum$(num,places)
s$ = str$(num)
L = len(s$)
for i = L+1 to places
s$ = "0" + s$
next
endfunction s$


function endGame()
end
endfunction

function checkHighscore(score)
f$ = "highscore.hsc"
if file exist(f$)
open to read 1, f$
read long 1, highscore
close file 1
else
highscore = -1
endif
if score > highscore
if file exist(f$) then delete file f$
open to write 1, f$
write long 1, score
close file 1
highscore = score
endif
endfunction highscore


function centerText(y,s$,col)
d3d_starttext
d3d_text 1, scrw/2+1, y+1, 1, s$, (col && 0xFF000000)
d3d_text 1, scrw/2, y, 1, s$, col
d3d_endtext
endfunction
Rem ***** Included Source File *****



function cam_init()
global cam_OutX as float
global cam_OutY as float
global cam_scrw2 as integer : cam_scrw2 = scrw*0.5
global cam_scrh2 as integer : cam_scrh2 = scrh*0.5
endfunction

function cam_worldToScreen(x#, y#, z#)
cam_OutX = cam_scrw2 + x# - 512
cam_OutY = cam_scrh2 + 0.5*(y#-512) - 150.0*z#
endfunction
Rem ***** Included Source File *****


#constant UNIT__GRAVITY = -0.007


type unit_Type
alive as boolean
hp as integer
x as float
y as float
z as float
vz as float
vx as float
vy as float
onGround as boolean
airControl as boolean
heading as boolean
headingAway as boolean
walkDistance as float
yOffset as integer `used for simple walking animation
aiTx as integer
aiTy as integer
nextMarkTime as integer
shockCycles as integer
s as string
endtype



function unit_init()
rem Array
global unit_capacity as integer = 100
global unit_count as integer = 1
dim unit(unit_capacity) as unit_Type
for u = 1 to unit_count
unit(u).alive = 1
unit(u).x = 512
unit(u).y = 512
unit(u).z = level_getHeight(unit(u).x, unit(u).y)
unit(u).nextMarkTime = 0
next
rem ...
endfunction

function unit_control(ID)
rl = (rightkey() or keystate(32)) - (leftkey() or keystate(30))
ud = (upkey() or keystate(17)) - (downkey() or keystate(31))
if rl or ud
ang# = atanfull(rl, ud)
unit_move(ID,ang#)
else
unit_break(ID)
endif
rem Space to Jump
if spacekey()
if unit(ID).onGround
unit(ID).vz = 0.12
endif
endif
remstart
rem CTRL to Mark
if controlkey()
if game_runtime > unit(ID).nextMarkTime
unit(ID).nextMarkTime = game_runtime + 1200
unit__addMark(ID)
endif
endif
remend
rem Mouse to Shoot
if mouseclick() = 1
weapon_fire()
endif
endfunction

function unit_move(ID, ang#)
if unit(ID).onGround or (ID = 1 and unit(ID).airControl)
spd# = 1.0 + 3.5*(ID = 1)
unit(ID).vx = spd#*sin(ang#)
unit(ID).vy = spd#*cos(ang#)
rem Looking Direction
if unit(ID).vx <> 0 then unit(ID).heading = (unit(ID).vx > 0)
if unit(ID).vy <> 0 then unit(ID).headingAway = (unit(ID).vy > 0)
endif
endfunction


function unit_break(ID)
if unit(ID).onGround or (ID = 1 and unit(ID).airControl)
unit(ID).vx = unit(ID).vx * 0.9 `0.0
unit(ID).vy = unit(ID).vy * 0.9 `0.0
endif
endfunction

function unit_drawGround()
for u = 1 to unit_count
unit__drawGround(u)
next
endfunction

function unit__drawGround(u)
drawShadow(unit(u).x, unit(u).y, unit(u).z)
endfunction

function unit_draw()
unit__draw1(1)
for u = 2 to unit_count
if unit(u).alive then unit__draw(u)
next
endfunction

function unit__draw(u)
cam_worldToScreen(unit(u).x, unit(u).y, unit(u).z)
rem Feet
ox# = 6*sin(5*unit(u).walkDistance)
rem paste sprite spr_Foot, cam_OutX + ox#, cam_OutY
rem paste sprite spr_Foot, cam_OutX - ox#, cam_OutY
alpha# = level_getAlpha(unit(u).x, unit(u).y)
draw_addAdvanced(spr_Foot, 0, 0, cam_OutX + ox#, cam_OutY, unit(u).y+1, 0, 20, 20, 0.5, 0.7, 255*alpha#)
draw_addAdvanced(spr_Foot, 0, 0, cam_OutX - ox#, cam_OutY, unit(u).y+1, 0, 20, 20, 0.5, 0.7, 255*alpha#)
rem Rest
dec cam_OutY, -2*unit(u).yOffset
rem if sprite mirrored(spr_Enemy) = unit(u).heading then mirror sprite spr_Enemy
rem if unit(u).headingAway then set sprite frame spr_Enemy, 2 else set sprite frame spr_Enemy, 1
rem paste sprite spr_Enemy, cam_OutX, cam_OutY
draw_addAdvanced(spr_Enemy, 1+unit(u).headingAway, 1-unit(u).heading, cam_OutX, cam_OutY, unit(u).y, 0, 20, 20, 0.5, 1.0, 255*alpha#)
rem box cam_OutX, cam_OutY, cam_OutX+unit(u).hp, cam_OutY+5
rem Target
remstart
sx = cam_OutX : sy = cam_OutY
cam_worldToScreen(unit(u).aiTX, unit(u).aiTY, 1.0)
ink 0xFFFF0000,0
line sx,sy,cam_OutX, cam_OutY
remend
endfunction

function unit__draw1(u)
cam_worldToScreen(unit(u).x, unit(u).y, unit(u).z)
rem Feet
ox# = 6*sin(5*unit(u).walkDistance)
rem set sprite diffuse spr_Foot, 0,0,0
rem paste sprite spr_Foot, cam_OutX + ox#, cam_OutY
rem paste sprite spr_Foot, cam_OutX - ox#, cam_OutY
rem set sprite diffuse spr_Foot, 0,0,255
alpha# = level_getAlpha(unit(u).x, unit(u).y)
draw_addAdvanced(spr_Foot1, 0, 0, cam_OutX + ox#, cam_OutY, unit(u).y+1, 0, 20, 20, 0.5, 0.7, 255*alpha#)
draw_addAdvanced(spr_Foot1, 0, 0, cam_OutX - ox#, cam_OutY, unit(u).y+1, 0, 20, 20, 0.5, 0.7, 255*alpha#)
rem Rest
dec cam_OutY, 2*unit(u).yOffset
rem if sprite mirrored(spr_Player) = unit(u).heading then mirror sprite spr_Player
rem if unit(u).headingAway then set sprite frame spr_Player, 2 else set sprite frame spr_Player, 1
rem paste sprite spr_Player, cam_OutX, cam_OutY
rem paste sprite spr_Hat, cam_OutX, cam_OutY
draw_addAdvanced(spr_Hat, 0, 0, cam_OutX, cam_OutY, unit(u).y, 0, 20, 20, 0.5, 1.0, 255*alpha#)
draw_addAdvanced(spr_Player, 1+unit(u).headingAway, 1-unit(u).heading, cam_OutX, cam_OutY, unit(u).y, 0, 20, 20, 0.5, 1.0, 255*alpha#)
rem Hint when Player is out of Screen
rem ...prevented instead ...
endfunction

function unit_update()
unit__update(1)
for u = 2 to unit_count
if unit(u).alive
unit__update(u)
unit__updateAI(u)
endif
next
rem Player out of screen?
if unit(1).x < 0 then unit(1).x = 0 else if unit(1).x > 1024 then unit(1).x = 1024
if unit(1).y < 0 then unit(1).y = 0 else if unit(1).y > 1024 then unit(1).y = 1024
endfunction

function unit__update(ID)
rem Shocked?
if unit(ID).shockCycles > 0
dec unit(ID).shockCycles
endif
rem Gravity
grav# = UNIT__GRAVITY
if ID = 1
rem Increase Gravity for player falling down -> "stomping"
if unit(ID).vz < 0.0 then grav# = grav#*1.5
endif
inc unit(ID).vz, grav#
inc unit(ID).z, unit(ID).vz
minz# = level_getHeight(unit(ID).x, unit(ID).y)
unit(ID).onGround = 0
if unit(ID).z < minz# 
unit(ID).z = minz#
unit(ID).onGround = 1
unit(ID).airControl = 1
if unit(ID).vz < - 0.025
unit_stomp(ID, -unit(ID).vz*0.9)
if ID > 1
if unit(ID).vx <> 0 or unit(ID).vy <> 0 then layer_add(spr_Blood, unit(ID).x, unit(ID).y, rnd(359), 8000, 1) : unit_damage(ID, -200*unit(ID).vz)
else
if unit(ID).vz < -0.1 then l = layer_add(spr_Stomp, unit(ID).x, unit(ID).y, rnd(359), 8000, 1) : layer(l).alpha = 140 : sound_play(sound_land)
endif
endif
unit(ID).vz = 0.0
endif
rem Movement
inc unit(ID).x, unit(ID).vx
dec unit(ID).y, unit(ID).vy
spd# = sqrt(unit(ID).vx*unit(ID).vx + unit(ID).vy*unit(ID).vy)
inc unit(ID).walkDistance, spd#
if unit(ID).onGround and spd# > 0
unit(ID).yOffset = ((unit(ID).walkDistance mod 50) < 25)
else
unit(ID).yOffset = 0
endif
endfunction

function unit_stomp(ID, f#)
df# = 1000.0
dis# = df#*f#
for u = 2 to unit_count
if u <> ID
if unit(u).onGround
dx = unit(ID).x - unit(u).x
if abs(dx) < dis#
dy = unit(ID).y - unit(u).y
if abs(dy) < dis#
cdis# = sqrt(dx*dx + dy*dy)
if cdis# < dis#
p# = 1.0 - cdis#/dis#
ang# = atanfull(dx, dy)
unit(u).vx = -40*f#*sin(ang#)
unit(u).vy = 40*f#*cos(ang#)
unit(u).vz = f#*0.85
endif
endif
endif
endif
endif
next
endfunction

function unit__updateAI(ID)
if unit(ID).shockCycles > 0 then unit_break(ID) : exitfunction
rem Distance to Target
dx = unit(ID).x - unit(ID).aiTX
dy = unit(ID).y - unit(ID).aiTY
if abs(dx) < 2 and abs(dy) < 2
unit__newTarget(ID)
else
ang# = atanfull(-dx, dy)
unit_move(ID, ang#)
endif
endfunction

function unit__newTarget(ID)
dis = 250 - rnd(rnd(250))
ang = rnd(359)
unit(ID).aiTX = 512 + dis*sin(ang)
unit(ID).aiTY = 512 + dis*cos(ang) 
endfunction


function unit_clearEnemies()
unit_count = 1
endfunction

function unit_damage(ID,dmg#)
if unit(ID).alive
dec unit(ID).hp, dmg#
if unit(ID).hp <= 0
unit(ID).alive = 0
layer_add(spr_Corpse, unit(ID).x, unit(ID).y, rnd(359), 1000, 1)
endif
endif
endfunction


function unit_spawn(x,y)
inc unit_count
if unit_count > unit_capacity
inc unit_capacity
array insert at bottom unit()
endif
ID = unit_count
rem Setup
unit(ID).alive = 1
unit(ID).x = x
unit(ID).y = y
unit(ID).z = level_getHeight(x,y) + 0.3
unit(ID).vx = 0.0
unit(ID).vy = 0.0
unit(ID).vz = 0.0
unit(ID).heading = rnd(1)
unit(ID).hp = 100
unit__newTarget(ID)
endfunction

function unit_kill(ID)
unit(ID).alive = 0
endfunction

function unit_remove(ID)
if ID > 1 and ID <= unit_count
unit(ID) = unit(unit_count)
dec unit_count
endif
endfunction



function unit__addMark(ID)
mark_add(unit(ID).x, unit(ID).y)
endfunction
Rem ***** Included Source File *****


#constant WP_DELAY = 1500


#constant WP_COUNT = 8
#constant WP_NONE = 0
#constant WP_PUSH = 1
#constant WP_BOMB = 2
#constant WP_GRENADE = 3
#constant WP_MINE = 4
#constant WP_AIRSTRIKE = 5
#constant WP_SHOCK = 6
#constant WP_MARK = 7
#constant WP_BAIT = 8

type weapon_Type
name as string
blifetime as integer
usesMouse as boolean = 0
endtype

type bullet_Type
wp as integer
x as float
y as float
z as float
vx as float
vy as float
vz as float
lifetime
endtype


function weapon_init()
global weapon_cursorSprite
weapon_cursorSprite = media_loadSprite("media/cursor.png")
set sprite diffuse weapon_cursorSprite, 255, 0, 0
global currentWeapon as integer = 0
global weapon_nextTime as integer = 0
dim weapon(WP_COUNT) as weapon_Type
weapon(WP_NONE).name = "None"
weapon(WP_BOMB).name = "Bomb"
weapon(WP_PUSH).name = "Blast"
weapon(WP_GRENADE).name = "Grenade"
weapon(WP_AIRSTRIKE).name = "Airstrike"
weapon(WP_MINE).name = "Mine"
weapon(WP_SHOCK).name = "Shock"
weapon(WP_MARK).name = "Repellent"
weapon(WP_BAIT).name = "Attractor"
weapon(WP_PUSH).blifetime = 120
weapon(WP_BOMB).blifetime = 120
weapon(WP_GRENADE).blifetime = -1
weapon(WP_AIRSTRIKE).blifetime = -1
weapon(WP_MINE).blifetime = -1
weapon(WP_SHOCK).blifetime = 300
weapon(WP_PUSH).usesMouse = 1
weapon(WP_GRENADE).usesMouse = 1
weapon(WP_AIRSTRIKE).usesMouse = 1
rem Bullets
global bullet_Count as integer = 0
dim bullet(999) as bullet_Type
rem Sprites
global weapon_bombSprite as integer
global weapon_flameSprite as integer
global weapon_grenadeSprite as integer
global weapon_smoke
global weapon_craterSprite 
global weapon_mineSprite
weapon_bombSprite = media_loadSpriteOff("media/bomb.png",0.5,0.92)
weapon_flameSprite = media_loadAnimation("media/flame_small.png",3,1)
weapon_grenadeSprite = media_loadSprite("media/grenade.png")
weapon_smoke = media_loadSprite("media/blood.png") : set sprite diffuse weapon_smoke, 80,80,80
weapon_craterSprite = media_loadSprite("media/blood.png") : set sprite diffuse weapon_craterSprite, 20,20,20
weapon_mineSprite = media_loadAnimationOff("media/mine.png",2,1,0.5,0.7)
rem Text
global weapon_text as integer = 0
ink 0x00FF0000,0
weapon_text = txh_prepare(weapon_text, "Weapon: -")
endfunction

function weapon_shuffle()
if currentWeapon > 0 then exitfunction
currentWeapon = 1 + rnd(WP_COUNT-1)
`currentWeapon = WP_MARK : if rnd(1) then currentWeapon = WP_BAIT
set text size 40
ink 0xFFF0D000,0
weapon_text = txh_prepare(weapon_text, "Weapon: " + weapon(currentWeapon).name)
mouse_worldX = unit(1).x
mouse_worldY = unit(1).y
endfunction

function weapon_fire()
weapon__fire(currentWeapon, unit(1).x, unit(1).y, unit(1).z, mouse_worldX, mouse_worldY, mouse_worldZ)
currentWeapon = 0
set text size 40
ink 0xA0000000,0
weapon_text = txh_prepare(weapon_text, "Weapon: -")
weapon_nextTime = game_runtime + WP_DELAY
endfunction


function weapon_drawGround()
rem Text
spr = txh_Buffer(weapon_text).spr
rem set sprite diffuse spr, 240,210,0
rem ang# = 0.1*game_runtime + 180
ang# = 10*sin(game_runtime*0.1)
x# = 512 - 340*sin(ang#)
y# = 512 + 340*cos(ang#)
rotate sprite spr, ang#
paste sprite spr, x#, y#
rem Bullet Shadows
for b = 1 to bullet_count
drawShadow(bullet(b).x, bullet(b).y, bullet(b).z)
next b
rem Cursor
if weapon(currentWeapon).usesMouse
rotate sprite weapon_cursorSprite, game_runtime*0.15
paste sprite weapon_cursorSprite, mouse_worldX, mouse_worldY
endif
endfunction

function weapon_drawBullets()
set sprite frame weapon_flameSprite, 1 + ((game_runtime/200) mod 3)
set sprite frame weapon_mineSprite, 1 + ((game_runtime/800) mod 2)
for b = 1 to bullet_count
bullet__draw(b)
next
endfunction

function bullet__draw(ID)
cam_WorldToScreen(bullet(ID).x, bullet(ID).y, bullet(ID).z)
select bullet(ID).wp        
case WP_PUSH
rem paste sprite weapon_smoke, cam_OutX, cam_OutY
draw_add3(weapon_smoke, cam_OutX, cam_OutY, bullet(ID).y, 0)
endcase
case WP_BOMB
rem Bomb
rem paste sprite weapon_bombSprite, cam_OutX, cam_OutY
draw_add3(weapon_flameSprite, cam_OutX-3, cam_OutY-40, bullet(ID).y, 0)
draw_add3(weapon_bombSprite, cam_OutX, cam_OutY, bullet(ID).y, 0)
rem Fire
rem paste sprite weapon_flameSprite, cam_OutX-3, cam_OutY-40
endcase
case WP_GRENADE
rem rotate sprite weapon_GrenadeSprite, 0.2*game_runtime
rem paste sprite weapon_GrenadeSprite, cam_OutX, cam_OutY
draw_add3(weapon_grenadeSprite, cam_OutX, cam_OutY, bullet(ID).y, 0.2*game_runtime)
endcase
case WP_AIRSTRIKE
rem Bomb
rem paste sprite weapon_bombSprite, cam_OutX, cam_OutY
draw_add3(weapon_flameSprite, cam_OutX-3, cam_OutY-40, bullet(ID).y, 0)
draw_add3(weapon_bombSprite, cam_OutX, cam_OutY, bullet(ID).y, 0)
rem Fire
rem paste sprite weapon_flameSprite, cam_OutX-3, cam_OutY-40        
endcase
case WP_MINE
rem paste sprite weapon_mineSprite, cam_OutX, cam_OutY
draw_add3(weapon_mineSprite, cam_OutX, cam_OutY, bullet(ID).y, 0)
endcase
endselect
endfunction


function weapon_updateBullets()
for b = bullet_count to 1 step -1
bullet__update(b)
next
endfunction

function bullet__update(ID)
rem General
if bullet(ID).lifetime > 0 then dec bullet(ID).lifetime
if bullet(ID).lifetime = 0 then weapon__removeBullet(ID) : exitfunction
inc bullet(ID).x, bullet(ID).vx
inc bullet(ID).y, bullet(ID).vy
inc bullet(ID).z, bullet(ID).vz
impact = 0
h# = level_getHeight(bullet(ID).x, bullet(ID).y)
if bullet(ID).z < h# then bullet(ID).z = h# : bullet(ID).vz = 0.0 : impact = 1
grav# = 0.0
rem Specific
select bullet(ID).wp
case WP_PUSH
rem Find Units in Range and push them away
for u = 2 to unit_count
dx = unit(u).x - bullet(ID).x
dy = unit(u).x - bullet(ID).x
dz = 100*(unit(u).z - bullet(ID).z)
dis = dx*dx + dy*dy + dz*dz
if dis < 400
unit(u).vx = bullet(ID).vx
unit(u).vy = -bullet(ID).vy
unit(u).vz = 0.03
endif
next
endcase
case WP_BOMB
maxdis# = 180
maxdis2# = maxdis#*maxdis#
rem Explode?
if bullet(ID).lifetime <= 1
rem Hit units
for u = 1 to unit_count
if unit(u).alive
dx = unit(u).x - bullet(ID).x
dy = unit(u).y - bullet(ID).y
dz = 100*(unit(u).z - bullet(ID).z)
dis = dx*dx + dy*dy + dz*dz
if dis < maxdis2#
p# = sqrt(1.0 - sqrt(dis)/maxdis#)
f# = p#*0.5
ang# = atanfull(dx, dy)
unit(u).vx = 40*f#*sin(ang#)
unit(u).vy = -40*f#*cos(ang#)
unit(u).vz = f#*0.5
unit(u).airControl = 0
endif
endif
next
rem Crater
layer_add(weapon_craterSprite, bullet(ID).x, bullet(ID).y, rnd(359), 15000, 1)
rem Explosion Effect
fx_explosion(bullet(ID).x, bullet(ID).y, bullet(ID).z)
rem Remove
weapon__removeBullet(ID) : exitfunction
endif
grav# = UNIT__GRAVITY
endcase 
case WP_GRENADE
if impact
rem Explode
weapon__explosionImpact(bullet(ID).x, bullet(ID).y, bullet(ID).z, 120, 0.5)
rem Crater
layer_add(weapon_craterSprite, bullet(ID).x, bullet(ID).y, rnd(359), 15000, 1)
rem Explosion Effect
fx_explosion(bullet(ID).x, bullet(ID).y, bullet(ID).z)
rem Remove
weapon__removeBullet(ID) : exitfunction
endif
grav# = UNIT__GRAVITY*0.5
endcase
case WP_AIRSTRIKE
if impact
rem Explode
weapon__explosionImpact(bullet(ID).x, bullet(ID).y, bullet(ID).z, 160, 0.3)
rem Crater
layer_add(weapon_craterSprite, bullet(ID).x, bullet(ID).y, rnd(359), 15000, 1)
rem Explosion Effect
fx_explosion(bullet(ID).x, bullet(ID).y, bullet(ID).z)
rem Remove
weapon__removeBullet(ID) : exitfunction
endif
grav# = UNIT__GRAVITY*0.2                
endcase
case WP_MINE
rem Any Unit in Range?
maxdis2# = 15*15
for u = 2 to unit_count
if unit(u).alive
dx = unit(u).x - bullet(ID).x
dy = unit(u).x - bullet(ID).x
dz = 100*(unit(u).z - bullet(ID).z)
dis = dx*dx + dy*dy + dz*dz
if dis < maxdis2#
exit
endif
endif
next
rem Explode?
if u <= unit_count
rem Explode
weapon__explosionImpact(bullet(ID).x, bullet(ID).y, bullet(ID).z, 120, 0.5)
rem Crater
layer_add(weapon_craterSprite, bullet(ID).x, bullet(ID).y, rnd(359), 15000, 1)
rem Explosion Effect
fx_explosion(bullet(ID).x, bullet(ID).y, bullet(ID).z)
rem Remove
weapon__removeBullet(ID) : exitfunction
endif
grav# = UNIT__GRAVITY
endcase
endselect
if grav# <> 0.0 then inc bullet(ID).vz, grav#
endfunction

function weapon__explosionImpact(x,y,z#,maxdis#,fac#)
maxdis2# = maxdis#*maxdis#
rem Hit units
for u = 1 to unit_count
if unit(u).alive
dx = unit(u).x - x
dy = unit(u).y - y
dz = 100*(unit(u).z - z#)
dis = dx*dx + dy*dy + dz*dz
if dis < maxdis2#
p# = sqrt(1.0 - sqrt(dis)/maxdis#)
f# = p#*fac#
ang# = atanfull(dx, dy)
inc unit(u).vx, 40*f#*sin(ang#)
inc unit(u).vy, -40*f#*cos(ang#)
unit(u).vz = 0.5*f#
unit(u).airControl = 0
unit_damage(u, f#*100)
endif
endif
next    
endfunction



function weapon__fire(ID, x, y, z#, tx, ty, tz#)
dx = tx-x : dy = ty-y : dz# = tz#-z#
ang# = atanfull(dx,dy)
select ID
case WP_PUSH
for i = 1 to 24
angi# = ang# - 40 + 80*rnd(1000)*0.001
weapon_addBullet(ID, x, y, z#, angi#, 6.0, 0.0)
next
endcase
case WP_BOMB
ang# = atanfull(unit(1).vx, -unit(1).vy)
spd# = sqrt(unit(1).vx*unit(1).vx + unit(1).vy*unit(1).vy)*0.5
weapon_addBullet(ID, x, y, z#, ang#, spd#, 0)
endcase
case WP_GRENADE
dis# = sqrt(dx*dx + dy*dy)
weapon_addBullet(ID, x, y, z#, ang#, dis#/66.0, 0.11)
endcase
case WP_MINE
weapon_addBullet(ID, x, y, z#, 0, 0, 0)
endcase
case WP_AIRSTRIKE
for i = 1 to 4
weapon_addBullet(ID, tx + rnd(20) - rnd(20), ty + rnd(20) - rnd(20), 4.0 + rnd(100)*0.01, rnd(359), rnd(100)*0.02, -0.00)
next
endcase
case WP_SHOCK
for u = 2 to unit_count
f# = 1.0 + 0.1*rnd(100)*0.01
unit(u).shockCycles = weapon(ID).blifetime*f#
next
endcase
case WP_MARK
mark_add(x, y)
endcase
case WP_BAIT
mark_addAttractor(x,y)
endcase
endselect
endfunction




function weapon_addBullet(wp,x,y,z#,ang#,spd#,vz#)
inc bullet_Count
ID = bullet_Count
bullet(ID).x = x
bullet(ID).y = y
bullet(ID).z = z#
bullet(ID).vx = spd#*sin(ang#)
bullet(ID).vy = spd#*cos(ang#)
bullet(ID).vz = vz#
bullet(ID).wp = wp
bullet(ID).lifetime = weapon(wp).blifetime
endfunction

function weapon__removeBullet(ID)
bullet(ID) = bullet(bullet_count)
dec bullet_count
endfunction
Rem ***** Included Source File *****
Rem ***** Included Source File *****

#constant TXH__BUFFERS = 5


type txh_BufferType
spr as integer
img as integer
txt as string
endtype


function txh_init()
global txh_Width : txh_Width = scrw
global txh_Height : txh_Height = scrh*0.25
dim txh_buffer(TXH__BUFFERS) as txh_BufferType
for i = 0 to txh__BUFFERS
txh_Buffer(i).img = media_freeImage()
ik create render target txh_Buffer(i).img, txh_Width, txh_Height
txh_Buffer(i).txt = ""
txh_Buffer(i).spr = media_sprite(txh_buffer(i).img)
next
global txh_Current as integer = TXH__BUFFERS
global txh_clearImage as integer
txh_clearImage = media_freeImage()
sz = 11 + 4*txh_Width*txh_Height
make memblock 1, sz+1
write memblock dword 1, 0, txh_Width
write memblock dword 1, 4, txh_Height
write memblock dword 1, 8, 32
for p = 12 to sz step 4
write memblock dword 1, p, 0xFF000000
next
make image from memblock txh_clearImage, 1
global txh_clearImage2 
txh_clearImage2 = media_freeImage()
for p = 12 to sz step 4
write memblock dword 1, p, 0x00000000
next
make image from memblock txh_clearImage2, 1
delete memblock 1
endfunction

function txh_prepare(ID,s$)
rem Cycle through available buffers
if ID = 0
txh_Current = (txh_Current mod TXH__BUFFERS) + 1
ID = txh_Current
endif
rem Draw to buffer 0 temporarily
remstart
ik paste image on image txh_clearImage2, txh_Buffer(0).img, 0, 0
ik set image channel txh_Buffer(0).img, 0xFF000000, 0
ik set image channel txh_Buffer(0).img, 0, 0
ik set image channel txh_Buffer(0).img, 1, 0
ik set image channel txh_Buffer(0).img, 4, 0
draw to image txh_Buffer(0).img
center text txh_Width*0.5, txh_Height*0.5 - text size()*0.5 - 1, s$
draw to bitmap 0
remend
rem Draw to current Buffer
ik paste image on image txh_clearImage2, txh_Buffer(ID).img, 0, 0
ik set image channel txh_Buffer(ID).img, 0xFF000000, 0
draw to image txh_Buffer(ID).img
cls
center text txh_Width*0.5, txh_Height*0.5 - text size()*0.5 - 1, s$
draw to bitmap 0
rem ik paste image on image txh_Buffer(0).img, txh_Buffer(ID).img, 0, 0 `, txh_Effect 
rem Return Sprite ID
r = txh_Buffer(ID).spr
endfunction ID
Rem ***** Included Source File *****
Rem ***** Included Source File *****

function media_init()
make memblock 1, 16
write memblock dword 1, 0, 1
write memblock dword 1, 4, 1
write memblock dword 1, 8, 32
write memblock dword 1, 12, 0xFFFFFFFF
img = media_freeImage()
make image from memblock img, 1
delete memblock 1
spr = media_sprite(img)
global media_boxSprite
media_boxSprite = spr
endfunction


function media_cls(r,g,b,a)
set sprite alpha media_boxSprite, a
set sprite diffuse media_boxSprite, r,g,b
size sprite media_boxSprite, scrw+4,scrh+4
paste sprite media_boxSprite, -2, -2
endfunction

function media_sprite(img)
spr = media_freeSprite()
sprite spr, 0, -8192, img
hide sprite spr
set sprite spr, 0, 1
offset sprite spr, sprite width(spr)/2, sprite height(spr)/2
endfunction spr

function media_loadImage(f$)
img = media_freeImage()
load image f$, img, 1
endfunction img

function media_loadSprite(f$)
spr = media_freeSprite()
sprite spr, 0, -8192, media_loadImage(f$)
hide sprite spr
set sprite spr, 0, 1
offset sprite spr, sprite width(spr)/2, sprite height(spr)/2
endfunction spr

function media_loadSpriteOff(f$,ox#,oy#)
spr = media_freeSprite()
sprite spr, 0, -8192, media_loadImage(f$)
hide sprite spr
set sprite spr, 0, 1
offset sprite spr, sprite width(spr)*ox#, sprite height(spr)*oy#
endfunction spr

function media_loadAnimation(f$,fx,fy)
spr = media_freeSprite()
create animated sprite spr, f$, fx, fy, media_freeImage()
endfunction spr

function media_loadAnimationOff(f$,fx,fy,ox#,oy#)
spr = media_loadAnimation(f$,fx,fy)
offset sprite spr, sprite width(spr)*ox#, sprite height(spr)*oy#
endfunction spr

function media_loadSound(f$)
snd = media_freeSound()
load sound f$, snd
endfunction snd


function media_freeImage()
i = 0 : repeat : inc i : until image exist(i) = 0
endfunction i

function media_freeSprite()
i = 0 : repeat : inc i : until sprite exist(i) = 0
endfunction i

function media_freeMemblock()
i = 0 : repeat : inc i : until memblock exist(i) = 0
endfunction i

function media_freeSound()
i = 0 : repeat : inc i : until sound exist(i) = 0
endfunction i

function media_freeBitmap()
i = 0 : repeat : inc i : until bitmap exist(i) = 0
endfunction i
Rem ***** Included Source File *****



function level_init(img,img2)
global level_width : level_width = image width(img)
global level_height : level_height = image height(img)
dim level_z(level_width, level_height) as float
dim level_view(level_width, level_height) as float
make memblock from image 1, img
make memblock from image 2, img2
p = 12
for y = 1 to level_height
for x = 1 to level_width
level_z(x,y) = memblock byte(1, p)/255.0
level_view(x,y) = 1.0 - memblock byte(2, p)/255.0
inc p, 4
next
next
delete memblock 1
delete memblock 2
endfunction

function level_getHeight(x,y)
if x < 1 or y < 1 or x > level_width or y > level_height
r# = 0.0
else
r# = level_z(x,y)
endif
endfunction r#

function level_getAlpha(x,y)
if x < 1 then x = 1 else if x > level_width then x = level_width
if y < 1 then y = 1 else if y > level_height then y = level_height
af# = 0.2 + 0.8*level_view(x,y)
endfunction af#
Rem ***** Included Source File *****



type gameplayType
round as integer
enemies as integer
tStart as integer
tEnd as integer
prevProgress as float
progress as float
txtSprite as integer
highscore as integer
endtype



function logics_init()
global logics as gameplayType
logics.round = 0
global img_time : img_time = media_loadImage("media/time.png")
ik load effect "media/time.fx", 2
ik set effect technique 2, "Time"
logics.highscore = checkHighscore(0)
logics.txtSprite = txh_prepare(logics.txtSprite, "0")
endfunction

function logics_nextRound()
unit_clearEnemies()
inc logics.round
rem Player
unit(1).x = 512
unit(1).y = 512
unit(1).z = level_getHeight(unit(1).x, unit(1).y) + 0.3
unit(1).vx = 0.0
unit(1).vy = 0.0
unit(1).vz = 0.0
unit(1).alive = 1
unit(1).onGround = 0
rem Weapon
weapon_shuffle()
rem Enemies
logics.enemies = 0 + logics.round
for u = 1 to logics.enemies
ang = rnd(359)
dis = 80 + rnd(200)
x = 512 + dis*sin(ang)
y = 512 + dis*cos(ang)
unit_spawn(x,y)
next
rem Time
logics.tStart = game_runtime
logics.tEnd = logics.tStart + 30000
logics.progress = 0.0
set text size 82
set text to bold
ink 0xFFFFFFFF,0
logics.txtSprite = txh_prepare(logics.txtSprite, str$(logics.round))
sound_play(sound_spawn)
endfunction

function logics_update()
if game_runtime <= logics.tEnd
rem Round still Running
logics.prevProgress = logics.progress
logics.progress = (game_runtime - logics.tStart)/(1.0*(logics.tEnd - logics.tStart))
`if logics_passes(0.333) or logics_passes(0.667) then weapon_shuffle()
if game_runtime > weapon_nextTime then if currentWeapon = 0 then weapon_shuffle()
rem Check for Winning Condition
won = logics_check()
if won
sound_play(sound_won)
logics_nextRound()
endif
else
logics.progress = 1.01
sound_play(sound_lost)
checkHighscore(logics.round)
rem Match is Over -> Lost
game_state = STATE__LOST
endif
endfunction

function logics_restart()
logics.round = 0
clearLevel()
logics_nextRound()
endfunction

function logics_passes(p#)
r = 0
if logics.progress >= p# and logics.prevProgress < p# then r = 1
endfunction r

function logics_drawTime()
ik set effect float 2, "progress", logics.progress
ik paste image img_Time, 512-128, 512-128, 2
spr = txh_Buffer(logics.txtSprite).spr
set sprite diffuse spr, 255,255,255
paste sprite spr, 512, 512
endfunction



function logics_check()
for u = 2 to unit_count
if unit(u).alive
dx = 512 - unit(u).x
dy = 512 - unit(u).y
d = dx*dx + dy*dy
if d < 260*260
exitfunction 0
endif
endif
next
endfunction 1
Rem ***** Included Source File *****

#constant MARK__DURATION = 15000

type mark_Type
x as integer
y as integer
tStart as integer
tEnd as integer
alpha as byte
isAttractor as boolean
endtype


function mark_init()
global mark_Sprite as integer
global mark_sprite2 as integer
mark_Sprite = media_loadSprite("media/blood.png")
set sprite diffuse mark_sprite, 220,170,90
mark_Sprite2 = media_sprite(sprite image(mark_sprite))
set sprite diffuse mark_Sprite2, 0,0,255
scale sprite mark_sprite, 150
scale sprite mark_sprite2, 150
global mark_count as integer = 0
dim mark(99) as mark_Type
endfunction



function mark_add(x,y)
inc mark_count
ID = mark_count
mark(ID).x = x
mark(ID).y = y
mark(ID).tStart = game_runtime
mark(ID).tEnd = mark(ID).tStart + MARK__DURATION
mark(ID).isAttractor = 0
endfunction ID

function mark_addAttractor(x,y)
ID = mark_add(x,y)
mark(ID).isAttractor = 1
endfunction 

function mark_update()
for m = mark_count to 1 step -1
mark__update(m)
next
endfunction

function mark__update(ID)
rem Timing
if game_runtime >= mark(ID).tEnd
rem Delete
mark(ID) = mark(mark_count)
dec mark_count
else
rem Still Alive -> Repell Enemies
if rnd(5) = 0
dis0 = 220
if mark(ID).isAttractor then dis0 = 350
for u = 2 to unit_count
if unit(u).alive
dx = mark(ID).x - unit(u).x
dy = mark(ID).y - unit(u).y
if abs(dx) < dis0 and abs(dy) < dis0                    
if dx*dx + dy*dy < dis0*dis0
if mark(ID).isAttractor
rem Attractor
ang# = atanfull(dx, dy) + rnd(10) - rnd(10) + 180
dis = 30 + rnd(rnd(50))
unit(u).aitx = unit(u).x - dis*sin(ang#) + 15 - rnd(30)
unit(u).aity = unit(u).y - dis*cos(ang#) + 15 - rnd(30)
else
rem Repellent
ang# = atanfull(dx, dy) + rnd(10) - rnd(10)
dis = 20 + rnd(rnd(150))
unit(u).aitx = unit(u).x - dis*sin(ang#) 
unit(u).aity = unit(u).y - dis*cos(ang#) 
endif
endif
endif
endif
next
endif
rem Alpha
p# = (game_runtime - mark(ID).tStart)/(1.0*MARK__DURATION)
if p# < 0.1
mark(ID).alpha = 2550*p#
else
if p# > 0.5
p# = 2*(p#-0.5)
mark(ID).alpha = 255 - 255*p#
else
mark(ID).alpha = 255
endif
endif
endif
endfunction


function mark_angDif(a1,a2)
ad = wrapvalue(a2-a1)
if ad > 180 then dec ad, 360
endfunction ad


function mark_draw()
for m = 1 to mark_count
mark__draw(m)
next
endfunction 

function mark__draw(ID)
`cam_worldToScreen(mark(ID).x, mark(ID).y,)
if mark(ID).isAttractor then spr = mark_Sprite2 else spr = mark_Sprite
set sprite alpha spr, mark(ID).alpha
paste sprite spr, mark(ID).x, mark(ID).y
endfunction
Rem ***** Included Source File *****



type layer_Type
x as integer
y as integer
spr as integer
tStart as integer
tEnd as integer
tDur as integer
alpha as byte
angle as float
stay as boolean
endtype


function layer_init()
global layer_capacity as integer = 512
global layer_count as integer = 0
dim layer(layer_capacity) as layer_Type
endfunction


function layer_add(spr, x, y, angle, duration, stay)
ID = layer__new()
layer(ID).x = x
layer(ID).y = y
layer(ID).spr = spr
layer(ID).tStart = game_runtime
layer(ID).tDur = duration
layer(ID).tEnd = layer(ID).tStart + duration
layer(ID).alpha = 255
layer(ID).angle = angle
layer(ID).stay = 1
endfunction ID


function layer_draw()
for l = layer_count to 1 step -1
layer__draw(l)
next
endfunction

function layer__draw(ID)
if game_runtime > layer(ID).tEnd
rem Delete
layer(ID) = layer(layer_count)
dec layer_count
else
p# = (game_runtime - layer(ID).tStart)/(1.0*layer(ID).tDur)
kill = 0
if layer(ID).stay 
if p# > 0.1
rem Apply
draw to image render_textureTrg
kill = 1
endif
endif
alpha = (layer__getAlpha(p#)*layer(ID).alpha)/255
set sprite alpha layer(ID).spr, alpha
rotate sprite layer(ID).spr, layer(ID).angle
paste sprite layer(ID).spr, layer(ID).x, layer(ID).y
if kill = 1
draw to image render_groundTarget
paste sprite layer(ID).spr, layer(ID).x, layer(ID).y
rem Remove
layer(ID) = layer(layer_count)
dec layer_count
endif
endif
endfunction

function layer__getAlpha(p#)
if p# < 0.1
alpha = 2550*p#
else
if p# > 0.5
p# = (p#-0.5)*2
alpha = 255*(1-p#)
else
alpha = 255
endif
endif
endfunction alpha





function layer__new()
inc layer_count
if layer_count > layer_capacity
inc layer_capacity, 512
array insert at bottom layer(), 512
endif
ID = layer_count
endfunction ID
Rem ***** Included Source File *****


#constant DRAW__SPRITE_STEP = 256

type draw_spriteType
spr as integer
nextSprite as integer
x as integer
y as integer
wy as integer
angle as float
w as integer
h as integer
offx as float
offy as float
alpha as byte
frame as integer
mirrored as boolean
endtype


function draw_init(h, h_buff)
global draw_lines as integer : draw_lines = h + 2*h_buff
global draw_lines1 as integer : draw_lines1 = draw_lines+1
global draw_offset as integer : draw_offset = h_buff
rem Line Array
dim draw_line(draw_lines1) as integer
rem Sprite Array
global draw_sprites as integer = 0
global draw_sprite_capacity as integer = DRAW__SPRITE_STEP 
dim draw_sprite(draw_sprite_capacity) as draw_spriteType
endfunction


function draw_clear()
rem Clear Lines
for l = 0 to draw_lines1
draw_line(l) = 0
next
rem Clear Sprites
draw_sprites = 0
endfunction

function draw_add(spr, x, y, wy, ang#, w, h, ox#, oy#, alpha)
draw_addAdvanced(spr, 0, 0, x, y, wy, ang#, w, h, ox#, oy#, alpha)
endfunction

function draw_add2(spr, frame, mirrored, x, y, wy, ang#, alpha)
draw_addAdvanced(spr, frame, mirrored, x, y, wy, ang#, sprite width(spr), sprite height(spr), sprite offset x(spr)/(1.0*sprite width(spr)), sprite offset y(spr)/(1.0*sprite height(spr)), alpha)
endfunction

function draw_add3(spr, x, y, wy, ang#)
draw_add2(spr, 0, 0, x, y, wy, ang#, 255)
endfunction

function draw_addAdvanced(spr, frame, mirrored, x, y, wy, ang#, w, h, ox#, oy#, alpha)
inc draw_sprites
if draw_sprites > draw_sprite_capacity
inc draw_sprite_capacity, DRAW__SPRITE_STEP
array insert at bottom draw_sprite(), DRAW__SPRITE_STEP
endif
ID = draw_sprites
rem Line
inc wy, draw_offset
if wy < 0 then wy = 0 else if wy > draw_lines1 then wy = draw_lines1
draw_sprite(ID).nextSprite = draw_line(wy)
draw_line(wy) = ID
rem Sprite
draw_sprite(ID).spr = spr
draw_sprite(ID).x = x
draw_sprite(ID).y = y `- draw_offset
draw_sprite(ID).wy = wy
draw_sprite(ID).angle = ang#
draw_sprite(ID).w = w
draw_sprite(ID).h = h
draw_sprite(ID).offx = ox#
draw_sprite(ID).offy = oy#
draw_sprite(ID).alpha = alpha
draw_sprite(ID).frame = frame
draw_sprite(ID).mirrored = mirrored
endfunction

function draw_render()
for y = 0 to draw_lines1
if draw_line(y) > 0 then draw__renderSprite(draw_line(y))
next y
endfunction

function draw__renderSprite(ID)
spr = draw_sprite(ID).spr
set sprite alpha spr, draw_sprite(ID).alpha
rem size sprite spr, draw_sprite(ID).w, draw_sprite(ID).h
rem offset sprite spr, draw_sprite(ID).offx, draw_sprite(ID).offy
rotate sprite spr, draw_sprite(ID).angle
if sprite mirrored(spr) <> draw_sprite(ID).mirrored then mirror sprite spr
if draw_sprite(ID).frame > 0 then set sprite frame spr, draw_sprite(ID).frame
paste sprite spr, draw_sprite(ID).x, draw_sprite(ID).y
rem Next
if draw_sprite(ID).nextSprite > 0 then draw__renderSprite(draw_sprite(ID).nextSprite)
endfunction
Rem ***** Included Source File *****

#constant FX_EXPLOSION = 1


type fx_Type
tp as byte
x as float
y as float
z as float
t0 as integer
t1 as integer
endtype


function fx_init()
global fx_count as integer = 0
dim effect(999) as fx_Type
global fx_explosionSprite
fx_explosionSprite = media_loadAnimationOff("media/explosion.png",6,5, 0.5, 0.5)
endfunction


function fx__add(tp)
inc fx_count
ID = fx_count
effect(ID).tp = tp
endfunction ID



function fx_explosion(x,y,z#)
ID = fx__add(FX_EXPLOSION)
effect(ID).x = x
effect(ID).y = y
effect(ID).z = z#
effect(ID).t0 = game_runtime
effect(ID).t1 = effect(ID).t0 + 1000
sound_play(sound_explosion)
endfunction

function fx_draw()
for f = 1 to fx_count
fx__drawEffect(f)
next 
endfunction

function fx__drawEffect(ID)
if game_runtime > effect(ID).t1
rem Delete
effect(ID) = effect(fx_count)
dec fx_count
else        
rem Still going -> update
p# = (game_runtime - effect(ID).t0)/(1.0*(effect(ID).t1 - effect(ID).t0))
cam_worldToScreen(effect(ID).x, effect(ID).y, effect(ID).z)
select effect(ID).tp
case FX_EXPLOSION                
frame = int(1 + 29.9*p#)
rem set sprite frame fx_explosionSprite, frame
rem paste sprite fx_explosionSprite, cam_OutX, cam_OutY
draw_addAdvanced(fx_explosionSprite, frame, 0, cam_OutX, cam_OutY, effect(ID).y, 0, 0,0,0,0, 255)
endcase
endselect
endif
endfunction
Rem ***** Included Source File *****



type sound_Type
current as integer
endtype

function sound_init()
global sound_playSum as integer = 0
global sound_firstID as integer = 0
global sound_index as integer = 0
dim sound(5) as sound_Type
global sound_won
global sound_lost
global sound_spawn
global sound_land
global sound_explosion
sound_won = sound_load("won.wav")
sound_lost = sound_load("lost.wav")
sound_spawn = sound_load("spawn.wav")
sound_land = sound_load("land.wav")
sound_explosion = sound_load("explosion.wav")
for i = 1 to sound_firstID
set sound volume i, 85
next i
endfunction

function sound_load(f$)
f$ = "media/" + f$
inc sound_firstID
inc sound_index
r = sound_index
load sound f$, sound_firstID
for i = 1 to 2
clone sound sound_firstID + i, sound_firstID
next i
inc sound_firstID, 2
endfunction r


function sound_play(ID)
sound(ID).current = (sound(ID).current + 1) mod 3
s = 3*(ID-1) + 1 + sound(ID).current
if sound playing(s) = 0 then play sound s
inc sound_playSum
endfunction
Rem ***** Included Source File *****


#constant INTRO_TIMESPAN = 5000

global intro_Active as boolean

function SetupIntroScreen()
cls 0xFFFFFF : sync : wait 600
rem Load Media
global intro_image1 
global intro_text1
global intro_text2
global intro_gradient
intro_image1 = loadImage("media/shellfish.png")
intro_text1 = loadSprite("media/shellfishtext.png")
intro_text2 = loadSprite("media/shellfishText2.png")
intro_gradient = loadSprite("media/shellfishGradient.png")
size sprite intro_gradient, sprite width(intro_gradient), 400
offset sprite intro_gradient, 0, 0
rem Box Drawing
make memblock 1, 16
write memblock dword 1, 0, 1
write memblock dword 1, 4, 1
write memblock dword 1, 8, 32
write memblock dword 1, 12, 0xFFFFFFFF
img = freeImage()
make image from memblock img,1
delete memblock 1
spr = freeSprite()
sprite spr, 0, -8192, img
set sprite spr, 0, 1
hide sprite spr
global intro_boxSprite as integer : intro_boxSprite = spr
rem Get Time
global intro_StartTime as integer : intro_StartTime = timer()
global intro_nextUpdate as integer : intro_nextUpdate = intro_StartTime
rem Draw
intro_Active = 1
updateIntroScreen()
endfunction

function FinishIntroScreen()
repeat
r = updateIntroScreen()
until r 
delete image intro_image1
deleteSprite(intro_text1)
deleteSprite(intro_text2)
deleteSprite(intro_gradient)
intro_Active = 0
endfunction

function updateIntroScreen()
tmr = timer()
tdif = tmr - intro_StartTime
if tdif > INTRO_TIMESPAN or returnkey() or escapekey() or spacekey() then exitfunction 1
if tmr < intro_nextUpdate then exitfunction 0
intro_nextUpdate = tmr + 17
p# = tdif/(1.0*INTRO_TIMESPAN)
cx = scrw/2
imgy = scrh*0.4
txy = imgy + 160
rem Background
cls 0xFFFFFF
rem Shellfish Image
paste image intro_image1, cx - image width(intro_image1)/2, imgy - image height(intro_image1)/2, 1
rem Text
paste sprite intro_text1, cx, txy
alpha = 255*( 2.5-3*p# )
if alpha < 0 then alpha = 0 else if alpha > 255 then alpha = 255
set sprite alpha intro_text2, alpha
paste sprite intro_text2, cx, txy
rem Gradient
rem start
gp# = -0.5 + 3*p#
x = scrw*gp#
paste sprite intro_gradient, x, txy-100
ink 0xFFFFFFFF,0
box x + sprite width(intro_gradient), txy-100, scrw+1, scrh
rem end
rem Fade In
alpha = (1.0-3*p#)*255
if alpha > 0
intro_box(0,0,scrw+1,scrh+1, 255,255,255,alpha)
endif
rem Fade Out
alpha = (5*(p#-0.8))*255
if alpha > 0
if alpha > 255 then alpha = 255
intro_box(0,0,scrw+1,scrh+1, 0,0,0,alpha)
endif
sync
endfunction 0



function intro_box(x1,y1,x2,y2, r,g,b,alpha)
size sprite intro_boxSprite, x2-x1, y2-y1
set sprite diffuse intro_boxSprite, r,g,b
set sprite alpha intro_boxSprite, alpha
paste sprite intro_boxSprite, x1,y1
endfunction



function loadImage(img$)
img = freeImage()
load image img$, img, 1
endfunction img

function loadSprite(f$)
img = loadImage(f$)
spr = freeSprite()
sprite spr, 0, -8192, img
set sprite spr, 0, 1
hide sprite spr
offset sprite spr, sprite width(spr)/2, sprite height(spr)/2
endfunction spr

function loadAnimation(f$, fx, fy)
img = loadImage(f$)
spr = freeSprite()
create animated sprite spr, f$, fx, fy, img
set sprite spr, 0, 1
hide sprite spr
offset sprite spr, sprite width(spr)/2, sprite height(spr)/2
endfunction spr

function freeImage()
ID = 150 : repeat : inc ID : until image exist(ID) = 0
endfunction ID

function freeSprite()
ID = 150 : repeat : inc ID : until sprite exist(ID) = 0
endfunction ID

function deleteSprite(spr)
delete image sprite image(spr)
delete sprite spr
endfunction    