[GroovyとProcessing]まいんくらふと２D？

episode10は実行可能なJarの作成だったので飛ばしてepisode11。

マインクラフト2Dっぽいもの。
初期画面では空のブロックが全体に敷き詰められていて1つだけ石ブロックが置いてある。
マウスのクリック、ドラッグで石ブロックに変わる。
キーボードのSでJsonファイルにブロックの状態を保存、Lでロードする。

動画リスト：[LWJGLのチュートリアル](http://www.youtube.com/playlist?list=PL19F2453814E0E315)
動画は[ココ](http://www.youtube.com/watch?v=7G_xtkvyleM)

```groovy:DisplayTest.groovy
package episode011

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import processing.core.PApplet

class DisplayTest extends PApplet {

    def grid

    def void setup() {
        size(640, 480)
        frameRate(60)

        grid = new BlockGrid(this)
        grid.setAt(10, 10, BlockType.STONE)
    }

    def void draw() {
        background(0, 0, 0)

        grid.draw()
    }

    def void keyPressed() {
        switch (key) {
            case 's':
                grid.save(new File('save.json'))
                break
            case 'l':
                grid.load(new File('save.json'))
                break
        }
    }

    def void mouseClicked() {
        setStoneBlock()
    }

    def void mouseDragged() {
        setStoneBlock()
    }

    def setStoneBlock() {
        def gridX = floor(mouseX / World.BLOCK_SIZE)
        def gridY = floor(mouseY / World.BLOCK_SIZE)
        if (gridX >= 0 && gridX < World.BLOCKS_WIDTH
                && gridY >= 0 && gridY < World.BLOCKS_HEIGHT) {
            grid.setAt(gridX, gridY, BlockType.STONE)
        }
    }

    def static void main(args) {
        PApplet.main('episode011.DisplayTest')
    }
}

enum BlockType {
    STONE('stone.png'), AIR('air.png'), GRASS('grass.png'), DIRT('dirt.png')

    def location

    def BlockType(location) {
        this.location = location
    }
}

class Block {
    def type = BlockType.AIR
    def x, y
    def img
    def display

    def Block(display, type, x, y) {
        this.display = display
        this.type = type
        this.x = x
        this.y = y
        this.img = display.loadImage(type.location)
    }

    def draw() {
        display.image(img, x, y)
    }
}

class BlockGrid {
    def Block[][] blocks = new Block[World.BLOCKS_WIDTH][World.BLOCKS_HEIGHT];
    def display

    def BlockGrid(display) {
        this.display = display
        World.BLOCKS_WIDTH.times { x ->
            World.BLOCKS_HEIGHT.times { y ->
                blocks[x][y] = new Block(display, BlockType.AIR, x * World.BLOCK_SIZE, y * World.BLOCK_SIZE)
            }
        }
    }

    def load(loadFile) {
        def list = new JsonSlurper().parse(loadFile.newReader())
        list.each { block ->
            blocks[block.x][block.y] = new Block(
                    display,
                    BlockType.valueOf(block.type),
                    block.x * World.BLOCK_SIZE,
                    block.y * World.BLOCK_SIZE)
        }
    }

    def save(saveFile) {
        def list = []
        World.BLOCKS_WIDTH.times { x ->
            World.BLOCKS_HEIGHT.times { y ->
                list << [
                    x: blocks[x][y].x / World.BLOCK_SIZE,
                    y: blocks[x][y].y / World.BLOCK_SIZE,
                    type: blocks[x][y].type
                ]
            }
        }
        saveFile.write(new JsonBuilder(list).toString())
    }

    def setAt(x , y, type) {
        blocks[x][y] = new Block(display, type, x * World.BLOCK_SIZE, y * World.BLOCK_SIZE)
    }

    def getAt(x , y) {
        blocks[x][y]
    }

    def draw() {
        World.BLOCKS_WIDTH.times { x ->
            World.BLOCKS_HEIGHT.times { y ->
                blocks[x][y].draw()
            }
        }
    }
}

class World {
    public static final int BLOCK_SIZE = 32
    public static final int BLOCKS_WIDTH = 20
    public static final int BLOCKS_HEIGHT = 20
}
```

![grocessingGL011.png](https://qiita-image-store.s3.amazonaws.com/0/17179/706d8f73-b205-d83c-46e7-549d06c0dace.png)