From 5c34cd694117421e570b3a6cc3bb813e17e50b33 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 18 Mar 2010 09:14:32 +0100 Subject: Added bullet/tank collision; reduced tick count --- src/CPUPlayer.hs | 2 +- src/Collision.hs | 21 +++++++++++++++++++++ src/Game.hs | 2 +- src/HTanks.hs | 4 ++-- src/Simulation.hs | 23 ++++++++++++++++------- 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/CPUPlayer.hs b/src/CPUPlayer.hs index 4a6fb37..1a6ce70 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.08 else angle+0.02), Just angle, True, Just (-angle), False) + playerUpdate (CPUPlayer angle) _ = (CPUPlayer (if (angle+0.2) > 180 then angle-359.8 else angle+0.2), Just angle, True, Just (-angle), False) diff --git a/src/Collision.hs b/src/Collision.hs index 9ad898b..a69dc10 100644 --- a/src/Collision.hs +++ b/src/Collision.hs @@ -1,5 +1,6 @@ module Collision ( collisionTankBorder , collisionBulletBullet + , collisionBulletTank ) where import Tank @@ -49,3 +50,23 @@ collisionBulletBullet :: (Bullet, Bullet) -> (Bullet, Bullet) -> Bool collisionBulletBullet (b1, b1') (b2, b2') = distancesq < (bulletDiameter^2) where distancesq = (bulletX b1' - bulletX b2')^2 + (bulletY b1' - bulletY b2')^2 + +collisionBulletTank :: (Bullet, Bullet) -> (Tank, Tank) -> Bool +collisionBulletTank (b, b') (tank, tank') = (not ((between bx minx maxx) && (between by miny maxy))) && ((between bx' minx maxx) && (between by' miny maxy)) + where + between x a b = x >= a && x <= b + + dir t = (fromRational . toRational . tankDir $ t)*pi/180 + cosd t = fromRational (round ((cos $ dir t)*1000000)%1000000) + sind t = fromRational (round ((sin $ dir t)*1000000)%1000000) + + rotp t (x, y) = ((cosd t)*x + (sind t)*y, -(sind t)*x + (cosd t)*y) + transp t (x, y) = (x - tankX t, y - tankY t) + + (bx, by) = (rotp tank) . (transp tank) $ (bulletX b, bulletY b) + (bx', by') = (rotp tank') . (transp tank') $ (bulletX b', bulletY b') + + minx = -tankLength/2 + maxx = tankLength/2 + miny = -tankWidth/2 + maxy = tankWidth/2 diff --git a/src/Game.hs b/src/Game.hs index 651918c..623e3ad 100644 --- a/src/Game.hs +++ b/src/Game.hs @@ -23,7 +23,7 @@ data Bullet = Bullet , bulletSpeed :: !Micro , bulletBouncesLeft :: !Int , bulletTank :: !Int - } deriving Show + } deriving (Eq, Show) data GameState = GameState { level :: !Level diff --git a/src/HTanks.hs b/src/HTanks.hs index 15c3ed6..63e647d 100644 --- a/src/HTanks.hs +++ b/src/HTanks.hs @@ -61,11 +61,11 @@ mainLoop = do liftIO $ threadDelay $ truncate $ 1e6*(minFrameTime - drender) currenttime <- liftIO getCurrentTime - let d = round $ 1e3*(diffUTCTime currenttime t) + let d = round $ 1e2*(diffUTCTime currenttime t) replicateM_ d simulationStep - let newtime = addUTCTime ((1e-3)*(fromIntegral d)) t + let newtime = addUTCTime ((1e-2)*(fromIntegral d)) t modify $ \state -> state {time = newtime} diff --git a/src/Simulation.hs b/src/Simulation.hs index a1c193f..c9810b3 100644 --- a/src/Simulation.hs +++ b/src/Simulation.hs @@ -10,6 +10,7 @@ import Tank import Control.Monad.State import Data.Fixed +import Data.List import Data.Maybe import Data.Ratio @@ -17,7 +18,7 @@ import Data.Ratio updateAngle :: Micro -> State Tank () updateAngle angle = do oldangle <- gets tankDir - tspeed <- gets tankTurnspeed >>= return . (/1000) + tspeed <- liftM (/100) $ gets tankTurnspeed let diff = angle - oldangle let diff360 = if (diff > 180) @@ -65,8 +66,8 @@ updateTank game angle move aangle = do when (isNothing angle || (isJust angle && (tdir == fromJust angle)) || moved) $ do let anglej = (fromRational . toRational $ tdir)*pi/180 - dx = tspeed * fromRational (round ((cos anglej)*1000)%1000000) - dy = tspeed * fromRational (round ((sin anglej)*1000)%1000000) + 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} @@ -83,8 +84,8 @@ updateBullet game = do bullet <- get let angle = (fromRational . toRational . bulletDir $ bullet)*pi/180 speed = bulletSpeed bullet - dx = speed * fromRational (round ((cos angle)*1000)%1000000) - dy = speed * fromRational (round ((sin angle)*1000)%1000000) + dx = speed * fromRational (round ((cos angle)*1000)%100000) + dy = speed * fromRational (round ((sin angle)*1000)%100000) x = dx + bulletX bullet y = dy + bulletY bullet lw = fromIntegral . levelWidth . level $ game @@ -123,8 +124,12 @@ simulationStep = do lift $ modify $ \state -> let thebullets = map (runState $ updateBullet state) $ bullets state leftbullets = collideBullets $ zipWith (\(left, bullet') bullet -> (left, bullet, bullet')) thebullets $ bullets state - thetanks = map (\(tank, n) -> tank {tankBulletsLeft = (tankBulletsLeft tank) + (countLostTankBullets n leftbullets)}) $ zip newtanks [0..] - in state {tanks = thetanks, bullets = newbullets ++ (map snd . filter fst $ leftbullets)} + bt = hitBullets $ liftM2 (\(b, (_, b')) (t, t') -> (b, b', t, t')) (zip (bullets state) leftbullets) (zip (tanks state) newtanks) + leftbullets2 = map (\(left, bullet) -> (left && (all (\(c, b, _) -> (b /= bullet) || (not c)) bt), bullet)) leftbullets + + thetanks = map (\(tank, n) -> tank {tankBulletsLeft = (tankBulletsLeft tank) + (countLostTankBullets n leftbullets2)}) $ zip newtanks [0..] + + in state {tanks = thetanks, bullets = newbullets ++ (map snd . filter fst $ leftbullets2)} where collideBullets [] = [] @@ -135,6 +140,10 @@ simulationStep = do left = map (\(left, c, b, b') -> (left && not c, b, b')) $ cs in (collided, left) + hitBullets :: [(Bullet, Bullet, Tank, Tank)] -> [(Bool, Bullet, Tank)] + hitBullets [] = [] + hitBullets ((b, b', t, t'):xs) = (collisionBulletTank (b, b') (t, t'), b', t'):(hitBullets xs) + updateTank' game (player, tank) = let (p, angle, move, aangle, shoot) = playerUpdate player tank t = execState (updateTank game angle move aangle) tank in (p, t, shoot) -- cgit v1.2.3