packages feed

starrover2-0.0.9: src/AObject.hs

module AObject
where

import Data.Maybe
import Data.Foldable

import Graphics.Rendering.OpenGL as OpenGL

import OpenGLUtils
import Entity
import Collision
import Utils
import Tree

data AObject = AObject {
    aobjName          :: String
  , angle             :: GLdouble
  , color             :: Color4 GLfloat
  , size              :: GLdouble
  , orbitalSpeedcoeff :: GLdouble
  , orbitRadius       :: GLdouble
  , barycenter        :: GLvector3
  , colonyOwner       :: Maybe String
  }

modifyAngle :: (GLdouble -> GLdouble) -> AObject -> AObject
modifyAngle f t = t{angle = f (angle t)}

modifyBarycenter :: (GLvector3 -> GLvector3) -> AObject -> AObject
modifyBarycenter f t = t{barycenter = f (barycenter t)}

nullBarycenters :: AObjTree -> AObjTree
nullBarycenters (Leaf a)    = Leaf (modifyBarycenter (const glVector3Null) a)
nullBarycenters (Node n ts) = Node n (map nullBarycenters ts)

setupBarycenters :: AObjTree -> AObjTree
setupBarycenters = updateBarycenters . nullBarycenters

updateBarycenters :: AObjTree -> AObjTree
updateBarycenters = go glVector3Null
  where go disp (Leaf a)             = 
          Leaf (modifyBarycenter (*+* disp) a)
        go disp (Node (ang, rad) ts) = 
          Node (ang, rad) 
               (map (go ((getPosition' ang rad) *+* disp)) ts)

type Orbit = (GLdouble, GLdouble) -- angle, orbitRadius

type AObjTree = Tree Orbit AObject

nullAObjTree :: AObjTree
nullAObjTree = Node (0.0, 0.0) []

aobjToEntities :: AObject -> (Entity, Entity)
aobjToEntities a = (e, o)
  where e = newEntity 
               (sin (degToRad $ angle a) * (orbitRadius a),
                cos (degToRad $ angle a) * (orbitRadius a),
                0)
               0
               (AObject.color a)
               Polygon
               (circlePoints 16)
               (glVector3AllUnit *** (size a))
        o = newEntity
               glVector3Null
               0
               (Color4 0.5 0.5 0.5 0.1)
               LineLoop
               (circlePoints 128)
               (glVector3AllUnit *** (orbitRadius a))

aobjPoints = circlePoints 32
aorbitPoints = circlePoints 128
aorbitColor = Color4 0.5 0.5 0.5 (1 :: GLfloat)

getPosition :: AObject -> GLvector3
getPosition aobj = 
  (getPosition' (angle aobj) (orbitRadius aobj)) *+* 
    (barycenter aobj)

getPosition' :: GLdouble -> GLdouble -> GLvector3
getPosition' a' r = 
  let a = degToRad a'
  in (r * cos a, r * sin a, 0)

findCollisions :: (Foldable f) => ((GLdouble, GLdouble), (GLdouble, GLdouble)) -> f AObject -> Maybe AObject
findCollisions plbox aobs = 
  listToMaybe . catMaybes $ map colliding (toList aobs)
    where colliding aobj =
            if collides2d plbox abox
              then Just aobj
              else Nothing
            where (objcoordx, objcoordy, _) = AObject.getPosition aobj
                  abox = boxArea (objcoordx, objcoordy) (size aobj)

planetNameToAllegiance :: AObjTree -> String -> String
planetNameToAllegiance aobs planetname =
  fromMaybe "Unknown" (fmap aobjName (find (\a -> aobjName a == planetname) aobs))

getAllegiance :: AObject -> String
getAllegiance a = fromMaybe "Unknown" (colonyOwner a)

hasOwner :: String -> AObject -> Bool
hasOwner alleg a = case colonyOwner a of
                     Nothing -> False
                     Just n  -> n == alleg

hasSomeOwner :: AObject -> Bool
hasSomeOwner = isJust . colonyOwner