What would be the typical game skeleton for a Haskell game, let's say a simple shoot them up for instance? I am particularly interested on the data structure, and how to manage the update of all the elements in the world, in regards of immutability issue. Just saying that
new_world=update_world(world)
is a little bit simplistic. For instance, how to deal with multiple interaction that can occurs between element of the world (collisions, reaction to player, etc....) especially when you have a lot of 'independent' elements impacted.
The main concern is about immutability of the world, which makes very difficult to update a "small" part of the world based on another subset of the world.
I love gloss
(gloss 2D library. it's very closed to your needs (I think)
A very simple example
import Graphics.Gloss
import Graphics.Gloss.Interface.Pure.Game
-- Your app data
data App = App { mouseX :: Float
, mouseY :: Float
}
-- Draw world using your app data
-- Here thing about *draw* your world (e.g. if radius > MAX then red else blue)
drawWorld (App mousex mousey) = color white $ circle mousex
-- Handle input events and update your app data
-- Here thing about user interaction (e.g. when press button start jump!)
handleEvent
(EventMotion (x, y)) -- current viewport mouse coordinates
(App _ _) = App x y
handleEvent e w = w
-- Without input events you can update your world by time
-- Here thing about time (e.g. if jumping use `t` to compute new position)
handleTime t w = w
runApp =
play
( InWindow "Test" (300, 300) (0, 0) ) -- full screen or in window
black -- background color
20 -- frames per second
( App 0 0 ) -- your initial world
drawWorld -- how to draw the world?
handleEvent -- how app data is updated when IO events?
handleTime -- how app data is updated along the time?
-- enjoy!
main = runApp
One simple example modifying some data structure (a list of circle radius) along the three event handlers (draw, input and time)
import Graphics.Gloss
import Graphics.Gloss.Interface.Pure.Game
import System.IO.Unsafe
data App = App { mouseX :: Float
, mouseY :: Float
, circleList :: [Float]
, lastTime :: Float
, currTime :: Float
}
drawWorld app =
color white $ pictures $ map circle $ circleList app
handleEvent
(EventMotion (x, y)) -- current viewport mouse coordinates
app = app { mouseX = x, mouseY = y,
-- drop circles with radius > mouse **MOVED** position
circleList = filter (<(abs x)) $ circleList app }
handleEvent e app = app
handleTime t app =
app { currTime = currTime', lastTime = lastTime', circleList = circleList' }
where currTime' = currTime app + t
-- create new circle each 1 second
createNew = currTime' - lastTime app > 1
lastTime' = if createNew then currTime' else lastTime app
-- each step, increase all circle radius
circleList' = (if createNew then [0] else []) ++ map (+0.5) (circleList app)
runApp =
play
( InWindow "Test" (300, 300) (0, 0) )
black
20
( App 0 0 [] 0 0 )
drawWorld
handleEvent
handleTime
main = runApp
with result
来源:https://stackoverflow.com/questions/26120076/what-would-be-a-typical-game-skeleton-in-haskell