packages feed

YACPong-0.1: GameState.hs

{-
    The MIT License

    Copyright (c) 2010 Korcan Hussein.

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
-}
{-# LANGUAGE TemplateHaskell, TypeOperators, FlexibleContexts #-}
module GameState where

import Prelude hiding (id, (.), mod)

import System.Random

import Control.Category
import Control.Monad.Reader
import Control.Monad.State hiding (get)
--import qualified Control.Monad.State as MState (get,put)

import Data.Word
import Data.Record.Label

import Graphics.UI.SDL (Surface)
import Graphics.UI.SDL.TTF (Font)
import Graphics.UI.SDL.Mixer (Chunk)

import Labels
import Vector2
import Collision
import Timer
import Consts

--type Vector2f = (Float, Float)
data Player = Player1 | Player2
    deriving (Eq, Show)

data GameLoopState =
      Win Player
    | Init Player
    | Play
    | Paused

data Ball = Ball {
    _pos :: Vector2f,
    _vel :: Vector2f
} deriving (Eq, Show)

data Paddle = Paddle {
    _pPos    :: Vector2f,
    _yVel    :: Float,
    _lastPos :: Float
} deriving (Eq, Show)

data Stats = Stats {
    _player1Count :: Integer,
    _player2Count :: Integer
} deriving (Eq, Show)

data GameData = GameData {
    _paddle1   :: Paddle,
    _paddle2   :: Paddle,
    _ball      :: Ball,
    _stats     :: Stats,
    _ticker    :: Timer,
    _state     :: GameLoopState,
    _randGen   :: StdGen
}

data GameConfig = GameConfig {
    _font         :: Font,
    _screen       :: Surface,
    _ballSprite   :: Surface,
    _paddleSprite :: Surface,
    _pausedSprite :: Surface,
    _wallBounce   :: Chunk,
    _paddleBounce :: Chunk,
    _winSound     :: Chunk
}

$(mkLabels [''Ball, ''Paddle, ''Stats, ''GameData, ''GameConfig])

getTicksM :: (MonadIO m, MonadState GameData m) => m Word32
getTicksM = getM ticker >>= getTicks

stopTicks :: (MonadIO m, MonadState GameData m) => m ()
stopTicks = modM_ ticker stop

startTicks :: (MonadIO m, MonadState GameData m) => m ()
startTicks = modM_ ticker start

resetTicks :: (MonadIO m, MonadState GameData m) => m ()
resetTicks = start timer >>= setM ticker

newBall :: RandomGen g => Player -> Vector2f -> g -> (Ball,g)
newBall p pos g = (Ball pos vel, g')--(-141.4,-141.4)
 where (deg,g') = randomR (135,225) g
       angle = deg * degToRad
       vel = (xdir * ballVel * cos angle, ballVel * sin angle)
       xdir = case p of
                Player1 -> 1
                Player2 -> (-1)

newBallM :: (MonadState GameData m) => Player -> Vector2f -> m Ball
newBallM p pos = do
    rgen <- getM randGen
    let (b, rgen') = newBall p pos rgen
    randGen =: rgen'
    return b

gameData :: Vector2f -> Vector2f -> Vector2f -> Timer -> GameData
gameData p1 p2 b ticks = GameData (Paddle p1 0 p1LastPos) (Paddle p2 0 p2LastPos) (Ball b (200.0,0)) (Stats 0 0) ticks (Init Player1) $ mkStdGen 0
 where p1LastPos = snd p1
       p2LastPos = snd p2

mapPlayer :: Player -> Stats :-> Integer
mapPlayer Player1 = player1Count
mapPlayer Player2 = player2Count