Skip to content

Instantly share code, notes, and snippets.

@jrm2k6
Created April 21, 2014 20:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrm2k6/11155844 to your computer and use it in GitHub Desktop.
Save jrm2k6/11155844 to your computer and use it in GitHub Desktop.
shoot the rectangle
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