{-# OPTIONS_HADDOCK hide #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE LambdaCase #-} module Imj.Game.Hamazed.World.Ship ( shipAnims , createShipPos ) where import Imj.Prelude import Data.Char( intToDigit ) import Data.List( foldl' ) import Data.Maybe( isNothing ) import Imj.Game.Hamazed.Loop.Event import Imj.Game.Hamazed.World.Space import Imj.Geo.Discrete import Imj.Geo.Continuous import Imj.Graphics.Animation {- | If the ship is colliding and not in "safe time", and the event is a gamestep, this function creates an animation where the ship and the colliding number explode. The ship animation will have the initial speed of the number and vice-versa, to mimic the rebound due to the collision. -} shipAnims :: World -> KeyTime -> [Animation] shipAnims world@(World _ (BattleShip (PosSpeed shipCoords shipSpeed) _ safeTime collisions) _ _ _) k = if not (null collisions) && isNothing safeTime then -- when number and ship explode, they exchange speeds let collidingNumbersAvgSpeed = foldl' sumCoords zeroCoords $ map (\(Number (PosSpeed _ speed) _) -> speed) collisions numSpeed = scalarProd 0.4 $ speed2vec collidingNumbersAvgSpeed shipSpeed2 = scalarProd 0.4 $ speed2vec shipSpeed (Number _ n) = head collisions interaction = environmentInteraction world WorldFrame in fragmentsFreeFallThenExplode numSpeed shipCoords interaction (Speed 1) (Right k) '|' ++ fragmentsFreeFallThenExplode shipSpeed2 shipCoords interaction (Speed 1) (Right k) (intToDigit n) else [] createShipPos :: Space -> [Number] -> IO PosSpeed createShipPos space numbers = do let numPositions = map (\(Number (PosSpeed pos _) _) -> pos) numbers candidate@(PosSpeed pos _) <- createRandomNonCollidingPosSpeed space if pos `notElem` numPositions then return candidate else createShipPos space numbers