packages feed

freekick2-0.1.0: src/Match/Ball.hs

{-# LANGUAGE TemplateHaskell #-}
module Match.Ball
where

import Data.List
import Control.Monad.State

import Drawing
import FVector
import DeriveMod

data Ball = Ball {
    ballposition :: FVector3
  , ballvelocity :: FVector3
  , ballimage    :: ImageInfo
  , ballshadow   :: ImageInfo
  , ballposz     :: Float
  }
$(deriveMods ''Ball)

data Block = CylinderX FVector3 Float Float
           | CylinderZ FVector3 Float Float

instance Sprite Ball where
  getTexture     = imgtexture . ballimage
  getRectangle b = ballTexRectangle True b
  getDepth b     = topDownDepth (to2D $ ballposition b) (ballposz b)

initialBall :: Float -> FRange -> ImageInfo -> ImageInfo -> Ball
initialBall zv (px, py) img shimg = Ball (px / 2, py / 2, 0) nullFVector3 img shimg zv

ballTexRectangle :: Bool -> Ball -> Rectangle
ballTexRectangle sh b = ((x - s / 2, y - t / 2 + sz), (s, t))
      where (x, y, z) = ballposition b
            (s, t) = imgsize $ ballimage b
            sz = if sh
                   then z
                   else 0

collCheckGroundBall :: Float -> Ball -> Ball
collCheckGroundBall bounc b =
  let zv = getZ (ballposition b)
      zvel = getZ $ ballvelocity b
  in if zv < 0  -- bounciness
       then modBallposition (addZ (2 * (-zv))) (modBallvelocity (addZ (bounc * (-zvel))) b)
     else
       b

gravitateBall :: Float -> Float -> Ball -> Ball
gravitateBall g dt b = 
  let zv = getZ $ ballposition $ b
      zvel = getZ $ ballvelocity $ b
  in if (zv > 0.01)
       then 
         modBallvelocity (addZ (g * dt)) b
       else
         if (abs zvel < 0.1) 
           then modBallvelocity (setZ 0) b
           else b

collCheckPostsBall :: Float -> [Block] -> Ball -> Ball
collCheckPostsBall _ bs bl = foldl' check bl bs
  where check b _ = b -- TODO

collCheckNetBall :: Float -> [(Cube, FVector3)] -> Ball -> Ball
collCheckNetBall dt ns bl = foldl' check bl ns
  where check b ((c1, cl), vvec) =
          let bprevpos = bpos *-* (bvel *** dt)
              bpos     = ballposition b
              bvel     = ballvelocity b
              resetvel (x1, y1, z1) (rx, ry, rz) =
                (x1 * rx, y1 * ry, z1 * rz)
              brad     = 0.35
          in if (bpos *-* (brad, brad, brad), bpos *+* (brad, brad, brad)) `inside3cube` (c1, c1 *+* cl)
               then b{ballvelocity = resetvel bvel vvec, ballposition = bprevpos}
               else b

slowDownBall :: Float -> Float -> Float -> Ball -> Ball
slowDownBall vis rol dt b =
  let zv = getZ $ ballposition $ b
      zvel = getZ $ ballvelocity $ b
  in if zv > 0.01
       then  -- air viscosity
         modBallvelocity (*** (1 - (vis * dt))) b
       else  -- rolling friction
         modBallvelocity (*** (1 - (rol * dt))) b

drawBall :: Ball -> IO ()
drawBall = drawSprite 

drawBallShadow :: Ball -> IO ()
drawBallShadow b = drawSprite' (imgtexture (ballshadow b)) (ballShadowRectangle b) (ballposz b)

ballShadowRectangle :: Ball -> Rectangle
ballShadowRectangle b = ((x, y), (w, h))
  where (x, y)   = (bx, by - bh / 2)
        (bx, by) = fst $ ballTexRectangle False b
        (w, h) = imgsize $ ballshadow b
        (_, bh) = imgsize $ ballimage b