Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a206761
commit aa90208
Showing
5 changed files
with
935 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
|
||
module Collision where | ||
|
||
import Data.VectorSpace | ||
import Data.List | ||
import Control.Monad | ||
|
||
-- Information about collision | ||
type Vector = (Double, Double) -- thanks to vector-space we can do ^+^ and similar | ||
|
||
data Collision = Collision { normal :: Vector } deriving (Show) | ||
|
||
type Radius = Double | ||
data Circle = Circle { circlePos :: Vector, circleRadius :: Radius} | ||
data Rectangle = Rectangle Vector Vector | ||
data RoundedRect = RoundedRect { rectMin :: Vector, rectMax :: Vector, rectRadius :: Radius} | ||
|
||
|
||
|
||
class CircleShaped a where | ||
circle :: a -> Maybe Circle | ||
class RoundedRectShaped a where | ||
roundedRect :: a -> Maybe RoundedRect | ||
|
||
instance CircleShaped Circle where | ||
circle c = Just c | ||
|
||
circleCollision :: (CircleShaped a, CircleShaped b) => a -> b -> Maybe Collision | ||
circleCollision a b = do | ||
(Circle p1 r1) <- circle a | ||
(Circle p2 r2) <- circle b | ||
let centerDiff = p2 ^-^ p1 | ||
guard (centerDiff <.> centerDiff <= (r1 + r2) * (r1 + r2)) | ||
return $ Collision $ normalized centerDiff | ||
|
||
pointInRectangle :: Vector -> Rectangle -> Bool | ||
pointInRectangle (px,py) (Rectangle (minX,minY) (maxX,maxY)) | ||
| px > maxX = False | ||
| px < minX = False | ||
| py > maxY = False | ||
| py < minY = False | ||
| otherwise = True | ||
|
||
circleRectCollision :: (CircleShaped a, RoundedRectShaped b) => a -> b -> Maybe Collision | ||
circleRectCollision c r = do | ||
circle <- circle c | ||
rect <- roundedRect r | ||
circleRectCollision' circle rect | ||
where | ||
circleRectCollision' circle@(Circle (cx,cy) cr) (RoundedRect (minX,minY) (maxX,maxY) rr) | ||
--test the corners | ||
| cx <= innerMinX && cy <= innerMinY = circleCollision (Circle (innerMinX, innerMinY) rr) circle | ||
| cx >= innerMaxX && cy <= innerMinY = circleCollision (Circle (innerMaxX, innerMinY) rr) circle | ||
| cx >= innerMaxX && cy >= innerMaxY = circleCollision (Circle (innerMaxX, innerMaxY) rr) circle | ||
| cx <= innerMinX && cy <= innerMinY = circleCollision (Circle (innerMinX, innerMaxY) rr) circle | ||
-- test if collision with rectangle occured | ||
| not $ pointInRectangle (cx,cy) (Rectangle ((minX-cr), (minY-cr)) ((maxX+cr), (maxY+cr))) = Nothing | ||
-- collision definitly occured, find correct normal | ||
| otherwise = Just $ fst $ minimumBy (\(_,a) (_,b) -> compare a b) | ||
[ | ||
(Collision (-1.0,0.0), cx - minX), | ||
(Collision (1.0, 0.0), maxX - cx), | ||
(Collision (0.0,-1.0), cy - minY), | ||
(Collision (0.0, 1.0), maxY - cy) | ||
] | ||
where | ||
innerMinX = minX + rr | ||
innerMinY = minY + rr | ||
innerMaxX = maxX - rr | ||
innerMaxY = maxY - rr | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
{-# LANGUAGE Arrows #-} | ||
|
||
module WireUtils where | ||
|
||
import Control.Wire | ||
import Prelude hiding ((.),id) | ||
import Data.Maybe | ||
import qualified Data.Map as M | ||
|
||
-- dynamic set of wires. Wires are created with the creator function and the [c] parameter | ||
-- Wires that inhibit are deleted | ||
dynamicSet :: (Monad m) => (c -> Wire e m a b) -> [Wire e m a b] -> Wire e m (a, [c]) [b] | ||
dynamicSet creator ws' = mkGen $ \dt (i,new) -> do | ||
res <- mapM (\w -> stepWire w dt i) ws' | ||
let filt (Right a, b) = Just (a,b) | ||
filt _ = Nothing | ||
resx = mapMaybe filt res | ||
return (Right $ (fmap fst resx), dynamicSet creator $ (fmap snd resx) ++ (map creator new)) | ||
|
||
-- queue for the objects in the list given as parameter | ||
-- The Int argument says how many objects should be returned | ||
staticQueue :: (Monad m) => [a] -> Wire e m Int [a] | ||
staticQueue set = unfold give set | ||
where | ||
give s n = (take n s, drop n s) | ||
|
||
-- Pairs the input list with the given list, which is assumed to be infinite | ||
pairListsWith :: (Monad m) => [p] -> Wire e m [a] [(p,a)] | ||
pairListsWith pairs = proc as -> do | ||
p <- staticQueue pairs -< length as | ||
returnA -< zip p as | ||
|
||
-- Same as dynamic set, but pairs all wires with a key. The input map is than loouped with these keys to determine the input for the indubidual wires | ||
dynamicSetMap :: (Monad m) => (c -> Wire e m (Maybe a) b) -> [Wire e m (Maybe a) b] -> Wire e m (M.Map Int a, [c]) [(Int,b)] | ||
dynamicSetMap creator ws = dynamicSet creator' ws' . (second $ pairListsWith restKeys) | ||
where | ||
wireWithLookupAndKey :: (Monad m) => Int -> Wire e m (Maybe a) b -> Wire e m (M.Map Int a) (Int,b) | ||
wireWithLookupAndKey i w = (pure i) &&& (w . (arr (M.lookup i))) | ||
keys = [0,1..] | ||
restKeys = drop (length ws) keys | ||
ws' = map (uncurry wireWithLookupAndKey) $ zip keys ws | ||
creator' (i,c) = wireWithLookupAndKey i (creator c) | ||
|
||
|
||
-- same as dynamicSet, only that it can not grow | ||
shrinking :: (Monad m) => [Wire e m a b] -> Wire e m a [b] | ||
shrinking ws = dynamicSet undefined ws <<< arr (\a -> (a,[])) | ||
|
||
-- same as dynamicSetMap, only that it can not grow | ||
shrinkingMap :: (Monad m) => [Wire e m (Maybe a) b] -> Wire e m (M.Map Int a) [(Int,b)] | ||
shrinkingMap ws = dynamicSetMap undefined ws <<< arr (\a -> (a,[])) | ||
|
Oops, something went wrong.