edge 0.8.12.1 → 0.8.14
raw patch · 7 files changed
+348/−3 lines, 7 filesbinary-added
Files
- Projectile/SWForward.hs +1/−1
- Projectile/SWSide.hs +1/−1
- Resources.hs +62/−0
- Unit/Smart/Master.hs +282/−0
- edge.cabal +2/−1
- image/master-cloaking.bmp binary
- image/master.bmp binary
Projectile/SWForward.hs view
@@ -78,7 +78,7 @@ Just x -> x in self { center = center' , idealNewCenter = Nothing- , radius = (radius self) + radiusGrowth * t+ , radius = min 128.0 ((radius self) + radiusGrowth * t) } updateIdealTargetCenter :: Time -> SWForward -> SWForward
Projectile/SWSide.hs view
@@ -78,7 +78,7 @@ Just x -> x in self { center = center' , idealNewCenter = Nothing- , radius = (radius self) + radiusGrowth * t+ , radius = min 128.0 ((radius self) + radiusGrowth * t) } updateIdealTargetCenter :: Time -> SWSide -> SWSide
Resources.hs view
@@ -17,6 +17,7 @@ import qualified Unit.Smart.ATank as ATank import qualified Unit.Smart.STank as STank import qualified Unit.Smart.Death as Death+import qualified Unit.Smart.Master as Master import qualified Unit.Smart.Ninja as Ninja import qualified Unit.Smart.Saucer as Saucer import qualified Unit.Smart.Sniper as Sniper@@ -44,6 +45,8 @@ , "item-sigma.bmp" , "lance.bmp" , "lance-thrusting.bmp"+ , "master.bmp"+ , "master-cloaking.bmp" , "mine.bmp" , "mine-explosion.bmp" , "mine-lit.bmp"@@ -476,6 +479,62 @@ , (-1700.0, 1100.0) ] }+ ,+ -- 12+ a { smartUnits = masterGen rt wmap+ [ ((-600, 600.0), 0.0, 10.0)+ , ((800, 600.0), 0.0, 16.0)+ , ((-800, 1000.0), 0.0, 13.0)+ , ((1200, 1000.0), 0.0, 18.0)+ , ((1400, 1300.0), 0.0, 10.0)+ , ((-300, 900.0), 0.0, 20.0)+ , ((700, -900.0), 0.0, 12.0)+ , ((-1499, -1499.0), 0.0, 10.0)+ ]+ , asteroids = asteroidGen rt wmap+ [ ((1000, 600), (100, -140))+ , ((-850, 1100), (100, -140))+ , ((200, -900), (100, -140))+ ] +++ bigAsteroidGen rt wmap+ [ ((-600, 1300), (100, -140))+ , ((1400, -1000), (100, -140))+ ]+ }+ ,+ -- 13+ a { smartUnits = sTankGen rt wmap+ [ ((0, -500.0), pi / 2)+ , ((-200, -700.0), pi / 2)+ , ((200, -700.0), pi / 2)+ , ((-400, -900.0), pi / 2)+ -- , ((0, -900.0), pi / 2)+ , ((400, -900.0), pi / 2)+ , ((-600, -1100.0), pi / 2)+ -- , ((-200, -1100.0), pi / 2)+ -- , ((200, -1100.0), pi / 2)+ , ((600, -1100.0), pi / 2)+ , ((-800, -1300.0), pi / 2)+ , ((800, -1300.0), pi / 2)+ ]+ -- sniperGen rt wmap+ -- [ ((-600.0, 1000.0), 0.0)+ -- , ((600.0, 1000.0), 0.0)+ -- ]+ , simpleUnits = turretGen rt wmap+ [ ((0.0, 1000.0), 0.0, pi / 2)+ , ((-600.0, 1000.0), 0.0, - pi / 2)+ , ((600.0, 1000.0), 0.0, - pi / 2)+ ]+ , asteroids = asteroidGen rt wmap+ [ ((1000, 600), (40, -40))+ , ((200, -900), (-10, 30))+ ] +++ bigAsteroidGen rt wmap+ [ ((-600, 1300), (60, -30))+ , ((1400, -1000), (-20, 70))+ ]+ } ] let addItems a = do (it1, it2) <- randomItemPair x1 <- randomRIO (0, 2999)@@ -542,4 +601,7 @@ ninjaGen rt wmap = map (\(x, y) -> SmartUnit (Ninja.new rt wmap (wrappoint wmap x) y))++masterGen rt wmap =+ map (\(x, y, z) -> SmartUnit (Master.new rt wmap (wrappoint wmap x) y z))
+ Unit/Smart/Master.hs view
@@ -0,0 +1,282 @@+module Unit.Smart.Master ( Master(..)+ , new+ ) where++import Data.WrapAround+import Animation+import Graphics.Gloss.Data.Picture+import Graphics.Gloss.Data.Color+import GHC.Float+import Trigonometry+import ResourceTracker+import Updating+import qualified Moving as M+import Combat+import qualified Projectile.Blade as P.Blade+import AfterEffect+import qualified AfterEffect.SimpleExplosion as SimpleExplosion+import Data.Maybe+import Universe hiding (wrapMap, resourceTracker)+import qualified Universe as U+import Sound.ALUT+import Common++radialVelocity = pi/2 -- radians per second++maxVelocityMag = 400.0++kamikazeDamage = 8.0++maxIntegrity = 3++accelerationRate = 250.0++adjAngle = pi / 8++shotDelay = 4.0++data Master = Master { angle :: Angle -- radians+ , velocity :: Velocity+ , center :: WrapPoint+ , idealTargetLocation :: Maybe WrapPoint+ , wrapMap :: WrapMap+ , launchTube :: [Projectile]+ , sinceLastShot :: Time+ , integrity :: Double+ , vision :: Maybe Arena+ , resourceTracker :: ResourceTracker+ , cloakClock :: Time+ , cloakPeriod :: Time++ -- Sound+ , queueShotSound :: Bool+ , shotSoundSource :: Maybe Source+ }++instance Audible Master where++ processAudio self lcenter =+ do self' <- if isNothing (shotSoundSource self)+ then initializeShotSoundSource self+ else return self+ if not (queueShotSound self)+ then return self'+ else do let (x, y) = vectorRelation+ (wrapMap self)+ (lcenter)+ (center self)+ let s = fromJust $ shotSoundSource self+ sourcePosition s $= (Vertex3 (double2Float x)+ (double2Float (-y))+ 0)+ play [s]+ return self' { queueShotSound = False }++ terminateAudio self =+ if isNothing (shotSoundSource self)+ then return self+ else do stop [fromJust (shotSoundSource self)]+ return self++initializeShotSoundSource self =+ do [source] <- genObjectNames 1+ buffer source $= getSound (resourceTracker self) "energy-shot-02.wav"+ -- ...+ sourceRelative source $= Listener+ referenceDistance source $= audioReferenceDistance+ rolloffFactor source $= audioRolloffFactor+ return self { shotSoundSource = Just source }++new :: ResourceTracker+ -> WrapMap+ -> WrapPoint+ -> Angle+ -> Time+ -> Master+new rt wmap center' angle' cloakPeriod' =+ Master { center = center'+ , angle = angle'+ , idealTargetLocation = Nothing+ , velocity = (0.0, 0.0)+ , wrapMap = wmap+ , launchTube = []+ , sinceLastShot = 0.0+ , integrity = maxIntegrity+ , vision = Nothing+ , resourceTracker = rt+ , queueShotSound = False+ , shotSoundSource = Nothing+ , cloakClock = 0.0+ , cloakPeriod = cloakPeriod'+ }++instance Observant Master where++ updateVision self arena = self { vision = Just arena }++updateCloakingData t self+ = self { cloakClock = let a = cloakClock self + t in+ if a >= cloakPeriod self then 0.0 else a+ }++updateAngle t self+ = case vision self of+ Nothing -> self+ Just a -> case lance a of+ Nothing -> self+ Just l -> let sDir = angle self in+ let sDir' = if sDir == 0.0 / 0.0+ then 0.1+ else sDir in+ let tDir = vectorDirection+ (vectorRelation+ (wrapMap self)+ (center self)+ (M.center l)) in+ let adj+ | tDir - sDir' > adjAngle = radialVelocity * t+ | tDir - sDir' < (-1) * adjAngle = (-radialVelocity) * t+ | otherwise = 0.0 in+ self { angle = angle self + adj }++updateVelocity :: Time -> Master -> Master+updateVelocity t self =+ let thrustingVelocity = M.calcNewVelocity+ (velocity self)+ accelerationRate+ (angle self)+ maxVelocityMag+ t in+ let velocity' = case vision self of+ Nothing -> velocity self+ Just a ->+ case lance a of+ Nothing -> velocity self+ Just l -> let sDir = angle self in+ let sDir' = if sDir == 0.0 / 0.0+ then 0.1+ else sDir in+ let tDir = vectorDirection+ (vectorRelation+ (wrapMap self)+ (center self)+ (M.center l)) in+ if abs (tDir - sDir') <= adjAngle+ then thrustingVelocity+ else velocity self in+ self { velocity = velocity' }++instance Animation Master where+ image self _ = Rotate (radToDeg+ (double2Float+ (angle self)) * (-1) - 90)+ currentPic+ where defaultPic = fromMaybe+ (Scale 0.20 0.20+ (Color white+ (Text "Error! Missing image!")))+ (getImage rt "master.bmp")+ cloakingPic = fromMaybe Blank (getImage rt "master-cloaking.bmp")+ rt = resourceTracker self+ t = cloakClock self+ p = cloakPeriod self+ currentPic = if t < 0.3+ then cloakingPic+ else if t < p * 0.5 - 0.3+ then defaultPic+ else if t < p * 0.5+ then cloakingPic+ else Blank++instance M.Locatable Master where+ center = center++instance M.Moving Master where+ velocity = velocity++instance M.Colliding Master where+ collisionRadius _ = 40.0++instance InternallyUpdating Master where++ preUpdate self t = (updateFiringInformation t+ . updateIdealTargetLocation t+ . updateVelocity t+ . updateAngle t+ . updateCloakingData t) self++ postUpdate self t =+ let center' = fromMaybe (center self) (idealTargetLocation self) in+ self { center = center'+ , idealTargetLocation = Nothing+ }++updateFiringInformation t self =+ let cloaked = cloakClock self >= cloakPeriod self * 0.5 in+ let sinceLastShot' = sinceLastShot self + t in+ if sinceLastShot' >= shotDelay+ then self { sinceLastShot = 0.0+ , launchTube = if cloaked+ then launchTube self+ else projectile : launchTube self+ , queueShotSound = if cloaked then False else True+ }+ else self { sinceLastShot = sinceLastShot' }+ where projectile = Projectile+ (P.Blade.new+ (wrapMap self)+ (resourceTracker self)+ pAngle+ (center self)+ (velocity self))+ pSpeed = P.Blade.speed+ pAngle = case vision self of+ Nothing -> angle self+ Just arena ->+ case lance arena of+ Nothing -> angle self+ Just l -> targetingA+ pSpeed+ (vectorRelation+ (U.wrapMap arena)+ (center self)+ (M.center l))+ (subV+ (M.velocity l)+ (M.velocity self))++updateIdealTargetLocation :: Time -> Master -> Master+updateIdealTargetLocation t self =+ self { idealTargetLocation = Just (M.idealNewLocation (wrapMap self)+ (center self)+ (velocity self)+ t)+ }++instance Launcher Master where++ deployProjectiles self = (launchTube self, self { launchTube = [] })++instance Transient Master where++ expired' self = if integrity self > 0.0+ then Nothing+ else Just [aeffect]+ where aeffect = AfterEffect (SimpleExplosion.new (resourceTracker self)+ (wrapMap self)+ (center self)+ (velocity self))++instance Damageable Master where++ inflictDamage self d = + let cloaked = cloakClock self >= cloakPeriod self * 0.5 in+ if cloaked + then self+ else self { integrity = max 0.0 (integrity self - d) }++instance Damaging Master where++ damageEnergy self = + let cloaked = cloakClock self >= cloakPeriod self * 0.5 in+ if cloaked then 0.0 else kamikazeDamage
edge.cabal view
@@ -7,7 +7,7 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version: 0.8.12.1+Version: 0.8.14 -- A short (one-line) description of the package. Synopsis: Top view space combat arcade game@@ -110,6 +110,7 @@ , Unit.Smart.ATank , Unit.Smart.STank , Unit.Smart.Death+ , Unit.Smart.Master , Unit.Smart.Ninja , Unit.Smart.Saucer , Unit.Smart.Sniper
+ image/master-cloaking.bmp view
binary file changed (absent → 10186 bytes)
+ image/master.bmp view
binary file changed (absent → 10186 bytes)