hokug使ってみる_ツクセカのマップを利用する
公開 2025/08/04 22:26
最終更新
2025/08/06 08:42
ツクセカは2Dマップを作成して公開したりみんなで遊べたりするサービスです。
https://tsukuseka.com/
これで作ったマップを書き出してhokugで利用してみます。
hokugある程度慣れた人向けです。

これを使って適当なマップを作りました。
サンプルなので最小の8×8マスです。

使ってない素材がありますが、小さすぎる画像はこのブログにはアップできないようなので適当に入れました。
ツクセカ側の画像なのでキャラが居ますが、今回hokugではマップのみです。
ツクセカでデータを書き出します(マップ基本情報の下のほうにエクスポートボタンがあります)
今回はファイル読み込みせずコピぺします。
変数に入れて使えるようにしときましょう。
こんな感じです。
必要に応じてJSON.parse()を。
通常x,y座標は画像左上になりますが、hokugのBlockクラスでは画像中央です。
任意に変えられるようにoriginX,Yのパラメータを作りました。(Phina.jsのまねです)。
今回は左上からピッタリ敷き詰めたいので0,0にしておきます。
スプライトシートからbg.idxの分x,yをずらして切り出します。
説明が雑です。
フィールドクラス用の変数を用意します。
スプライトのサイズをマップデータから読み込んでおきます。
(手動で設定してもいいですがこうしておけばマップデータ変えてもそのまま使えるので)
マップのコマ数もあとで読み込むけど、サイズは他でも使うので先頭で設定しておく。
phaseChangedのところにinit();を入れます。
初期化処理です。中身は次の工程で作ります。
関数にせずphaseChandedに直接書いても動くけど、読みにくくなるので
実行するとフィールド部分が表示されると思います。

次はキャラを表示するのも書いてみようかな
https://tsukuseka.com/
これで作ったマップを書き出してhokugで利用してみます。
hokugある程度慣れた人向けです。
ツクセカで作業 #
素材
これを使って適当なマップを作りました。
サンプルなので最小の8×8マスです。

使ってない素材がありますが、小さすぎる画像はこのブログにはアップできないようなので適当に入れました。
ツクセカ側の画像なのでキャラが居ますが、今回hokugではマップのみです。
ツクセカでデータを書き出します(マップ基本情報の下のほうにエクスポートボタンがあります)
hokugで作業 #
hokug.config.jsでwidthとheightを256にしときますマップデータを貼り付ける #
書き出したデータをhokugのgame.js等に貼り付けます。今回はファイル読み込みせずコピぺします。
変数に入れて使えるようにしときましょう。
こんな感じです。
const map_data = {
"version": 3,
"width": 8,
"height": 8,
"baseLayer1": [
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 0, 0],
[1, 1, 0, 0, 0, 1, 0, 0]
],
"baseLayer2": [
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, 2, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1]
],
"frontLayer": [
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1]
],
"passabilityMap": [
[false, false, false, false, false, false, false, false],
[false, false, false, false, false, false, false, false],
[false, false, true, true, true, true, true, true],
[false, false, true, false, true, true, true, true],
[false, false, true, true, true, true, true, true],
[false, false, true, true, true, false, false, false],
[false, false, true, true, true, false, true, true],
[false, false, true, true, true, false, true, true]
],
"startPosition": { "x": 4, "y": 4 },
"actionPoints": [],
"mobs": [],
"spriteSheet": { "tileSize": 32 }
}
ファイルから読み込んで使う場合はjson文字列をjavascriptのオブジェクトに変換したりするのですが、こちらの環境のせいかコピペしたらそのまま使えました(そういうもの?)必要に応じてJSON.parse()を。
マップ用のclassを作る #
hokugのBlockクラスはスプライトシートに対応していないので、スプライト表示させるだけのシンプルなclassを作ります。/**
* Bgクラス
* 背景などのアニメーションしないクラス
// x;
// y;
// originX;x座標がスプライトのどの位置になるか(0;左端 〜 1;右端)
// originY;y座標がスプライトのどの位置になるか(0;上端 〜 1;下端)
// width;
// height;
// posX;マップ上のX座標
// posY;マップ上のY座標
// img;画像
// idx;スプライトシートのフレーム番号
// l:レイヤー
*/
class Bg {
constructor(x, y, w, h, posX, posY, img, idx = 0) {
this.x = x;
this.y = y;
this.originX = 0;
this.originY = 0;
this.width = w;
this.height = h;
this.posX = posX;
this.posY = posY;
this.img = img;
this.idx = idx;
this.l = 0;
}
}
originX,Y通常x,y座標は画像左上になりますが、hokugのBlockクラスでは画像中央です。
任意に変えられるようにoriginX,Yのパラメータを作りました。(Phina.jsのまねです)。
今回は左上からピッタリ敷き詰めたいので0,0にしておきます。
マップクラスの描画関数を作る #
スプライトシートを描画できるようにします。スプライトシートからbg.idxの分x,yをずらして切り出します。
説明が雑です。
/**
* Bgクラスの描画
*/
function drawBg(bg) {
//フレーム番号が-1のとき描画しない
if (bg.idx == -1) return
const w = bg.width;
const h = bg.height;
//表示位置の調整
const x = bg.x - (w * bg.originX);
const y = bg.y - (h * bg.originY);
const idx = bg.idx; //フレーム番号
const col = ~~(bg.img.width / w); //横コマ数
const row = ~~(bg.img.height / h); //縦コマ数
//フレーム番号がコマ数以上のときループ
const maxIdx = row * col;
bg.idx = idx % maxIdx;
//スプライトシートの切り取り開始位置
const sx = (idx % row) * w;
const sy = ~~(idx / row) * h;
//hokugのcanvasに描画
hokug.ctx.drawImage(bg.img, sx, sy, w, h, x, y, w, h);
}
BgクラスをまとめておくClassを作る。 #
画面に敷き詰めたスプライトを登録しておいていっぺんに処理するクラスを作りまうs。/**
* 背景等をまとめておくクラス
*/
class Field {
obj = [];
//objに登録されたスプライトをまとめて描画
draw() {
this.obj.forEach((obj)=>{
drawSprite(obj);
});
}
}
マップを読み込む処理 #
フィールドクラス用の変数を用意します。
スプライトのサイズをマップデータから読み込んでおきます。
(手動で設定してもいいですがこうしておけばマップデータ変えてもそのまま使えるので)
マップのコマ数もあとで読み込むけど、サイズは他でも使うので先頭で設定しておく。
let field;
const tileSize = map_data.spriteSheet.tileSize;
phaseChangedのところにinit();を入れます。
初期化処理です。中身は次の工程で作ります。
/**
* ゲームのフェーズが変わった時に呼び出されるイベント.
*/
hokug.phaseChanged = function() {
switch (hokug.state.phase) {
case hokug.Phase.
////ここから追加
init();
////ここまで追加
break;
case hokug.Phase.READY:
break;
case hokug.Phase.GO:
break;
case hokug.Phase.RUN:
// do nothing
break;
case hokug.Phase.FINISH:
break;
case hokug.Phase.GAMEOVER:
break;
}
};
init()の中身を作る #
ファイルの下の方に書きます。関数にせずphaseChandedに直接書いても動くけど、読みにくくなるので
/**
* ゲームを開始するための初期処理.
*/
function init() {
field = new Field(); //Fieldクラスのインスタンス
const ts = tileSize; //変数名長いので短い変数に入れて使いやすくする
const col = map_data.width; //横のコマ数をマップデータから読み込む
const row = map_data.height; //縦のコマ数をマップデータから読み込む
//baseLayer1読み込み
//縦のコマ数分ループ
for (let v = 0; v < row; v++) {
//横のコマ数分ループ
for (let i = 0; i < col; i++) {
//Bgクラスのインスタンスを作成
const bg = new Bg(i * ts, v * ts, ts, ts, i, v, hokug.res["bg.png"]);
//インデックス番号をマップデータから取得
bg.idx = map_data.baseLayer1[v][i];
//レイヤー番号を設定
bg.l = 1;
//fieldに追加
field.obj.push(bg);
}
}
//baseLayer2読み込み
for (let v = 0; v < row; v++) {
for (let i = 0; i < col; i++) {
const bg = new Bg(i * ts, v * ts, ts, ts, i, v, hokug.res["bg.png"]);
bg.idx = map_data.baseLayer2[v][i];
bg.l = 2;
field.obj.push(bg);
}
}
//fieldを描画
field.draw();
}
実行するとフィールド部分が表示されると思います。

次はキャラを表示するのも書いてみようかな
