summaryrefslogtreecommitdiffstats
path: root/src/Simulation.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Simulation.hs')
-rw-r--r--src/Simulation.hs82
1 files changed, 36 insertions, 46 deletions
diff --git a/src/Simulation.hs b/src/Simulation.hs
index c1debb2..3cf4fec 100644
--- a/src/Simulation.hs
+++ b/src/Simulation.hs
@@ -7,31 +7,33 @@ import Level
import MainLoop
import Player
import Tank
+import Transformable
+import Vector
import Control.Monad.State
-import Data.Fixed
import Data.List
import Data.Maybe
-import Data.Ratio
+import Data.VectorSpace
-updateAngle :: Micro -> Tank -> Tank
-updateAngle angle tank = tank {tankDir = newangle180}
+updateAngle :: Vector -> Tank -> Tank
+updateAngle dir tank = tank {tankDir = rotate newangle >< Vector 1 0}
where
- oldangle = tankDir tank
+ oldangle = toAngle . tankDir $ tank
+ angle = toAngle dir
tspeed = (tankTurnspeed tank)/100
diff = angle - oldangle
- diff360 = if (diff > 180)
- then (diff-360)
- else if (diff <= -180)
- then (diff+360)
+ diff360 = if (diff > pi)
+ then (diff-2*pi)
+ else if (diff <= -pi)
+ then (diff+2*pi)
else diff
- (diff180, angle180) = if (diff360 > 90)
- then (diff360-180, oldangle+180)
- else if (diff360 <= -90)
- then (diff360+180, oldangle-180)
+ (diff180, angle180) = if (diff360 > pi/2)
+ then (diff360-180, oldangle+pi)
+ else if (diff360 <= -pi/2)
+ then (diff360+pi, oldangle-pi)
else (diff360, oldangle)
turn = if (diff180 > tspeed)
@@ -41,21 +43,19 @@ updateAngle angle tank = tank {tankDir = newangle180}
else diff180
newangle = angle180 + turn
-
- newangle180 = if (newangle > 180)
- then (newangle-360)
- else if (newangle <= -180)
- then (newangle+360)
- else newangle
+approx :: Vector -> Vector -> Bool
+approx (Vector x1 y1) (Vector x2 y2) = x1 `approx'` x2 && y1 `approx'` y2
+ where
+ approx' a b = (abs (a-b)) < 0.000001
-updateTank :: GameState -> Maybe Micro -> Bool -> Maybe Micro -> State Tank ()
-updateTank game angle move aangle = do
- when (isJust angle) $
- modify $ updateAngle $ fromJust angle
+updateTank :: GameState -> Maybe Vector -> Bool -> Maybe Vector -> State Tank ()
+updateTank game dir move aim = do
+ when (isJust dir) $
+ modify $ updateAngle $ fromJust dir
- when (isJust aangle) $
- modify $ \tank -> tank {tankAim = fromJust aangle}
+ when (isJust aim) $
+ modify $ \tank -> tank {tankAim = fromJust aim}
when move $ do
tank <- get
@@ -63,12 +63,8 @@ updateTank game angle move aangle = do
tspeed = tankSpeed tank
moved = tankMoving tank
- when (isNothing angle || (isJust angle && (tdir == fromJust angle)) || moved) $ do
- let anglej = (fromRational . toRational $ tdir)*pi/180
- dx = tspeed * fromRational (round ((cos anglej)*1000)%100000)
- dy = tspeed * fromRational (round ((sin anglej)*1000)%100000)
-
- put tank {tankX = dx + tankX tank, tankY = dy + tankY tank, tankMoving = True}
+ when (isNothing dir || (isJust dir && (tdir `approx` fromJust dir) || moved)) $
+ put $ translateV (tdir ^* (tspeed/100)) >< tank {tankMoving = True}
when (not move) $ do
modify $ \tank -> tank {tankMoving = False}
@@ -79,22 +75,17 @@ updateTank game angle move aangle = do
updateBullet :: GameState -> Bullet -> (Bullet, Bool)
-updateBullet game bullet = (bullet {bulletX = newx, bulletY = newy, bulletDir = dir3, bulletBouncesLeft = bounces3}, bounces3 >= 0)
+updateBullet game bullet = (bullet {bulletPos = Vertex x' y', bulletDir = Vector dx' dy', bulletBouncesLeft = bounces3}, bounces3 >= 0)
where
- angle = (fromRational . toRational . bulletDir $ bullet)*pi/180
speed = bulletSpeed bullet
- dx = speed * fromRational (round ((cos angle)*1000)%100000)
- dy = speed * fromRational (round ((sin angle)*1000)%100000)
- x = dx + bulletX bullet
- y = dy + bulletY bullet
+ d@(Vector dx dy) = bulletDir bullet
+ Vertex x y = translateV (d ^* (speed/100)) >< bulletPos bullet
+ bounces = bulletBouncesLeft bullet
lw = fromIntegral . levelWidth . level $ game
lh = fromIntegral . levelHeight . level $ game
- dir = bulletDir bullet
- bounces = bulletBouncesLeft bullet
- sg = if dir < 0 then -1 else 1
- (newx, dir2, bounces2) = if x < 0 then (-x, sg*180 - dir, bounces-1) else if x > lw then (2*lw-x, sg*180 - dir, bounces-1) else (x, dir, bounces)
- (newy, dir3, bounces3) = if y < 0 then (-y, -dir2, bounces2-1) else if y > lh then (2*lh-y, -dir2, bounces2-1) else (y, dir2, bounces2)
+ (x', dx', bounces2) = if x < 0 then (-x, -dx, bounces-1) else if x > lw then (2*lw-x, -dx, bounces-1) else (x, dx, bounces)
+ (y', dy', bounces3) = if y < 0 then (-y, -dy, bounces2-1) else if y > lh then (2*lh-y, -dy, bounces2-1) else (y, dy, bounces2)
gameStep :: [(Tank, Bool)] -> GameState -> GameState
gameStep tanksshoot state = state {tanks = thetanks, bullets = newbullets ++ (map snd . filter fst $ leftbullets2)}
@@ -104,8 +95,7 @@ gameStep tanksshoot state = state {tanks = thetanks, bullets = newbullets ++ (ma
thetanks = map (\(tank, n) -> tank {tankBulletsLeft = (tankBulletsLeft tank) + (countLostTankBullets n leftbullets2)}) $ zip newtanks2 [0..]
newtanks = map (\(tank, shoot, _) -> if (shoot && (tankBulletsLeft tank) > 0) then tank {tankBulletsLeft = (tankBulletsLeft tank) - 1} else tank) $ ts
newbullets = map (\(tank, n) -> Bullet
- { bulletX = tankX tank
- , bulletY = tankY tank
+ { bulletPos = tankPos tank
, bulletDir = tankAim tank
, bulletSpeed = tankBulletSpeed tank
, bulletBouncesLeft = tankBulletBounces tank
@@ -144,6 +134,6 @@ simulationStep = do
modify $ \state -> state {players = p, gameState = gameStep (zip t s) (gameState state)}
where
updateTank' game (player, tank) = do
- (p, angle, move, aangle, shoot) <- playerUpdate player tank
- let t = execState (updateTank game angle move aangle) tank
+ (p, dir, move, aim, shoot) <- playerUpdate player tank
+ let t = execState (updateTank game dir move aim) tank
return $ if (tankLife tank > 0) then (p, t, shoot) else (player, tank, False)