summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <matthias@gamezock.de>2010-03-09 22:36:22 +0100
committerMatthias Schiffer <matthias@gamezock.de>2010-03-09 22:36:22 +0100
commite85dc20a4869c91faa3869695d2d19bfe07f9abc (patch)
treeec4c2ae2d5d40c96065782a46fb4f45fc11dbfe1
parentf3d9814ad5e7efe7aa883b1c58b854a574c0cf61 (diff)
downloadhtanks-e85dc20a4869c91faa3869695d2d19bfe07f9abc.tar
htanks-e85dc20a4869c91faa3869695d2d19bfe07f9abc.zip
Nice tank-border collision detection
-rw-r--r--htanks.cabal5
-rw-r--r--src/CPUPlayer.hs2
-rw-r--r--src/Collision.hs41
-rw-r--r--src/Simulation.hs33
4 files changed, 65 insertions, 16 deletions
diff --git a/htanks.cabal b/htanks.cabal
index 053eec7..584e905 100644
--- a/htanks.cabal
+++ b/htanks.cabal
@@ -14,6 +14,7 @@ data-files: tex/*.png
executable: HTanks
hs-source-dirs: src
main-is: HTanks.hs
-other-modules: CPUPlayer, DefaultPlayer, Game, GLDriver, GLX, Level, MainLoop, Paths_htanks, Player, Render, Simulation, Texture, Bindings.GLX, Bindings.GLPng
-ghc-options: -threaded
+other-modules: Collision, CPUPlayer, DefaultPlayer, Game, GLDriver, GLX, Level, MainLoop, Paths_htanks, Player, Render, Simulation, Texture,
+ Bindings.GLX, Bindings.GLPng
+ghc-options: -threaded -O2
extra-libraries: glpng
diff --git a/src/CPUPlayer.hs b/src/CPUPlayer.hs
index 0276de3..4a6fb37 100644
--- a/src/CPUPlayer.hs
+++ b/src/CPUPlayer.hs
@@ -16,4 +16,4 @@ data CPUPlayer = CPUPlayer Micro
deriving (Typeable, Show)
instance Player CPUPlayer where
- playerUpdate (CPUPlayer angle) _ = (CPUPlayer (if (angle+0.1) > 180 then angle-359.9 else angle+0.1), Just angle, True, Just (-angle), False)
+ playerUpdate (CPUPlayer angle) _ = (CPUPlayer (if (angle+0.1) > 180 then angle-359.08 else angle+0.02), Just angle, True, Just (-angle), False)
diff --git a/src/Collision.hs b/src/Collision.hs
new file mode 100644
index 0000000..d29738a
--- /dev/null
+++ b/src/Collision.hs
@@ -0,0 +1,41 @@
+module Collision ( collisionTankBorder
+ ) where
+
+import Game
+
+import Data.Fixed
+import Data.Ratio
+
+tankWidth :: Micro
+tankWidth = 0.95
+
+tankLength :: Micro
+tankLength = 0.95
+
+collisionTankBorder :: Micro -> Micro -> Tank -> Tank
+collisionTankBorder lw lh tank = tank {tankX = newx, tankY = newy}
+ where
+ dir = (fromRational . toRational . tankDir $ tank)*pi/180
+ cosd = fromRational (round ((cos dir)*1000000)%1000000)
+ sind = fromRational (round ((sin dir)*1000000)%1000000)
+
+ points = [ (tankLength/2, tankWidth/2)
+ , (-tankLength/2, tankWidth/2)
+ , (-tankLength/2, -tankWidth/2)
+ , (tankLength/2, -tankWidth/2)
+ ]
+
+ rotp (x, y) = (cosd*x - sind*y, sind*x + cosd*y)
+ transp (x, y) = (x + tankX tank, y + tankY tank)
+
+ pointst = map (transp . rotp) points
+ minx = minimum $ map fst pointst
+ maxx = maximum $ map fst pointst
+ miny = minimum $ map snd pointst
+ maxy = maximum $ map snd pointst
+
+ dx = if minx < 0 then (-minx) else if maxx > lw then (-maxx+lw) else 0
+ dy = if miny < 0 then (-miny) else if maxy > lh then (-maxy+lh) else 0
+
+ newx = (tankX tank) + dx
+ newy = (tankY tank) + dy
diff --git a/src/Simulation.hs b/src/Simulation.hs
index f45ab99..33465cc 100644
--- a/src/Simulation.hs
+++ b/src/Simulation.hs
@@ -1,6 +1,7 @@
module Simulation ( simulationStep
) where
+import Collision
import Game
import Level
import MainLoop
@@ -47,8 +48,8 @@ updateAngle angle = do
modify $ \tank -> tank {tankDir = newangle180}
-updateTank :: Maybe Micro -> Bool -> Maybe Micro -> State Tank ()
-updateTank angle move aangle = do
+updateTank :: GameState -> Maybe Micro -> Bool -> Maybe Micro -> State Tank ()
+updateTank game angle move aangle = do
when (isJust angle) $
updateAngle $ fromJust angle
@@ -56,19 +57,24 @@ updateTank angle move aangle = do
modify $ \tank -> tank {tankAim = fromJust aangle}
when move $ do
- tdir <- gets tankDir
- tspeed <- gets tankSpeed
- moved <- gets tankMoving
+ tank <- get
+ let tdir = tankDir tank
+ tspeed = tankSpeed tank
+ moved = tankMoving tank
when (isNothing angle || (isJust angle && (tdir == fromJust angle)) || moved) $ do
let anglej = (fromRational . toRational $ tdir)*pi/180
- x = tspeed * fromRational (round ((cos anglej)*1000)%1000000)
- y = tspeed * fromRational (round ((sin anglej)*1000)%1000000)
+ dx = tspeed * fromRational (round ((cos anglej)*1000)%1000000)
+ dy = tspeed * fromRational (round ((sin anglej)*1000)%1000000)
- modify $ \tank -> tank {tankX = x + tankX tank, tankY = y + tankY tank, tankMoving = True}
+ put tank {tankX = dx + tankX tank, tankY = dy + tankY tank, tankMoving = True}
when (not move) $ do
modify $ \tank -> tank {tankMoving = False}
+
+ let lw = fromIntegral . levelWidth . level $ game
+ lh = fromIntegral . levelHeight . level $ game
+ modify $ collisionTankBorder lw lh
updateBullet :: GameState -> State Bullet Bool
@@ -96,9 +102,10 @@ updateBullet game = do
simulationStep :: Main ()
simulationStep = do
oldplayers <- gets players
- oldtanks <- lift $ gets tanks
+ game <- lift get
+ let oldtanks = tanks game
- let (p, t, s) = unzip3 $ map updateTank' $ zip oldplayers oldtanks
+ let (p, t, s) = unzip3 $ map (updateTank' game) $ zip oldplayers oldtanks
ts = zip3 t s [0..]
shootingtanks = map (\(tank, _, n) -> (tank, n)) $ filter (\(tank, shoot, _) -> shoot && (tankBulletsLeft tank) > 0) $ ts
newtanks = map (\(tank, shoot, _) -> if (shoot && (tankBulletsLeft tank) > 0) then tank {tankBulletsLeft = (tankBulletsLeft tank) - 1} else tank) $ ts
@@ -117,8 +124,8 @@ simulationStep = do
thetanks = map (\(tank, n) -> tank {tankBulletsLeft = (tankBulletsLeft tank) + (countLostTankBullets n thebullets)}) $ zip newtanks [0..]
in state {tanks = thetanks, bullets = map snd . filter fst $ thebullets}
where
- updateTank' (player, tank) = let (p, angle, move, aangle, bullet) = playerUpdate player tank
- t = execState (updateTank angle move aangle) tank
- in (p, t, bullet)
+ updateTank' game (player, tank) = let (p, angle, move, aangle, bullet) = playerUpdate player tank
+ t = execState (updateTank game angle move aangle) tank
+ in (p, t, bullet)
countLostTankBullets n (x:xs) = (if ((not . fst $ x) && (n == (bulletTank . snd $ x))) then 1 else 0) + (countLostTankBullets n xs)
countLostTankBullets n [] = 0