Here's my current version, more to come soon!
REM ===============================================
REM Title: Looney Lander Challenge
REM Author: Phaelax
REM Date: March 31, 2011
REM ===============================================
set display mode 1024, 768, 32
randomize timer()
Global GRAV# = 0.01
Global FUEL = 1000
#CONSTANT EPSILON = 0.01
#CONSTANT WHITE = rgb(255,255,255)
#CONSTANT BROWN = rgb(72,43,2)
REM ==== start variables for terrain ========================
Global DEPTH = 5
numOfPts = 2^DEPTH + 1
Global PT_COUNT = numOfPts
Global LANDING_POINT = 0
Global LANDING_WIDTH = 0
dim points(numOfPts,2)
REM ==== end terrain variables ==============================
dim stars(100, 2)
for i = 1 to 100
stars(i, 1) = rnd(screen width())
stars(i, 2) = rnd(screen height())
next i
dim msg$(5)
msg$(1) = "Perfect!" : ` < 0.3
msg$(2) = "Rough Landing" : ` 0.4 > 0.7
msg$(3) = "You got lucky!" : ` 0.7 > 1.0
msg$(4) = "Too hard!" : ` > 1.0
msg$(5) = "Kamikaze!" : ` >= 1.5
Type ShipObject
x as float
y as float
vx as float
vy as float
thrust as float
EndType
ship as ShipObject
ship.thrust = 0.04
ship.x = 200 : ship.y = 133
drawShip(32, 40)
get image 1, 0, 0, 64, 57, 1
sprite 1, 0, 0, 1 : hide sprite 1
offset sprite 1, 32, 40
rem build a random lunar map
buildRandomMap(1)
rem build starting platform
drawPlatform()
get image 3, 0, 0, 100, 70, 1
hide mouse
sync on
sync rate 60
do
cls
rem background sky
box 0, 0, 1024, 768, rgb(0,41,63),rgb(0,23,35),rgb(0,41,63),rgb(0,23,35)
rem player controls
thrust = 0
if hasLanded# = 0
if upkey() and FUEL > 0
dec FUEL
thrust = 1
dec ship.vy, ship.thrust
if ship.vy < -1.5 then ship.vy = -1.5
endif
if ship.vy <> 0
if rightkey()
inc ship.vx, ship.thrust
endif
if leftkey()
dec ship.vx, ship.thrust
endif
endif
endif
rem add gravity to ship's vertical velocity
inc ship.vy, GRAV#
if scancode() = 59 and flag = 0 then buildRandomMap(1) : flag = 1 : hasLanded# = 0
if scancode() = 60 and flag = 0 then buildRandomMap(2) : flag = 1 : hasLanded# = 0
if scancode() = 61 and flag = 0 then buildRandomMap(3) : flag = 1 : hasLanded# = 0
if scancode() = 62 and flag = 0 then buildRandomMap(4) : flag = 1 : hasLanded# = 0
if scancode() = 0 then flag = 0
rem cheap form of wind resistance, pushes
rem horizontal movement back to 0 velocity
if ship.vx > 0 then dec ship.vx, 0.01
if ship.vx < 0 then inc ship.vx, 0.01
if abs(ship.vx) < EPSILON then ship.vx = 0
rem check landing
if ship.y+16 >= points(LANDING_POINT, 2)-1
if ship.x-28 >= points(LANDING_POINT, 1) and ship.x+28 <= points(LANDING_POINT+2, 1)
ship.y = points(LANDING_POINT, 2)-17
if hasLanded# = 0 then hasLanded# = abs(ship.vy)+abs(ship.vx)
if thrust = 0 then ship.vy = 0
endif
endif
rem add velocity forces to ship's current position
inc ship.x, ship.vx
inc ship.y, ship.vy
rem rotate ship
t# = ship.vx/1.5
if t# > 1 then t# = 1
if t# < -1 then t# = -1
a# = 20*t#
rotate sprite 1, a#
rem calculate positions of landing feet
x1 = ship.x + sin(118+a#)*32.249
y1 = ship.y - cos(118+a#)*32.249
x2 = ship.x - sin(62+a#)*32.249
y2 = ship.y + cos(62+a#)*32.249
rem screen boundaries
if ship.x > screen width()+21 then ship.x = -20
if ship.x < -20 then ship.x = screen width()+20
rem check collision
for t = 1 to PT_COUNT-1
rem check if ship's left leg is within this terrain segment's region
if x2 >= points(t, 1) and x2 <= points(t+1, 1)
y# = getHeight#(x2)
rem if ship hit ground
if y2 >= y#
ship.vy = 0
ship.y = y#-16
endif
endif
rem check if ship's right leg is within this terrain segment's region
if x1 >= points(t, 1) and x1 <= points(t+1, 1)
y# = getHeight#(x1)
rem if ship hit ground
if y1 >= y#
ship.vy = 0
ship.y = y#-16
endif
endif
next t
rem platform
if x1 >= 150 and x2 <= 250
if (y1 >= 149 or y2 >= 149) and (y1 < 200 and y2 < 200)
ship.y = 133
ship.vy = 0
endif
endif
rem draw stars
ink rgb(255,255,255),0
for i = 1 to 100
box stars(i, 1), stars(i, 2), stars(i, 1)+1, stars(i, 2)+1
stars(i, 2) = stars(i, 2) - 1
if stars(i, 2) < 0 then stars(i, 2) = screen height() : stars(i, 1) = rnd(screen width())
next i
paste image 3, 150, 150, 1
rem draw the ship
paste sprite 1, ship.x, ship.y
if hasLanded# > 0
set sprite diffuse 1, rnd(255), rnd(255), rnd(255)
endif
if thrust = 1
hasLanded# = 0
t = rnd(10)+10
ink rgb(255,128,0),0
line ship.x-10, ship.y, ship.x, ship.y+t
line ship.x+10, ship.y, ship.x, ship.y+t
ink rgb(255,255,0),0
line ship.x-7, ship.y, ship.x, ship.y+t-5
line ship.x+7, ship.y, ship.x, ship.y+t-5
endif
rem draw the mountains image
paste image 2, 0, screen height()-500, 1
rem draw landing pad
ink 0, 0
box points(LANDING_POINT,1),points(LANDING_POINT,2), points(LANDING_POINT+2,1),points(LANDING_POINT+2,2)+3
inc r#, 0.5
if r# > LANDING_WIDTH-3 then r# = 0
ink rgb(255,255,0),0
box points(LANDING_POINT, 1)+LANDING_WIDTH-r#, points(LANDING_POINT, 2), points(LANDING_POINT, 1)+LANDING_WIDTH-r#+3, points(LANDING_POINT, 2)+3
box points(LANDING_POINT, 1)+LANDING_WIDTH+r#, points(LANDING_POINT, 2), points(LANDING_POINT, 1)+LANDING_WIDTH+r#+3, points(LANDING_POINT, 2)+3
rem Fuel meter
healthBar(412, 10, 200, 30, FUEL/1000.0)
ink 0, 0
center text 513, 19, "Fuel"
ink WHITE, 0
center text 512, 18, "Fuel"
if hasLanded# > 0 then center text screen width()/2, 40, getLandingMessage$(hasLanded#)
set cursor 0,0
print screen fps()
print "Landed: ", hasLanded#
print "VX: ", ship.vx
print "VY: ", ship.vy
print FUEL
sync
loop
function E2DC_Dot(x as integer, y as integer, color as dword )
if x > 0 and x < screen width() and y > 0 and y < screen height()
offset = get pixels pointer()
pitch = get pixels pitch()
bitsPerPixel = bitmap depth(0)/8
pointer = offset + y*pitch + x*bitsPerPixel
*pointer = color
endif
endfunction
function getLandingMessage$(landingValue#)
t$ = "Out of range"
if landingValue# <= 0.3 then t$ = msg$(1)
if landingValue# > 0.3 and landingValue# <= 0.7 then t$ = msg$(2)
if landingValue# > 0.7 and landingValue# <= 1.0 then t$ = msg$(3)
if landingValue# > 1.0 and landingValue# < 1.5 then t$ = msg$(4)
if landingValue# >= 1.5 then t$ = msg$(5)
endfunction t$
REM ===============================================
REM Draws the lunar lander
REM ===============================================
function drawShip(x, y)
ink rgb(255,255,255),0
rem top
DrawPolyCircle(x, y-20, 20, 6, 90)
rem base
box x-20, y-10, x+20, y
rem left leg
line x-20, y-5, x-28, y+8
line x-16, y, x-28, y+8
line x-28, y+8, x-28, y+16
line x-32, y+16, x-24, y+16
rem right leg
line x+20, y-5, x+28, y+8
line x+16, y, x+28, y+8
line x+28, y+8, x+28, y+16
line x+32, y+16, x+24, y+16
endfunction
REM ===============================================
REM Draw polygon with center at [x,y] and
REM a radius of 'r' with 'segs' number of
REM segments and rotated at 'Rot#' angle
REM ===============================================
function DrawPolyCircle(x,y,r,segs,Rot#)
AngStep# = 360.0 / segs
Ang# = Rot#
For s = 1 To segs
OldAng# = Ang#
Ang# = Ang# + AngStep#
x1 = x + (r * Sin(Ang#))
y1 = y + (r * Cos(Ang#))
x2 = x + (r * Sin(OldAng#))
y2 = y + (r * Cos(OldAng#))
line x1,y1,x2,y2
Next s
endfunction
REM ===============================================
REM
REM ===============================================
function buildRandomMap(difficulty)
rem set begin and end points
points(1,2) = screen height()-50
points(PT_COUNT,2) = screen height()-50
segLength = screen width() / (PT_COUNT-1)
for i = 1 to PT_COUNT
points(i, 1) = (i-1)*segLength
next i
rem call the midpoint displacement function
midpoint(points(1,1),points(1,2),points(PT_COUNT,1),points(PT_COUNT,2),screen height()-50,500,0.6,DEPTH,1,PT_COUNT)
rem smooth the terrain
smooth()
rem set landing point
LANDING_POINT = rnd(PT_COUNT-4)+1
points(LANDING_POINT+1, 2) = points(LANDING_POINT, 2)
points(LANDING_POINT+2, 2) = points(LANDING_POINT, 2)
rem easy
if difficulty = 1
points(LANDING_POINT-1, 2) = points(LANDING_POINT, 2) + (rnd(40)+40)
points(LANDING_POINT+3, 2) = points(LANDING_POINT+2, 2) + (rnd(40)+40)
GRAV# = 0.01
endif
rem medium
if difficulty = 2
GRAV# = 0.01
endif
rem hard
if difficulty = 3
points(LANDING_POINT-1, 2) = points(LANDING_POINT, 2) - (rnd(40)+40)
points(LANDING_POINT+3, 2) = points(LANDING_POINT+2, 2) - (rnd(40)+40)
GRAV# = 0.02
endif
rem expert
if difficulty = 4
points(LANDING_POINT-1, 2) = points(LANDING_POINT, 2) - (rnd(50)+100)
points(LANDING_POINT+3, 2) = points(LANDING_POINT+2, 2) - (rnd(50)+100)
GRAV# = 0.03
endif
FUEL = 1000
LANDING_WIDTH = (points(LANDING_POINT+2, 1)-points(LANDING_POINT, 1)) / 2
ship.x = 200 : ship.y = 133
cls
drawPlatform()
if image exist(3) then delete image 3
get image 3, 0, 0, 100, 70, 1
cls
drawTerrain()
if image exist(2) then delete image 2
get image 2, 0, screen height()-500, screen width(), screen height(), 1
endfunction
REM ===============================================
REM
REM ===============================================
function drawTerrain()
segLength# = screen width() / (PT_COUNT-1)
for t = 1 to PT_COUNT-1
rem fill the terrain
ink BROWN,0
y2 = max(points(t, 2), points(t+1, 2))
for x = points(t,1) to points(t+1,1)
t# = (x - points(t, 1)) / segLength#
y = points(t, 2) + (points(t+1, 2)-points(t, 2))*t#
box x, y, x+1, y2
next x
box points(t,1),y2, points(t+1,1),screen height()
next t
rem show landing score
ink WHITE, 0
center text points(LANDING_POINT+1, 1), points(LANDING_POINT+1, 2)+4, "10"
endfunction
REM ===============================================
REM
REM ===============================================
function drawPlatform()
tx = 0 : ty = 0
for i = 0 to 5
ax = 10+i*18
ay = 50+(rnd(40)-20)
if i = 5 then ax = 99 : ay = 3
ink BROWN, 0
for j = tx to ax
l# = ax-tx
t# = (j-tx)/l#
k = ty + (ay-ty)*t#
box j, 0, j+1, k
next j
tx = ax : ty = ay
next i
endfunction
REM ===============================================
REM recursive method using midpoint displacement
REM (x1,y1) - starting point of line
REM (x2,y2) - ending point of line
REM baseline - the base or ground of where the points start
REM height# - places midpoint Y-coord randomly between 0 and height#
REM h# - 0 < h# <= 1 : higher makes a very ridged line, lower makes smoother
REM depth - how many times should the line be split
REM arr1 - used for storing values in array
REM arr2 - used for storing values in array
REM ===============================================
function midpoint(x1,y1,x2,y2,baseline,height#,h#,depth, arr1,arr2)
y = baseline - rnd(height#)
arrIndex = arr1 + (arr2-arr1)/2
points(arrIndex,2) = y
dec depth, 1
if depth > 0
midpoint(x1,y1,x,y,baseline,height#*h#,h#,depth,arr1,arrIndex)
midpoint(x,y,x2,y2,baseline,height#*h#,h#,depth,arrIndex,arr2)
endif
endfunction
REM ===============================================
REM Smooths out terrain
REM ===============================================
function smooth()
rem define an array to temporarily store the points.
local dim temp(PT_COUNT)
for i = 2 to PT_COUNT - 1
y = points(i,2)
y1 = points(i-1,2)
y2 = points(i+1,2)
temp(i) = (y+y1+y2)/3
next i
for i = 2 to PT_COUNT - 1
points(i,2) = temp(i)
next i
endfunction
REM ===============================================
REM Returns the height on the terrain at point X
REM ===============================================
function getHeight#(x as float)
mapWidth# = points(PT_COUNT, 1) - points(1, 1)
segLength# = mapWidth# / (PT_COUNT-1)
p1 = ceil(x / segLength#)
if p1 = 0 then p1 = 1
p2 = p1+1
t# = (x - points(p1, 1)) / segLength#
h# = points(p1, 2) + (points(p2, 2)-points(p1, 2))*t#
endfunction h#
REM ===============================================
REM x,y is the upper left corner of meter
REM P# ranges from 0 to 1
REM ===============================================
function healthBar(x, y, width, height, P#)
rem gradient bar
seg = width / 3
box x, y, x+seg, y+height, rgb(255,0,0),rgb(255,0,0),rgb(255,128,0),rgb(255,128,0)
box x+seg, y, x+seg+seg, y+height, rgb(255,128,0),rgb(255,128,0), rgb(255,255,0),rgb(255,255,0)
box x+seg+seg, y, x+width, y+height, rgb(255,255,0),rgb(255,255,0), rgb(0,255,0),rgb(0,255,0)
rem empty bit
ink rgb(0,24,35),0
box x+width*P#, y, x+width, y+height
rem highlight
c1 = 0xCCFFFFFF
c2 = 0x33FFFFFF
box x, y, x+width, y+height*0.5, c2,c1,c2,c1
endfunction
REM ******************************************************************************************
REM
REM ENHANCED 2D COMMANDS
REM
REM ******************************************************************************************
REM **************************************************
REM Xiaolin Wu's line algorithm.
REM **************************************************
function E2DC_Line_AA_ALPHA(x1, y1, x2, y2, color as dword)
local dx as float
local dy as float
local xend as float
local yend as float
local xgap as float
local ygap as float
local xpxl1 as float
local ypxl1 as float
local xpxl2 as float
local ypxl2 as float
local intery as float
local interx as float
red = rgbr(color)
green = rgbg(color)
blue = rgbb(color)
dx = x2-x1
dy = y2-y1
if abs(dx) > abs(dy)
rem handle horizontal lines
if x2 < x1
ax = x1
x1 = x2
x2 = ax
ay = y1
y1 = y2
y2 = ay
endif
gradient# = dy / dx
rem handle first endpoint
xend = ceil(x1)
yend = y1 + gradient# * (xend-x1)
xgap = 1.0 - fract#(x1 + 0.5)
xpxl1 = xend : `used in main loop
ypxl1 = int(yend)
f# = 1-fract#(yend)*xgap : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box xpxl1, ypxl1, xpxl1+1, ypxl1+1, c, c, c, c
rem brightness: fract#(yend)*xgap
f# = fract#(yend)*xgap : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box xpxl1, ypxl1+1, xpxl1+1, ypxl1+2, c, c, c, c
intery = yend + gradient# : `first y-intersection for main loop
rem handle second endpoint
xend = ceil(x2)
yend = y2 + gradient# * (xend-x2)
xgap = 1.0 - fract#(x2 + 0.5)
xpxl2 = xend : `used in main loop
ypxl2 = int(yend)
f# = 1-fract#(yend)*xgap : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box xpxl2, ypxl2, xpxl2+1, ypxl2+1, c, c, c, c
f# = fract#(yend)*xgap : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box xpxl2, ypxl2+1, xpxl2+1, ypxl2+2, c, c, c, c
rem main loop
a = xpxl1+1
b = xpxl2-1
for x = a to b
f# = 1-fract#(intery) : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box x, intery, x+1, intery+1, c, c, c, c
f# = fract#(intery) : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box x, intery+1, x+1, intery+2, c, c, c, c
intery = intery + gradient#
next x
else
rem handle vertical lines
if y2 < y1
ax = x1
x1 = x2
x2 = ax
ay = y1
y1 = y2
y2 = ay
endif
gradient# = dx / dy
rem handle first endpoint
yend = ceil(y1)
xend = x1 + gradient# * (yend-y1)
ygap = 1.0 - fract#(y1 + 0.5)
xpxl1 = int(xend)
ypxl1 = yend
f# = 1-fract#(xend)*ygap : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box xpxl1, ypxl1, xpxl1+1, ypxl1+1, c, c, c, c
intery = intery + gradient#
f# = fract#(xend)*ygap : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box xpxl1, ypxl1+1, xpxl1+1, ypxl1+2, c, c, c, c
interx = xend + gradient# : `first y-intersection for main loop
rem handle second endpoint
yend = ceil(y2)
xend = x2 + gradient# * (yend-y2)
ygap = fract#(y2 + 0.5)
xpxl2 = int(xend)
ypxl2 = yend
f# = 1-fract#(xend)*ygap : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box xpxl2, ypxl2, xpxl2+1, ypxl2+1, c, c, c, c
f# = fract#(xend)*ygap : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box xpxl2, ypxl2+1, xpxl2+1, ypxl2+2, c, c, c, c
rem main loop
a = ypxl1+1
b = ypxl2-1
for y = a to b
f# = 1-fract#(interx) : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box interx, y, interx+1, y+1, c, c, c, c
f# = fract#(interx) : `brightness
alpha = 255*f#
c = E2DC_ARGB(alpha, red, green, blue)
box interx+1, y, interx+2, y+1, c, c, c, c
interx = interx + gradient#
next y
endif
endfunction
REM **************************************************
REM Just a little helper function
REM **************************************************
function fract#(x as float)
a# = x - int(x)
endfunction a#
REM **************************************************
REM Returns a color with an alpha value
REM **************************************************
function E2DC_ARGB(a,r,g,b)
local c as dword
c = (a*16777216)+(r*65536)+(g*256)+b
endfunction c