はじめに
前回の記事ではBGM・効果音を実装しました。今回は「玄関を開けて屋敷の中に入る」ステージ(room1-1)を追加し、左右に部屋を移動できるボタンを実装します。
左右移動は、タップ移動・戻るの応用になりますのでシンプルに実装が進むと思います。
- 第1回【Axmol Engine】 スプラッシュ画面シーンを実装する
- 第2回【Axmol Engine】 タイトルシーンを作って画像を表示する
- 第3回【Axmol Engine】 タップした領域への移動
- 第4回【Axmol Engine】 ノードを使用してポップアップを実装する
- 第5回【Axmol Engine】 テクスチャアトラスでダイヤル錠UIを実装する
- 第6回【Axmol Engine】 リファクタリング(メモリ消費対応、ステージをJSON管理、処理修正)+戻るボタン設置
- 第7回【Axmol Engine】 ローカルストレージでステージ進捗管理・ギミックをJSONで管理
- 第8回【Axmol Engine】 アイテムシステムの実装1 - アイテムの取得 -
- 第9回【Axmol Engine】 アイテムシステムの実装2 - アイテムの選択・表示 -
- 第10回【Axmol Engine】 アイテムシステムの実装3 - アイテムの使用 -
- 第11回【Axmol Engine】 BGM・効果音の実装 -
- 第12回【Axmol Engine】 左右移動ボタンの実装 -(今回)
用意した画像(Chat-GPT作成)
bg_stage_004.png(room1-1用):廃墟の広間

bg_stage_005.png(room1-2用):広間正面から左90度向いた視点

bg_stage_006.png(room1-3用):広間正面から右90度向いた視点

イメージ的にはこのような感じです
1. 屋敷内ステージ(room1-1)の追加
まずは左右移動とは直接関係無いですが、左右ボタン実装のため、ステージの追加実装と移動実装を行います。
プロンプト:
"room1-1"を追加して、"bg": "bg_stage_004.png"、"back": "infront" を定義してください
back を infront(玄関前)にすることで、戻るボタンで玄関前に戻れるようにします。
"room1-1": [
{
"bg": "bg_stage_004.png",
"touches": [],
"back": "infront"
}
]
2. 玄関からroom1-1への導線
プロンプト:
"infront"の2番目のtouchesの2番目の"stage"を"room1-1"に
infront は「鍵閉まり状態」と「鍵を開けた後の状態」の2パターンを持っています。鍵を開けた後のオブジェクトの2番目のタッチ領域(ドア部分)の遷移先を door から room1-1 に変更します。これで鍵を開けた後にドアをタップすると屋敷の中に入れるようになります。
{
"bg": "bg_stage_001_2.png",
"touches": [
{ "rect": [250, 41, 350, 510], "stage": "post" },
{ "rect": [450, 0, 830, 841], "stage": "room1-1" }
],
"back": "start"
}
3. 隣接する部屋(room1-2 / room1-3)の追加
プロンプト:
"room1-2"を追加して"bg": "bg_stage_005.png"、"room1-3"を追加して"bg": "bg_stage_006.png"をそれぞれ定義してください
room1-1 の左右に配置する部屋を追加します。
"room1-2": [
{
"bg": "bg_stage_005.png",
"touches": [],
"back": "infront"
}
],
"room1-3": [
{
"bg": "bg_stage_006.png",
"touches": [],
"back": "infront"
}
]
4. 左ボタンの実装
プロンプト:
"room1-1"に"left": "room1-2"を追加してください
"left"があるステージの場合は、画面左側中程にbtn_back.pngを時計回りに90度回転させたボタンを設置してください
このボタンをタップすると、指定ステージに遷移します
StageDef に left フィールドを追加し、JSONで左方向の遷移先を定義できるようにします。表示は既存の btn_back.png を流用し、90度回転させることで方向性を持たせています。
"room1-1": [
{
"bg": "bg_stage_004.png",
"touches": [],
"back": "infront",
"left": "room1-2"
}
]
struct StageDef {
std::string bg;
std::vector<TouchZone> touches;
std::string back;
std::string left; // 追加
std::vector<StageItem> items;
};
def.left = entry.HasMember("left") ? entry["left"].GetString() : "";
if (!def.left.empty())
{
auto leftItem = MenuItemImage::create(
"btn_back.png", "btn_back.png",
[this, leftStage = def.left](Object*) {
_stage = leftStage;
ax::UserDefault::getInstance()->setStringForKey("stage", _stage);
ax::UserDefault::getInstance()->flush();
_stageStatus = 0;
showStageBg();
});
if (leftItem)
{
constexpr float margin = 20.0f;
leftItem->setRotation(90.0f);
leftItem->setPosition(Vec2(
safeArea.origin.x + kItemPanelWidth / 2,
safeArea.origin.y + margin + leftItem->getContentSize().height / 2));
auto leftMenu = Menu::create(leftItem, nullptr);
leftMenu->setTag(301);
this->addChild(leftMenu, 5);
}
}
ステージ切り替え時に古いボタンが残らないよう、showStageBg() の冒頭で removeChildByTag(301) を追加します。
5. 左ボタンの位置調整
プロンプト:
leftのボタンは画面右側にあるアイテムスロット分の余白を左側に開けてください
Y軸は戻るボタンを合わせてください
プロンプト:
左ボタンを現在の左マージンの中央にしてください
画面右側には幅200pxのアイテムスロットパネルが常設されています。左ボタンにも同じ幅の余白を左側に確保し、左右対称のレイアウトにします。パネル幅はファイルスコープの定数に切り出して init() 側と共有します。
static constexpr float kItemPanelWidth = 200.0f;
X座標はマージン領域(200px)の中央、Y座標は戻るボタンと統一します。
leftItem->setPosition(Vec2(
safeArea.origin.x + kItemPanelWidth / 2,
safeArea.origin.y + margin + leftItem->getContentSize().height / 2));
6. 右ボタンの実装
プロンプト:
"room1-1" に"right": "room1-3" を追加定義してください。"right" が存在する場合、btn_backを反時計回りに90度回転させたボタンを画面右側、アイテムスロットより左に設置して、タップされたら指定のステージに遷移
左ボタンと対になる right を追加します。回転方向は反時計回り(-90度)で、アイテムスロットの左側に配置します。
"room1-1": [
{
"bg": "bg_stage_004.png",
"touches": [],
"back": "infront",
"left": "room1-2",
"right": "room1-3"
}
]
struct StageDef {
// ...
std::string left;
std::string right; // 追加
};
def.right = entry.HasMember("right") ? entry["right"].GetString() : "";
if (!def.right.empty())
{
auto rightItem = MenuItemImage::create(
"btn_back.png", "btn_back.png",
[this, rightStage = def.right](Object*) {
_stage = rightStage;
ax::UserDefault::getInstance()->setStringForKey("stage", _stage);
ax::UserDefault::getInstance()->flush();
_stageStatus = 0;
showStageBg();
});
if (rightItem)
{
constexpr float margin = 20.0f;
rightItem->setRotation(-90.0f);
rightItem->setPosition(Vec2(
visibleSize.width - kItemPanelWidth - margin - rightItem->getContentSize().height / 2,
safeArea.origin.y + margin + rightItem->getContentSize().height / 2));
auto rightMenu = Menu::create(rightItem, nullptr);
rightMenu->setTag(302);
this->addChild(rightMenu, 5);
}
}
showStageBg() の冒頭に removeChildByTag(302) も追加します。
7. room1-2 / room1-3 の遷移先を left/right に変更
プロンプト:
"room1-2" の "back" は削除して、"right": "room1-1" を追加、"room1-3" の "back" は削除して、"left": "room1-1" を追加してください
room1-1 を中心に左右へ部屋が並ぶ形で、行き来がどちらも左右ボタンで完結する構成にします。
"room1-2": [
{
"bg": "bg_stage_005.png",
"touches": [],
"right": "room1-1"
}
],
"room1-3": [
{
"bg": "bg_stage_006.png",
"touches": [],
"left": "room1-1"
}
]
戻る・左・右ボタンの位置関係
3種類のボタンはすべて同じ btn_back.png を使い回し、回転角と配置だけで役割を変えています。
| ボタン | 回転角 | 配置 | tag |
|---|---|---|---|
| 戻る(back) | 0度 | 画面下中央 | 300 |
| 左(left) | 時計回り90度 | 左マージン(200px)の中央 | 301 |
| 右(right) | 反時計回り90度 | アイテムスロット左端から20pxマージン | 302 |
Y座標はすべて safeArea.origin.y + margin + ボタン高さ/2 で統一しています。showStageBg() の冒頭で3つのタグをまとめて removeChildByTag() することで、ステージ切り替え時に古いボタンが残らないようにしています。
成果物
左ボタンで左を向く、右ボタンで右を向く
まとめ
| 実装内容 | 対応ファイル |
|---|---|
| 屋敷内ステージ room1-1 の追加と導線 | stages.json |
| room1-2 / room1-3 の追加 | stages.json |
| 左ボタン(時計回り・配置・遷移) | MainScene.cpp |
| 右ボタン(反時計回り・配置・遷移) | MainScene.cpp |
| room1-2/room1-3 の遷移を left/right に統一 | stages.json |
back と同じ仕組みを left / right に横展開するだけで、JSON側の定義追加のみで部屋同士の左右移動が組み込める設計になっています。
