Skip to content

Instantly share code, notes, and snippets.

@dobesv
Created January 30, 2013 19:09
Show Gist options
  • Save dobesv/4675836 to your computer and use it in GitHub Desktop.
Save dobesv/4675836 to your computer and use it in GitHub Desktop.
Moving the buildings to their own variables allows compilation to complete but it still takes 65 seconds.
import Automaton (init')
import JavaScript
import JavaScript.Experimental
foreign import jsevent "provideRobotAnimation"
(castElementToJSElement (spacer 0 0))
jsRobotAnimation :: Signal JSElement
robotAnimation = lift (castJSElementToElement 262 373) jsRobotAnimation
cropImage url origWidth origHeight left top width height =
collage width height
[sprite url origWidth origHeight (origWidth `div` 2 - left, origHeight `div` 2 - top)]
crop element left top width height =
let eltWidth = widthOf element
eltHeight = heightOf element
in collage width height
[toForm (eltWidth `div` 2 - left, eltHeight `div` 2 - top) element]
bldgSheet = {width=1800,height=400,src="images/CityBurner_Buildings_V2.png"}
bldg left top width height hitMask =
{width = width, height = height,
image = cropImage bldgSheet.src bldgSheet.width bldgSheet.height left top width height,
hitMask = move (0-left) (0-top) $ filled green hitMask}
b1=(bldg 0 249 141 151 $
polygon [(3,398), (4,325), (13,320), (13,293), (96,294), (94,308), (112,320),
(112,340), (138,341), (137,399)] (0,0))
b2=(bldg 178 61 86 339 $
polygon [(180,400), (180,193), (190,189), (190,149), (203,139), (203,118),
(240,118), (241,149), (260,150), (262,194), (262,400)] (0,0))
b3=(bldg 307 204 120 196 $
polygon [(310,400), (310,299), (342,268), (342,229), (348,229), (349,214),
(366,209), (388,220), (390,226), (403,227), (404,233), (411,243),
(424,250), (421,259), (425,265), (425,400)] (0,0))
b4=(bldg 479 186 86 214 $
polygon [(483,400), (486,226), (507,197), (557,214), (557,286), (560,286),
(561,400)] (0,0))
b5=(bldg 632 232 86 168 $
polygon [(634,400), (634,255), (643,251), (643,237), (655,237), (663,247),
(709,242), (714,400)] (0,0))
b6=(bldg 782 285 74 115 $
polygon [(784,400), (784,295), (854,295), (853,400)] (0,0))
b7=(bldg 904 322 143 78 $
polygon [(906,400), (906,338), (926,324), (951,339), (951,388), (957,388),
(957,338), (992,323), (1013,337), (1036,331), (1046,340), (1045,400)] (0,0))
b8=(bldg 1057 8 120 392 $
polygon [(1059,400), (1059,221), (1065,221), (1066, 175), (1073,174),
(1073,163), (1086,152), (1086,124), (1091,120), (1092,101),
(1099,100), (1111,80), (1113,9), (1117,81), (1128,99),
(1137,99), (1145,109), (1145,131), (1153,132), (1157,136),
(1160,145), (1161,161), (1172,161), (1173,179), (1173,400)] (0,0))
b9=(bldg 1206 228 133 172 $
polygon [(1208,400), (1210,243), (1234,243), (1234,229), (1245,229), (1244,241),
(1329,244), (1333,400)] (0,0))
ba=(bldg 1374 25 90 375 $
polygon [(1376,400), (1376,299), (1382,270), (1383,166), (1386,166), (1386,136),
(1409,89), (1414,86), (1415,25), (1423,87), (1433,87), (1440,122),
(1445,122), (1462,197), (1462,209), (1457,214), (1457,263),
(1462,267), (1462,290), (1457,296), (1458,348),(1463,351),(1463,400)] (0,0))
bb=(bldg 1504 294 140 106 $
polygon [(1509,400), (1509,337), (1513,337), (1515,317), (1576,313), (1579,316),
(1579,357), (1583,355), (1586,319), (1630,318), (1630,337), (1641,336),
(1641,400)] (0,0))
bc=(bldg 1656 324 134 76 $
polygon [(1660,400), (1660,368), (1667,362), (1665,341), (1687,326),
(1704,342), (1724,328), (1746,342), (1762,325), (1785,343),
(1785,400)] (0,0))
bldgs = [b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc]
bldgCount = length bldgs
allBldgsWidth = foldr (\bldg w -> bldg.width + w) 0 bldgs
f >>> g = g . f
x |> g = g x
half x = x `div` 2
-- Find the nth element of a list, or Nothing if the list is too short
nthMaybe n lst =
case lst of
[] -> Nothing
x:xs -> if n == 0 then Just x else nthMaybe (n-1) xs
nthBuilding n = case (nthMaybe (n `mod` bldgCount) bldgs) of
Just b -> b
Nothing -> head bldgs
takeWhile p lst =
case lst of
[] -> []
x:xs -> if p x then x : (takeWhile p xs) else []
dropWhile p lst =
case lst of
[] -> []
x:xs -> if p x then (dropWhile p xs) else lst
updateGame input oldState =
let {t,mouseDown,mousePosition} = input
oldFires = oldState.oldFires
robotElt = input.jselts.robot
(mouseX, mouseY) = mousePosition
gameWidth = 1024
gameHeight = 630
speed = 0.15
distanceTravelled = truncate (t * speed)
(cityShapes,cityHitMasks) =
let currentLoopX = distanceTravelled `mod` allBldgsWidth
buildingsOnScreen loopX bX bs n =
if bX - loopX > gameWidth then ([],[])
else case bs of
[] -> if n < 10 then buildingsOnScreen loopX bX bldgs (n+1) else ([],[])
x:xs -> let rest = buildingsOnScreen loopX (bX + x.width) xs n
in if ((bX + x.width) < loopX) then rest
else let bldgLeft = bX - loopX
bldgTop = gameHeight - x.height
form = toForm (bldgLeft + (half x.width),bldgTop + (half x.height)) x.image
hitMask = move bldgLeft bldgTop x.hitMask
in (form : (fst rest), hitMask : (snd rest))
in buildingsOnScreen currentLoopX 0 bldgs 1
headCenter = (292,410)
monsterShapes = [robotElt]
laserShapes = if mouseDown then [solid red (segment headCenter mousePosition)] else []
fireRadius since = (sqrt (t - since))*speed*5
fireVisible {worldX,since} = worldX > distanceTravelled - (fireRadius since)
fireShape {worldX,worldY,since} =
let radius = fireRadius since
x = worldX - distanceTravelled
in filled red (circle radius (x,worldY))
oldVisibleFires = filter fireVisible oldFires
newFire = {worldX=mouseX + distanceTravelled,
worldY=mouseY,
since=t}
mouseOverBuilding = any (isWithin mousePosition) cityHitMasks
mouseOverFire = any (isWithin mousePosition) (map fireShape oldVisibleFires)
timeSinceLastFire = case oldFires of
f:fs -> t - f.since
[] -> 1000
newFires = if mouseDown && mouseOverBuilding && (not mouseOverFire) && (timeSinceLastFire > 333)
then newFire : oldVisibleFires else oldVisibleFires
newState = {oldFires=newFires}
fireShapes = map fireShape newFires
shapes = monsterShapes ++ cityShapes ++ laserShapes ++ fireShapes
gameView = collage gameWidth gameHeight shapes
debugView () =
let debugTextView = show >>> toText >>> (Text.color green) >>> Text.monospace >>> Graphics.text
views = [debugTextView input,
debugTextView oldState,
debugTextView newState,
debugTextView bldgs]
in flow down views
newView = gameView --`above` (debugView ())
in (newView,newState)
mkjselts r = {robot=r}
jselts = lift mkjselts robotAnimation
mkinput t mouseDown mousePosition jselts = let r = {t=t, mouseDown=mouseDown, mousePosition=mousePosition, jselts=jselts} in r
input = lift4 mkinput (every 0.1) Mouse.isDown Mouse.position jselts
startState = {oldFires=[],buildings=[]}
gameAutomaton = init' startState updateGame
main = Automaton.run gameAutomaton input
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment