Added bullet/tank collision; reduced tick count
This commit is contained in:
parent
a1294859c7
commit
5c34cd6941
5 changed files with 41 additions and 11 deletions
|
@ -16,4 +16,4 @@ data CPUPlayer = CPUPlayer Micro
|
||||||
deriving (Typeable, Show)
|
deriving (Typeable, Show)
|
||||||
|
|
||||||
instance Player CPUPlayer where
|
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)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module Collision ( collisionTankBorder
|
module Collision ( collisionTankBorder
|
||||||
, collisionBulletBullet
|
, collisionBulletBullet
|
||||||
|
, collisionBulletTank
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Tank
|
import Tank
|
||||||
|
@ -49,3 +50,23 @@ collisionBulletBullet :: (Bullet, Bullet) -> (Bullet, Bullet) -> Bool
|
||||||
collisionBulletBullet (b1, b1') (b2, b2') = distancesq < (bulletDiameter^2)
|
collisionBulletBullet (b1, b1') (b2, b2') = distancesq < (bulletDiameter^2)
|
||||||
where
|
where
|
||||||
distancesq = (bulletX b1' - bulletX b2')^2 + (bulletY b1' - bulletY b2')^2
|
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
|
||||||
|
|
|
@ -23,7 +23,7 @@ data Bullet = Bullet
|
||||||
, bulletSpeed :: !Micro
|
, bulletSpeed :: !Micro
|
||||||
, bulletBouncesLeft :: !Int
|
, bulletBouncesLeft :: !Int
|
||||||
, bulletTank :: !Int
|
, bulletTank :: !Int
|
||||||
} deriving Show
|
} deriving (Eq, Show)
|
||||||
|
|
||||||
data GameState = GameState
|
data GameState = GameState
|
||||||
{ level :: !Level
|
{ level :: !Level
|
||||||
|
|
|
@ -61,11 +61,11 @@ mainLoop = do
|
||||||
liftIO $ threadDelay $ truncate $ 1e6*(minFrameTime - drender)
|
liftIO $ threadDelay $ truncate $ 1e6*(minFrameTime - drender)
|
||||||
|
|
||||||
currenttime <- liftIO getCurrentTime
|
currenttime <- liftIO getCurrentTime
|
||||||
let d = round $ 1e3*(diffUTCTime currenttime t)
|
let d = round $ 1e2*(diffUTCTime currenttime t)
|
||||||
|
|
||||||
replicateM_ d simulationStep
|
replicateM_ d simulationStep
|
||||||
|
|
||||||
let newtime = addUTCTime ((1e-3)*(fromIntegral d)) t
|
let newtime = addUTCTime ((1e-2)*(fromIntegral d)) t
|
||||||
|
|
||||||
modify $ \state -> state {time = newtime}
|
modify $ \state -> state {time = newtime}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Tank
|
||||||
|
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import Data.Fixed
|
import Data.Fixed
|
||||||
|
import Data.List
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Ratio
|
import Data.Ratio
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ import Data.Ratio
|
||||||
updateAngle :: Micro -> State Tank ()
|
updateAngle :: Micro -> State Tank ()
|
||||||
updateAngle angle = do
|
updateAngle angle = do
|
||||||
oldangle <- gets tankDir
|
oldangle <- gets tankDir
|
||||||
tspeed <- gets tankTurnspeed >>= return . (/1000)
|
tspeed <- liftM (/100) $ gets tankTurnspeed
|
||||||
|
|
||||||
let diff = angle - oldangle
|
let diff = angle - oldangle
|
||||||
let diff360 = if (diff > 180)
|
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
|
when (isNothing angle || (isJust angle && (tdir == fromJust angle)) || moved) $ do
|
||||||
let anglej = (fromRational . toRational $ tdir)*pi/180
|
let anglej = (fromRational . toRational $ tdir)*pi/180
|
||||||
dx = tspeed * fromRational (round ((cos anglej)*1000)%1000000)
|
dx = tspeed * fromRational (round ((cos anglej)*1000)%100000)
|
||||||
dy = tspeed * fromRational (round ((sin anglej)*1000)%1000000)
|
dy = tspeed * fromRational (round ((sin anglej)*1000)%100000)
|
||||||
|
|
||||||
put tank {tankX = dx + tankX tank, tankY = dy + tankY tank, tankMoving = True}
|
put tank {tankX = dx + tankX tank, tankY = dy + tankY tank, tankMoving = True}
|
||||||
|
|
||||||
|
@ -83,8 +84,8 @@ updateBullet game = do
|
||||||
bullet <- get
|
bullet <- get
|
||||||
let angle = (fromRational . toRational . bulletDir $ bullet)*pi/180
|
let angle = (fromRational . toRational . bulletDir $ bullet)*pi/180
|
||||||
speed = bulletSpeed bullet
|
speed = bulletSpeed bullet
|
||||||
dx = speed * fromRational (round ((cos angle)*1000)%1000000)
|
dx = speed * fromRational (round ((cos angle)*1000)%100000)
|
||||||
dy = speed * fromRational (round ((sin angle)*1000)%1000000)
|
dy = speed * fromRational (round ((sin angle)*1000)%100000)
|
||||||
x = dx + bulletX bullet
|
x = dx + bulletX bullet
|
||||||
y = dy + bulletY bullet
|
y = dy + bulletY bullet
|
||||||
lw = fromIntegral . levelWidth . level $ game
|
lw = fromIntegral . levelWidth . level $ game
|
||||||
|
@ -123,8 +124,12 @@ simulationStep = do
|
||||||
lift $ modify $ \state ->
|
lift $ modify $ \state ->
|
||||||
let thebullets = map (runState $ updateBullet state) $ bullets state
|
let thebullets = map (runState $ updateBullet state) $ bullets state
|
||||||
leftbullets = collideBullets $ zipWith (\(left, bullet') bullet -> (left, bullet, bullet')) thebullets $ 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..]
|
bt = hitBullets $ liftM2 (\(b, (_, b')) (t, t') -> (b, b', t, t')) (zip (bullets state) leftbullets) (zip (tanks state) newtanks)
|
||||||
in state {tanks = thetanks, bullets = newbullets ++ (map snd . filter fst $ leftbullets)}
|
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
|
where
|
||||||
collideBullets [] = []
|
collideBullets [] = []
|
||||||
|
@ -135,6 +140,10 @@ simulationStep = do
|
||||||
left = map (\(left, c, b, b') -> (left && not c, b, b')) $ cs
|
left = map (\(left, c, b, b') -> (left && not c, b, b')) $ cs
|
||||||
in (collided, left)
|
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
|
updateTank' game (player, tank) = let (p, angle, move, aangle, shoot) = playerUpdate player tank
|
||||||
t = execState (updateTank game angle move aangle) tank
|
t = execState (updateTank game angle move aangle) tank
|
||||||
in (p, t, shoot)
|
in (p, t, shoot)
|
||||||
|
|
Reference in a new issue