Created
April 21, 2014 20:40
-
-
Save jrm2k6/11155844 to your computer and use it in GitHub Desktop.
shoot the rectangle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Keyboard | |
import Window | |
import Debug | |
(gameWidth,gameHeight) = (600,800) | |
(halfWidth,halfHeight) = (300,400) | |
type Input = {space:Bool, dir:Int, delta:Time} | |
type Spaceship = {x:Float, y:Float, rotation:Float} | |
type Ball = {x:Float, y:Float, vx:Float, vy:Float, angle:Float, status:BallState} | |
type Enemy = {x:Float, y:Float, vx:Float, vy:Float} | |
type Game = {spaceship:Spaceship, balls:[Ball], enemy:Enemy, state:State} | |
defaultGame : Game | |
defaultGame = | |
{ spaceship = {x=0, y=-halfHeight+40, rotation=90}, | |
balls = [], | |
enemy = {x=0, y=halfHeight-40, vx=200, vy=200}, | |
state = NotShooting | |
} | |
defaultBall : Float -> Ball | |
defaultBall a = {x=0, y=-halfHeight+40, vx=600, vy=600, angle=a, status=Flying} | |
data State = Shooting | NotShooting | |
data BallState = Flying | OutOfBounds | Colliding | ReadyToFly | |
defaultSpaceship : Float -> Spaceship | |
defaultSpaceship h = {x=0, y=h + 40, rotation=90} | |
delta = inSeconds <~ fps 35 | |
input = sampleOn delta (Input <~ Keyboard.space | |
~ lift .x Keyboard.arrows | |
~ delta) | |
drawSpaceship : Spaceship -> Color -> Form | |
drawSpaceship spaceship clr = (rotate (degrees spaceship.rotation) ( move (spaceship.x, spaceship.y) (filled clr (ngon 3 20)))) | |
drawEnemy : Enemy -> Color -> Form | |
drawEnemy enemy clr = move (enemy.x, enemy.y) (filled clr (ngon 4 15)) | |
drawBall : Ball -> Color -> Form | |
drawBall ball clr = ( move (ball.x, ball.y) (filled clr (circle 8))) | |
stepGame : Input -> Game -> Game | |
stepGame ({space, dir, delta} as input) ({spaceship, balls, enemy, state} as game) = | |
let spaceship' = moveSpaceship spaceship delta dir | |
balls' = addBall balls space delta spaceship.rotation state enemy | |
enemy' = moveEnemy enemy delta balls | |
state' = updateState state space | |
in { game | spaceship <- spaceship', | |
balls <- balls', | |
enemy <- enemy', | |
state <- state'} | |
addBall : [Ball] -> Bool -> Time -> Float -> State -> Enemy -> [Ball] | |
addBall balls isSpacePressed delta angle state enemy = let balls' = if isSpacePressed then balls ++ [defaultBall angle] else balls | |
in updateAllBalls balls' delta angle state enemy | |
updateAllBalls : [Ball] -> Time -> Float -> State -> Enemy -> [Ball] | |
updateAllBalls balls delta angle state enemy = filter (\b -> b.status /= Colliding && b.status /= OutOfBounds) (map (\b -> moveBall b delta state angle (isColliding enemy b)) balls) | |
updateState : State -> Bool -> State | |
updateState state isSpacePressed = case (state, isSpacePressed) of | |
(Shooting, _) -> Shooting | |
(NotShooting, True) -> Shooting | |
(NotShooting, False) -> NotShooting | |
(_,_) -> NotShooting | |
{-moveBall : Ball -> Time -> State -> Float -> Bool -> Ball | |
moveBall ({x,y,vx,vy} as ball) delta state angle isColliding = let y' = if state == Shooting && y < halfHeight && not isColliding then y + vy * delta * sin (convertAngleToRadian ball.angle) | |
else -halfHeight+40 | |
x' = if state == Shooting && x > -halfWidth && x < halfWidth && not isColliding then x + vx * delta * cos (convertAngleToRadian ball.angle) | |
else 0 | |
status' = updateBallState ball isColliding | |
angle' = if state == NotShooting then angle else ball.angle | |
in {ball | x <- x', y <- y', angle <- angle', status <- status' } | |
-} | |
moveBall : Ball -> Time -> State -> Float -> Bool -> Ball | |
moveBall ({x,y,vx,vy} as ball) delta state angle isColliding = let (x',y') = updateBallPosition ball state delta | |
status' = updateBallState ball isColliding | |
angle' = if state == NotShooting || ball.status == ReadyToFly then angle else ball.angle | |
in {ball | x <- x', y <- y', angle <- angle', status <- status' } | |
updateBallState : Ball -> Bool -> BallState | |
updateBallState ball isColliding = if isColliding then Colliding | |
else if ball.y > halfHeight || ball.x < -halfWidth || ball.x > halfWidth then OutOfBounds | |
else if ball.status == ReadyToFly then Flying | |
else Flying | |
updateBallPosition : Ball -> State -> Time -> (Float,Float) | |
updateBallPosition ({x,y,vx,vy,angle,status} as ball) state delta= case (x, y, status, state) of | |
(_,_,ReadyToFly, Shooting) -> (0, -halfHeight+40) | |
(_,_,Flying,NotShooting) -> (0, -halfHeight+40) | |
(_,_,Flying,Shooting) -> (x + vx * delta * cos (convertAngleToRadian angle), y + vy * delta * sin (convertAngleToRadian ball.angle)) | |
convertAngleToRadian angleInDegree = angleInDegree / 180 * pi | |
moveSpaceship : Spaceship -> Time -> Int -> Spaceship | |
moveSpaceship spaceship delta angle = let rotation' = spaceship.rotation - ((toFloat angle)) | |
in {spaceship | rotation <- rotation'} | |
moveEnemy : Enemy -> Time -> [Ball] -> Enemy | |
moveEnemy ({x,y,vx,vy} as enemy) delta balls = let y' = if (y > -halfHeight && not (checkCollisions enemy balls)) || isEmpty balls | |
then y - vy * delta | |
else halfHeight-40 | |
in {enemy | y <- y'} | |
checkCollisions : Enemy -> [Ball] -> Bool | |
checkCollisions enemy balls = any (\b -> isColliding enemy b) balls | |
isColliding : Enemy -> Ball -> Bool | |
isColliding enemy ball = (abs (enemy.x - ball.x)) < 30 && (abs (enemy.y - ball.y)) < 30 | |
gameState : Signal Game | |
gameState = foldp stepGame defaultGame input | |
showRotation : Spaceship -> String | |
showRotation {x, y, rotation} = "Rotation " ++ show rotation | |
display : (Int, Int) -> Game -> Input -> Element | |
display (w,h) {spaceship, balls, enemy, state} i = collage w h [ | |
move (0, 0) (filled yellow (rect gameWidth gameHeight)), | |
move (0, 0) (filled green (rect 5 5)), | |
move (0, 0) (toForm (asText (state))), | |
(drawSpaceship spaceship red), | |
(drawEnemy enemy purple), | |
(displayBalls balls)] | |
displayBalls : [Ball] -> Form | |
displayBalls balls = group (map (\b -> drawBall b blue) balls) | |
main = lift3 display Window.dimensions gameState input |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment