tmlib-rpg マップの移動制限とかタイトルシーンとか作ってました。


tmlib.js 0.1.8 の MapSheet クラスでは、移動制限がまだ無いぽいので実装してみました。
とりあえず、タイルセットでの移動制限

VX Ace では、ビット演算でしてたけど、なんとなく配列に

# 移動制限定数、移動できる方向が true
# 方向は [2,4,6,8] の位置パラメータ
# VXAce にならって乗り物も入れるか…?
MOVE_RESTRICTION = {
  ALLOK: [true,true,true,true]
  UPOK: [false,false,false,true]
  DOWNOK: [true,false,false,false]
  LEFTOK: [false,true,false,false]
  RIGHTOK: [false,false,true,false]
  ALLNG: [false,false,false,false]
  HORIZON: [false,true,true,false]
  VERTICAL: [true,false,false,true]
  CORNER1: [false,false,true,true]
  CORNER3: [false,true,false,true]
  CORNER7: [true,false,true,false]
  CORNER9: [true,true,false,false]
  UPNG: [true,true,true,false]
  DOWNNG: [false,true,true,true]
  LEFTNG: [true,false,true,true]
  RIGHTNG: [true,true,false,true]
}

もういろいろつらい^^
実際に、この値を使うのは内部なので、あまり気にしないかもだけど、名前が特につらい…感じ、通れるのを指定するのか通れないのを指定するのか…

たとえば HORIZON は、水平に通れるの?通れないの?とかとか(OKとかNGとかもつけてるけど…ごっちゃに…)

本来は、xml で MapSheet に設定されるんだけど、ここでは json でとりあえず。というかJavaScript の Object。
xml の場合は、tilesets のエレメントに image でタイルセットを指定するんだけど、さらに 移動制限として restriction を追加しました。
これは、タイルIDに対応した、移動可能方向を設定する。

  'sample.tileset': 'img/test_tileset.png'
  'sample.mapsheet':
    tilesets: [
    _type: 'tmx'
    width: 30
    height: 30
    tilewidth: 32
    tileheight: 32
    tilesets: [
      {
        image: 'sample.tileset'
        restriction: [
          MOVE_RESTRICTION.ALLOK
          MOVE_RESTRICTION.ALLNG
          MOVE_RESTRICTION.UPOK
          MOVE_RESTRICTION.DOWNOK
          MOVE_RESTRICTION.LEFTOK
          MOVE_RESTRICTION.RIGHTOK
          MOVE_RESTRICTION.HORIZON
          MOVE_RESTRICTION.VERTICAL
          MOVE_RESTRICTION.CORNER1
          MOVE_RESTRICTION.CORNER3
          MOVE_RESTRICTION.CORNER7
          MOVE_RESTRICTION.CORNER9
          MOVE_RESTRICTION.UPNG
          MOVE_RESTRICTION.DOWNNG
          MOVE_RESTRICTION.LEFTNG
          MOVE_RESTRICTION.RIGHTNG
        ]
      }
    ]

テスト用のタイルセット

あとは、まぁ~いろいろがんばってます。

Character.coffee
  # 移動可能判定
  # TODO: ななめどしよ
  isPassable: (x, y, d) ->
    # マップの取得
    map = rpg.system.scene.map
    # 向き指定が文字列の場合は、数値に
    d = CHARACTER_DIRECTION[d] if typeof d is 'string'
    # 向き設定インデックスの計算 2,4,6,8 と言うのを、0,1,2,3 に
    di = d / 2 - 1
    # 移動先座標の計算
    nx = x + X_ROUTE[di]
    ny = y + Y_ROUTE[di]
    # マップ範囲チェック
    return false if not map.isValid(nx,ny)
    # 移動可能チェック
    return false if not map.isPassable(x,y,d)
    # 向きを逆に
    rd = REVERSE_DIRECTION[di]
    return false if not map.isPassable(nx,ny,rd)
    true
Map.coffee
  # マップ範囲内かどうか
  isValid: (x, y) -> 0 <= x and x < @width and 0 <= y and y < @height

  # 移動可能判定
  isPassable: (x, y, d) ->
    r = @_restriction(x,y)
    r[d / 2 - 1]

  # 移動制限情報の取得
  _restriction: (x, y) ->
    # TODO: イベントから見つかったらそれを返す
    # TODO: マップ固有情報から見つかったらそれを返す
    # タイルセットから
    @_restrictionTileset(x, y)

  _restrictionTileset: (x, y) ->
    i = @mapSheet.layers.length - 1
    while i >= 0
      layer = @mapSheet.layers[i--]
      if layer.type == 'layer'
        tileid = layer.data[x + y * @width]
        if tileid >= 0
          return @mapSheet.tilesets[0].restriction[tileid]
    MOVE_RESTRICTION.PASS

今見て思ったけど、オートタイルの移動制限を考えてないや…(心覚え)

あとタイトルシーンとかも作ってます。

  'scene.title':
    _type: 'json'
    background:
      image: 'scene.title.background.image'
    menus: [{
        name:'Start'
        next:
          scene:'SceneMap'
      },{
        name:'Continue'
        next:
          scene:''
      },{
        name:'Exit'
        next:
          scene:''
      }
    ]

基本的にJavaScriptは書かずにRPGが作れるようになるんだけど、json の整理とかあらためてしてるところ…
Windowクラスも作り直したし、いろいろ大変。

Sample