エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

ゲーム画面を作る

2日ほどこねくり回してようやくゲーム画面に相当するものができた。乱数の扱いが、最初いまひとつピンとこなかったのだけれど、ようやく把握…できたと思う。


以下、コード。

import Graphics.UI.GLUT
import Control.Exception
import System.Exit
import System.Random
import Data.IORef

main = do
  board <- (makeBoard >>= newIORef)
  getArgsAndInitialize
  createWindow "Sample"
  initialDisplayMode    $= [RGBAMode]
  displayCallback       $= display board
  keyboardMouseCallback $= Just keyboardMouse
  clearColor            $= Color4 0.0 0.0 0.2 0.2
  mainLoop

makeBoard = do
  g <- getStdGen
  let colors = map (\ n -> colorList !! n) $ randomRs (0, length colorList - 1) g
  return $ take 10 $ getTable 10 colors
  where
    getTable n colors = column : getTable n rest
      where (column, rest) = splitAt n colors

blue    = Color3 (0.0::Double) 0.0 1.0
green   = Color3 (0.0::Double) 1.0 0.0
cyan    = Color3 (0.0::Double) 1.0 1.0
red     = Color3 (1.0::Double) 0.0 0.0
magenta = Color3 (1.0::Double) 0.0 1.0
yellow  = Color3 (1.0::Double) 1.0 0.0
white   = Color3 (1.0::Double) 1.0 1.0
colorList = [blue, green, cyan, red, magenta, yellow, white]

keyboardMouse key keystate modifiers position =
  case key of
    Char 'q' -> throwIO $ ExitException ExitSuccess
    _        -> return ()

display points = do
  clear [ColorBuffer]
  ps <- readIORef points
  let posList = map (? n -> n / 10) [-9, -7..]
  mapM_ drawPoint $ concat $ zipWith (\ x column -> zipWith (\ y c -> (x, y, c)) posList column) posList ps
  flush

drawPoint (x, y, c) = do
  color c
  renderPrimitive Polygon $ mapM_ vertex 
    [
    Vertex3 (-0.07 + x) (-0.07 + y) 0.0,
    Vertex3 ( 0.00 + x) (-0.10 + y) 0.0,
    Vertex3 ( 0.07 + x) (-0.07 + y) 0.0,
    Vertex3 ( 0.10 + x) ( 0.00 + y) 0.0,
    Vertex3 ( 0.07 + x) ( 0.07 + y) 0.0,
    Vertex3 ( 0.00 + x) ( 0.10 + y) 0.0,
    Vertex3 (-0.07 + x) ( 0.07 + y) 0.0,
    Vertex3 (-0.10 + x) ( 0.00 + y) (0.0 :: GLfloat)
    ]