Shu-thing 1.0.20071203 → 1.1
raw patch · 2 files changed
+45/−46 lines, 2 filesdep +haskell98
Dependencies added: haskell98
Files
- Shu-thing.cabal +3/−4
- Shu-thing.hs +42/−42
Shu-thing.cabal view
@@ -1,18 +1,17 @@ name: Shu-thing-version: 1.0.20071203+version: 1.1 synopsis: A vector shooter game description: A 2-D vector graphics upwards-scrolling keyboard-controlled shooter.- You shoot the enemies while dodging their bullets until you reach and defeat the enemy.+ You shoot the enemies while dodging their bullets until you reach and defeat the enemy boss. category: Game license: BSD3 license-file: LICENSE author: Hideyuki Tanaka & Takayuki Muranushi maintainer: Takayuki Muranushi <muranushi@gmail.com>, <gwern0@gmail.com>-build-depends: base, GLUT+build-depends: base, GLUT, haskell98 build-type: Simple executable: shu-thing main-is: Shu-thing.hs ghc-options: -O2 -funbox-strict-fields -Wall -Werror -optl-Wl,-s ghc-prof-options: -prof -auto-all-extensions: BangPatterns
Shu-thing.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS_GHC -fbang-patterns #-} module Main (main) where @@ -59,7 +58,7 @@ lookAt (Vertex3 0 0 (927 :: Double)) (Vertex3 0 0 (0 :: Double)) (Vector3 0 1 (0 :: Double)) dispProc :: IORef (IO Scene) -> IO () -dispProc !cp = do +dispProc cp = do m <- readIORef cp Scene next <- m writeIORef cp next @@ -67,7 +66,7 @@ data Scene = Scene (IO Scene) openingProc :: IORef [Key] -> IO Scene -openingProc !ks = do +openingProc ks = do keystate <- readIORef ks clear [ColorBuffer,DepthBuffer] @@ -92,7 +91,7 @@ else return $ Scene $ openingProc ks endingProc :: IORef [Key] -> IORef Double -> IO Scene -endingProc !ks !ctr= do +endingProc ks ctr= do keystate <- readIORef ks counter <- readIORef ctr modifyIORef ctr $ min 2420 . (+1.5) @@ -152,7 +151,7 @@ " press x key"] mainProc :: IORef GameState -> IORef [Key] -> IO Scene -mainProc !gs !ks = do +mainProc gs ks = do keystate <- readIORef ks modifyIORef gs $ updateGameState keystate gamestate <- readIORef gs @@ -172,7 +171,7 @@ timerProc m = m >> addTimerCallback 16 (timerProc m) keyProc :: IORef [Key] -> Key -> KeyState -> t -> t1 -> IO () -keyProc keystate !key !ks _ _ = +keyProc keystate key ks _ _ = case (key,ks) of (Char 'q',_) -> exitLoop (Char 'c',_) -> exitLoop @@ -183,21 +182,21 @@ bosstime = 6600 bosstime2 = 7200 -data GameObject = Player {position :: !Point,shotEnergy :: !Double,hp :: !Double}| - Bullet {position :: !Point} | - EnemyMaker {timer :: !Int,deathtimer :: !Int}| - Enemy {position :: !Point,hp :: !Double,anime :: !Int,enemySpec :: !EnemySpec} | - Explosion {position :: !Point,hp :: !Double,size :: !Double}| - EnemyBullet {position :: !Point,velocity :: !Point} | +data GameObject = Player {position :: Point,shotEnergy :: Double,hp :: Double}| + Bullet {position :: Point} | + EnemyMaker {timer :: Int,deathtimer :: Int}| + Enemy {position :: Point,hp :: Double,anime :: Int,enemySpec :: EnemySpec} | + Explosion {position :: Point,hp :: Double,size :: Double}| + EnemyBullet {position :: Point,velocity :: Point} | GameoverSignal | ClearSignal deriving (Eq) -data EnemySpec = EnemySpec {ways :: !Int,spread :: !Double,speed :: !Double,freq :: !Int,endurance :: !Double,boss :: !Bool} +data EnemySpec = EnemySpec {ways :: Int,spread :: Double,speed :: Double,freq :: Int,endurance :: Double,boss :: Bool} deriving (Eq) updateObject :: GameState -> [Key] -> GameObject -> [GameObject] -updateObject _ !ks (!Player{position=pos,shotEnergy=sen,hp=oldhp}) +updateObject _ ks (Player{position=pos,shotEnergy=sen,hp=oldhp}) = [(Player{position=newPos,shotEnergy=nsen,hp=newhp})] ++ shots where newPos :: Point @@ -226,10 +225,10 @@ shotn :: Int shotn = if (oldhp <= 0) then 0 else if (shotmode == 0) then 0 else if (sen >= 0) then 1 else 0 -updateObject _ _ (!Bullet{position=pos}) = replicate n (Bullet newpos) where +updateObject _ _ (Bullet{position=pos}) = replicate n (Bullet newpos) where newpos = pos +++ (0.0,15.0) n = if( (\(_,y) -> y > 250) pos)then 0 else 1 -updateObject !gs _ (!EnemyMaker{timer=t,deathtimer=dtime}) = +updateObject gs _ (EnemyMaker{timer=t,deathtimer=dtime}) = [EnemyMaker{timer=t+1,deathtimer=newdtime}] ++ enemies ++ deatheffects where enemies = replicate n $ Enemy{position = (320*sin(dt*dt),240),hp=1.0,anime=0,enemySpec = spec} dt :: Double @@ -266,20 +265,21 @@ ] ++ map (\o -> EnemySpec {ways=o,spread=0.1,speed=4.0,freq=20,endurance=3.0,boss=False}) [0,1 ..] -updateObject !gs _ !oldenemy@(Enemy{position=pos,hp=oldhp,anime=oldanime,enemySpec=spec}) = +updateObject gs _ oldenemy@(Enemy{position=pos,hp=oldhp,anime=oldanime,enemySpec=spec}) = replicate n (oldenemy{position=newpos,hp=newhp,anime=newanime,enemySpec=newspec}) ++ shots ++ explosions where newpos = if isBoss then (200 * sin(danime/100),200 + 40 * cos(danime/80)) else pos +++ (0.0,-1.0) newhp = oldhp newanime = oldanime + 1 - newspec = if(not isBoss) then spec else - if (oldhp>0.75) then EnemySpec{ways=0,spread=0.1,speed=5.0,freq=10,endurance=300.0,boss=True} else - if (oldhp>0.50) then EnemySpec{ways=8,spread=0.15,speed=3.0,freq=30,endurance=300.0,boss=True} else - if (oldhp>0.25) then EnemySpec{ways=2,spread=1.2,speed=15.0,freq=10,endurance=300.0,boss=True} else - if (oldhp>0.05) then EnemySpec{ways=40,spread=0.075,speed=3.0,freq=60,endurance=400.0,boss=True} else - if (oldhp>0.00) then EnemySpec{ways=15,spread=0.2,speed=16.0,freq=20,endurance=900.0,boss=True} else - EnemySpec{ways=(-1),spread=0.1,speed=3.0,freq=10,endurance=300.0,boss=True} + newspec + | (not isBoss) = spec + | (oldhp > 0.75) = EnemySpec{ways=0,spread=0.1,speed=5.0,freq=10,endurance=300.0,boss=True} + | (oldhp > 0.50) = EnemySpec{ways=8,spread=0.15,speed=3.0,freq=30,endurance=300.0,boss=True} + | (oldhp > 0.25) = EnemySpec{ways=2,spread=1.2,speed=15.0,freq=10,endurance=300.0,boss=True} + | (oldhp > 0.05) = EnemySpec{ways=40,spread=0.075,speed=3.0,freq=60,endurance=400.0,boss=True} + | (oldhp > 0.00) = EnemySpec{ways=15,spread=0.2,speed=16.0,freq=20,endurance=900.0,boss=True} + | otherwise = EnemySpec{ways=(-1),spread=0.1,speed=3.0,freq=10,endurance=300.0,boss=True} danime :: Double danime = fromIntegral oldanime explosions = if(oldhp<=0 && not isBoss) then [Explosion{position=pos,hp=1.0,size=1.0}] else [] @@ -299,9 +299,9 @@ frq = freq spec sprd= spread spec isBoss = boss spec -updateObject _ _ !e@(Explosion{}) = if(hp e>0) then [e{hp=hp e - (0.024/(size e))}] else [] -updateObject _ _ !eb@(EnemyBullet{}) = if(outofmap (position eb)) then [] else - [eb{position=position eb+++velocity eb}] +updateObject _ _ e@(Explosion{}) = if(hp e>0) then [e{hp=hp e - (0.024/(size e))}] else [] +updateObject _ _ eb@(EnemyBullet{}) = if(outofmap (position eb)) then [] else + [eb{position=position eb +++ velocity eb}] updateObject _ _ go = [go] watcher :: [GameObject] -> [GameObject] @@ -334,7 +334,7 @@ _ -> (e,b,eb,p,o:x) renderGameObject :: GameObject -> IO () -renderGameObject !Player{position=pos,hp=h} = preservingMatrix $ do +renderGameObject Player{position=pos,hp=h} = preservingMatrix $ do let (x,y) = pos color (Color3 (1.0 :: Double) h h) translate (Vector3 x y 0) @@ -342,7 +342,7 @@ rotate (x) (Vector3 0 1 0) rotate (30 :: Double) (Vector3 0 0 1) renderObject Wireframe Dodecahedron -renderGameObject !Bullet{position=pos} = preservingMatrix $ do +renderGameObject Bullet{position=pos} = preservingMatrix $ do let (x,y) = pos color (Color3 (0.6 :: Double) 0.6 1.0) translate (Vector3 x y 0) @@ -350,7 +350,7 @@ rotate (45 :: Double) (Vector3 0 1 0) rotate (90 :: Double) (Vector3 1 0 0) renderObject Wireframe Tetrahedron -renderGameObject !Enemy{position=pos,anime=a,hp=h,enemySpec=EnemySpec{boss=False}} = preservingMatrix $ do +renderGameObject Enemy{position=pos,anime=a,hp=h,enemySpec=EnemySpec{boss=False}} = preservingMatrix $ do let (x,y) = pos color (Color3 (cos rho) (sin rho) (0.0 :: Double)) translate (Vector3 x y 0) @@ -359,7 +359,7 @@ renderObject Wireframe Octahedron where theta = fromIntegral a rho = h * 3.14 / 2 -renderGameObject !Enemy{position=pos,anime=a,hp=h,enemySpec=EnemySpec{boss=True}} = preservingMatrix $ do +renderGameObject Enemy{position=pos,anime=a,hp=h,enemySpec=EnemySpec{boss=True}} = preservingMatrix $ do let (x,y) = pos color (Color3 (cos rho) (sin rho) (0.0 :: Double)) translate (Vector3 x y 0) @@ -368,7 +368,7 @@ renderObject Wireframe (Teapot 1.0) where theta = fromIntegral a rho = h * 3.14 / 2 -renderGameObject !Explosion{position=pos,hp=h,size=s}= preservingMatrix $ do +renderGameObject Explosion{position=pos,hp=h,size=s}= preservingMatrix $ do let (x,y) = pos color (Color3 h 0.0 0.0) translate (Vector3 x y 0) @@ -377,7 +377,7 @@ scale r r r renderObject Wireframe Icosahedron where r = s*(100 - h*h*80) -renderGameObject !EnemyBullet{position=pos} = preservingMatrix $ do +renderGameObject EnemyBullet{position=pos} = preservingMatrix $ do let (x,y) = pos color (Color3 (1.0 :: Double) 1.0 1.0) translate (Vector3 x y 0) @@ -393,16 +393,16 @@ [(Player{position=(0.0,0.0),shotEnergy=0.0,hp=1.0}),(EnemyMaker{timer=0,deathtimer=0})]} renderGameState :: GameState -> IO () -renderGameState !GameState{objects=os} = mapM_ renderGameObject os +renderGameState GameState{objects=os} = mapM_ renderGameObject os updateGameState :: [Key] -> GameState -> GameState -updateGameState !ks !gs@(GameState { objects=os }) = newgs where +updateGameState ks gs@(GameState { objects=os }) = newgs where newgs = GameState{objects = watcher $ concatMap (updateObject gs ks) os} playerpos :: GameState -> Point playerpos = position . findplayer findplayer :: GameState -> GameObject -findplayer !GameState{objects=os} = player where +findplayer GameState{objects=os} = player where [player] = filter (\o -> case o of Player{} -> True _ -> False) os @@ -425,20 +425,20 @@ (ax,ay) +++ (bx,by) = (ax+bx, ay+by) (-+-) :: (Num t1, Num t) => (t, t1) -> (t, t1) -> (t, t1) -(!ax,!ay) -+- (!bx,!by) = (ax-bx,ay-by) +(ax,ay) -+- (bx,by) = (ax-bx,ay-by) (*++) :: (Num t) => (t, t) -> t -> (t, t) -(!ax,!ay) *++ (!s) = (ax*s,ay*s) +(ax,ay) *++ (s) = (ax*s,ay*s) (***) :: (Num t) => (t, t) -> (t, t) -> (t, t) -(!ax,!ay) *** (!bx,!by) = (ax*bx-ay*by,ay*bx+ax*by) +(ax,ay) *** (bx,by) = (ax*bx-ay*by,ay*bx+ax*by) sq :: Double -> Double -sq !x = x*x +sq x = x*x distance, distance2 :: Point -> Point -> Double distance a b= sqrt $ distance2 a b -distance2 !(ax,ay) !(bx,by) = sq(ax-bx) + sq(ay-by) +distance2 (ax,ay) (bx,by) = sq(ax-bx) + sq(ay-by) outofmap :: Point -> Bool -outofmap !(x,y) = (not $ abs x < 320) || (not $ abs y < 240) +outofmap (x,y) = (not $ abs x < 320) || (not $ abs y < 240)