Skip to content

Commit

Permalink
feat (Actions/Game): added random object placement
Browse files Browse the repository at this point in the history
  • Loading branch information
smallhadroncollider committed Jun 10, 2018
1 parent f5a7645 commit 360d556
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 23 deletions.
4 changes: 2 additions & 2 deletions roadmap.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
## Features

- Randomise obstacle placement
- Jump animation should be controlled by fps

## Bugs

- Collision detection fails at high speeds

## Done

- Collision detection
- Randomise obstacle placement
- Collision detection fails at high speeds
22 changes: 13 additions & 9 deletions src/Actions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Actions (
import ClassyPrelude

import Control.Lens ((&), (^.), (.~), (%~), (+~))
import Types (Player, Direction(..), UI, Direction(..), State(..), Obstacles, reset, player, position, obstacles, state, speed)
import Types (Player, Direction(..), UI, Direction(..), State(..), Obstacles, reset, player, position, obstacles, state, speed, dimensions)
import Loop (fps)

restart :: UI -> UI
Expand All @@ -20,26 +20,30 @@ jump ui = case ui ^. state of
Playing -> ui & player %~ startJump
_ -> ui

frame :: UI -> UI
frame ui = case ui ^. state of
Playing -> nextFrame ui
frame :: Int -> UI -> UI
frame rand ui = case ui ^. state of
Playing -> nextFrame rand ui
_ -> ui

-- internal functions
nextFrame :: UI -> UI
nextFrame ui = ui
nextFrame :: Int -> UI -> UI
nextFrame rand ui = ui
& state .~ st
& player %~ animate
& position +~ distance
& obstacles %~ trimObstacles ui
& obstacles %~ generateObstacles rand ui

where gameOver = collision ui
distance = if gameOver then 0 else 1 / fromIntegral fps * fromIntegral (ui ^. speed)
st = if gameOver then GameOver else Playing

trimObstacles :: UI -> Obstacles -> Obstacles
trimObstacles ui = filter (> pos)
generateObstacles :: Int -> UI -> Obstacles -> Obstacles
generateObstacles rand ui obs = if shouldAppend then filtered ++ [final + rand] else filtered
where pos = floor $ ui ^. position
(w, _) = ui ^. dimensions
final = fromMaybe 0 $ lastMay obs
shouldAppend = pos + w > final
filtered = filter (> pos) obs

collision :: UI -> Bool
collision ui = next < pos + 2 && next > pos - 2 && jumpHeight < 2
Expand Down
16 changes: 10 additions & 6 deletions src/Game.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ module Game (play) where

import ClassyPrelude

import Control.Lens ((&), (.~))
import Control.Lens ((&), (.~), (^.))
import System.Random (getStdRandom, randomR)

import Brick
import Brick.BChan (newBChan)
Expand All @@ -12,13 +13,16 @@ import qualified Actions (restart, jump, frame)
import Attr (attr)
import Draw (draw)
import Loop (loop)
import Types (Name, UI, Tick(Tick), create, dimensions)
import Types (Name, UI, Tick(Tick), create, speed, dimensions)
import Window (getDimensions)

handleTick :: UI -> EventM Name (Next UI)
handleTick ui = do
let sp = ui ^. speed
let minDistance = sp `div` 2
s <- liftIO getDimensions
continue $ Actions.frame (ui & dimensions .~ s)
r <- liftIO $ getStdRandom (randomR (minDistance, sp * 3))
continue $ Actions.frame r (ui & dimensions .~ s)

handleEvent :: UI -> BrickEvent Name Tick -> EventM Name (Next UI)
handleEvent ui (VtyEvent (EvKey (KChar 'q') [])) = halt ui
Expand All @@ -40,7 +44,7 @@ getSpeed :: IO Int
getSpeed = do
args <- getArgs
return $ case args of
[speed] -> fromMaybe 10 $ readMay speed
[sp] -> fromMaybe 10 $ readMay sp
_ -> 10


Expand All @@ -49,5 +53,5 @@ play = do
chan <- newBChan 1
loop chan
s <- getDimensions
speed <- getSpeed
void $ customMain (mkVty defaultConfig) (Just chan) app $ create s speed
sp <- getSpeed
void $ customMain (mkVty defaultConfig) (Just chan) app $ create s sp
14 changes: 8 additions & 6 deletions src/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module Types (

import ClassyPrelude

import Control.Lens ((.~), makeLenses)
import Control.Lens ((&), (^.), (.~), makeLenses)

import Window (Dimensions)

Expand All @@ -44,16 +44,18 @@ create s sp = UI {
_position = 0
, _dimensions = s
, _player = (Level, 0)
, _obstacles = [fst s, fst s + 18 .. 300]
, _obstacles = [fst s]
, _state = Playing
, _speed = sp
}

reset :: UI -> UI
reset = (state .~ Playing)
. (player .~ (Level, 0))
. (obstacles .~ [20, 38 .. 300])
. (position .~ 0)
reset ui = ui
& state .~ Playing
& player .~ (Level, 0)
& obstacles .~ [fst s]
& position .~ 0
where s = ui ^. dimensions

data Tick = Tick
type Name = ()

0 comments on commit 360d556

Please sign in to comment.