消去パネルの選択表示にも対応させる。
(InfoArea.cpp)
void InfoArea::Update(void)
{
int mx, my,ax,ay;
int prevBtn = edScene->GetPrevButtonStat(); //直前のマウスボタンを取得
int nowBtn = edScene->GetNowButtonStat(); //今のマウスボタン状態を取得
GetMousePoint(&mx,&my); //現在のマウスの座標(ウインドウ内)を取得(mx,myに格納される)
//情報エリアにマウスカーソルが載っているかどうかを判定
if (mx >= INFO_AREA_SX && mx < INFO_AREA_SX + INFO_AREA_WID && my >= INFO_AREA_SY && my < INFO_AREA_SY + INFO_AREA_HIG) {
//情報エリア内の座標に変換する
ax = mx - INFO_AREA_SX;
ay = my - INFO_AREA_SY;
if ((prevBtn & MOUSE_INPUT_LEFT) != 0 && (nowBtn & MOUSE_INPUT_LEFT) == 0) {
//アップトリガーで左ボタンの押下判定(押された場合)
//選択一覧内のマップチップが選択されたかどうかを調べる
for (int ii = 0; ii < E_LAND_MAX; ii++) {
int dx = INFO_CHIP_LIST_SX + (MAP_CHIP_WID + INFO_CHIP_DISTANCE_DX) * (ii % INFO_CHIP_DSP_XNUM);
int dy = INFO_CHIP_LIST_SY + (MAP_CHIP_HIG + INFO_CHIP_DISTANCE_DY) * (ii / INFO_CHIP_DSP_XNUM);
if (ax >= dx && ax < dx + MAP_CHIP_WID && ay >=dy&&ay<dy+MAP_CHIP_HIG) {
selChipKind = ii;
break;
}
}
//消去用地形が選択されたかどうかを調べる
if (ax >= INFO_CHIP_CLR_SX && ax < INFO_CHIP_CLR_SX + MAP_CHIP_WID && ay >= INFO_CHIP_CLR_SY && ay < INFO_CHIP_CLR_SY + MAP_CHIP_HIG) {
selChipKind = E_LAND_CLEAR;
}
}
}
}
全消去ボタンを描画
(InfoArea.cpp)
void InfoArea::Draw(void)
{
SetDrawScreen(infScrn); //情報画面用のスクリーンに切り替え
DrawBox(0, 0, INFO_AREA_WID, INFO_AREA_HIG, GetColor(255, 255, 255), true);
DrawString(INFO_INDEX_SX, INFO_INDEX_LIST_SY, "地形一覧", GetColor(247, 14, 70));
//地形選択画像リストの描画
for (int xy = 0; xy < E_LAND_MAX; xy++)
{
//座標計算だけ先に行う
int dx = INFO_CHIP_LIST_SX + (MAP_CHIP_WID + INFO_CHIP_DISTANCE_DX) * (xy % INFO_CHIP_DSP_XNUM);
int dy = INFO_CHIP_LIST_SY + (MAP_CHIP_HIG + INFO_CHIP_DISTANCE_DY) * (xy / INFO_CHIP_DSP_XNUM);
//描画したい画像のハンドルを取得する
int land = edScene->GetLandImageHndl((eLandFormKind)xy);//引数の型が違うのでキャストする
DrawGraph(dx, dy, land, true);
}
//消去用地形
DrawBox(INFO_CHIP_CLR_SX, INFO_CHIP_CLR_SY, INFO_CHIP_CLR_SX + MAP_CHIP_WID, INFO_CHIP_CLR_SY + MAP_CHIP_HIG, GetColor(0, 0, 0), true);
DrawString(INFO_CHIP_LIST_SX + 8, INFO_CHIP_CLR_SY + 8, "消", GetColor(255, 255, 255));
//選択地形の描画
DrawString(INFO_INDEX_SX, INFO_INDEX_SELCHIP_SY, "選択地形", GetColor(23u, 14, 70));
if (selChipKind == E_LAND_NON || selChipKind == E_LAND_CLEAR) {
DrawBox(INFO_SELCHIP_DX,INFO_SELCHIP_DY,INFO_SELCHIP_DX+MAP_CHIP_WID,INFO_SELCHIP_DY+MAP_CHIP_HIG,GetColor(0, 0, 0), true);
if (selChipKind == E_LAND_CLEAR) {
DrawString(INFO_SELCHIP_DX + 8, INFO_SELCHIP_DY + 8, "消", GetColor(255, 255, 255));
}
}
else {
int hndl = edScene->GetLandImageHndl((eLandFormKind)selChipKind);//描画中の地形番号をキャストして渡して、ハンドル番号をhndlで受ける
DrawGraph(INFO_SELCHIP_DX, INFO_SELCHIP_DY, hndl, true);
}
//消去用地形が選択されたかどうかを調べる
if (ax >= INFO_CHIP_CLR_SX && ax < INFO_CHIP_CLR_SX + MAP_CHIP_WID && ay >= INFO_CHIP_CLR_SY && ay < INFO_CHIP_CLR_SY + MAP_CHIP_HIG) {
selChipKind = E_LAND_CLEAR;
}
//全消去ボタンが押されたかどうかを調べる
if (ax >= ALLCLEAR_BTN_DX && ax < ALLCLEAR_BTN_DX + ALLCLEAR_BTN_WID && ay >= ALLCLEAR_BTN_DY && ay < ALLCLEAR_BTN_DY + ALLCLEAR_BTN_HIG) {
//edScene->ClearAllMapData();まだ未実装
}
//セーブボタンが押されたかどうかを調べる
f (ax >= SAVE_BTN_DX && ax < SAVE_BTN_DX + SAVELOAD_BTN_WID && ay >= SAVE_BTN_DY && ay < SAVE_BTN_DY + SAVELOAD_BTN_HIG) {
//edScene->SaveMapData();まだ未実装
}
//ロードボタンが押されたかどうかを調べる
if( ax >= LOAD_BTN_DX && ax < LOAD_BTN_DX + SAVELOAD_BTN_WID && ay >= LOAD_BTN_DY && ay < LOAD_BTN_DY + SAVELOAD_BTN_HIG) {
//edScene->LoadMapData();まだ未実装
}
この部分は要するにこう。
// 引数
DrawBox(x座標, y座標, x+幅, y+高さ, 色, 塗りつぶし);
DrawString(x+文字オフセット, y+文字オフセット, "ラベル", 色);
追加したボタンの押下判定を作る。
(InfoArea.cpp)
void InfoArea::Update(void)
{
int mx, my,ax,ay;
int prevBtn = edScene->GetPrevButtonStat(); //直前のマウスボタンを取得
int nowBtn = edScene->GetNowButtonStat(); //今のマウスボタン状態を取得
GetMousePoint(&mx,&my); //現在のマウスの座標(ウインドウ内)を取得(mx,myに格納される)
//情報エリアにマウスカーソルが載っているかどうかを判定
if (mx >= INFO_AREA_SX && mx < INFO_AREA_SX + INFO_AREA_WID && my >= INFO_AREA_SY && my < INFO_AREA_SY + INFO_AREA_HIG) {
//情報エリア内の座標に変換する
ax = mx - INFO_AREA_SX;
ay = my - INFO_AREA_SY;
if ((prevBtn & MOUSE_INPUT_LEFT) != 0 && (nowBtn & MOUSE_INPUT_LEFT) == 0) {
//アップトリガーで左ボタンの押下判定(押された場合)
//選択一覧内のマップチップが選択されたかどうかを調べる
for (int ii = 0; ii < E_LAND_MAX; ii++) {
int dx = INFO_CHIP_LIST_SX + (MAP_CHIP_WID + INFO_CHIP_DISTANCE_DX) * (ii % INFO_CHIP_DSP_XNUM);
int dy = INFO_CHIP_LIST_SY + (MAP_CHIP_HIG + INFO_CHIP_DISTANCE_DY) * (ii / INFO_CHIP_DSP_XNUM);
if (ax >= dx && ax < dx + MAP_CHIP_WID && ay >=dy&&ay<dy+MAP_CHIP_HIG) {
selChipKind = ii;
break;
}
}
//消去用地形が選択されたかどうかを調べる
if (ax >= INFO_CHIP_CLR_SX && ax < INFO_CHIP_CLR_SX + MAP_CHIP_WID && ay >= INFO_CHIP_CLR_SY && ay < INFO_CHIP_CLR_SY + MAP_CHIP_HIG) {
selChipKind = E_LAND_CLEAR;
}
//全消去ボタンが押されたかどうかを調べる
if (ax >= ALLCLEAR_BTN_DX && ax < ALLCLEAR_BTN_DX + ALLCLEAR_BTN_WID && ay >= ALLCLEAR_BTN_DY && ay < ALLCLEAR_BTN_DY + ALLCLEAR_BTN_HIG) {
edScene->ClearAllMapData();
}
//セーブボタンが押されたかどうかを調べる
if (ax >= SAVE_BTN_DX && ax < SAVE_BTN_DX + SAVELOAD_BTN_WID && ay >= SAVE_BTN_DY && ay < SAVE_BTN_DY + SAVELOAD_BTN_HIG) {
edScene->SaveMapData();
}
//ロードボタンが押されたかどうかを調べる
if( ax >= LOAD_BTN_DX && ax < LOAD_BTN_DX + SAVELOAD_BTN_WID && ay >= LOAD_BTN_DY && ay < LOAD_BTN_DY + SAVELOAD_BTN_HIG) {
edScene->LoadMapData();
}
}
}
}
〇ifの羅列かelse ifか
ifとelse ifの違いは「同時に条件が成立する可能性があるかどうか」です。
そして今回のようなマウスクリック座標による判定では、同時に複数の条件が成立することは基本的にないので、ifの羅列でも構造的には問題ありません。
🧠 if vs else if の構造的違い
if (...) {} | 条件が成立すれば実行 | すべての |
else if (...) {} | 直前の | どれか1つだけが実行される(最初に成立したもの) |
🧩今回のコード構造における意味
if (ax >= INFO_CHIP_CLR_SX && ...) {
selChipKind = E_LAND_CLEAR;
}
if (ax >= ALLCLEAR_BTN_DX && ...) {
// 全消去
}
else if (ax >= SAVE_BTN_DX && ...) {
// セーブ
}
else if (ax >= LOAD_BTN_DX && ...) {
// ロード
}
INFO_CHIP_CLR_SXの判定は選択チップ用で、他のボタンとは別のUI領域。ALLCLEAR,SAVE,LOADは同じUIエリア内のボタン群なので、同時に押されることはない。- つまり、すべて
ifで書いても、実行結果は変わらない。
✅構造的にどう書くべきか?
パターンA:全部ifで書く(並列評価)
if (選択チップが押された) { ... }
if (全消去が押された) { ... }
if (セーブが押された) { ... }
if (ロードが押された) { ... }
→ 構造が明快。それぞれの判定が独立していることがわかる。
パターンB:else ifで書く(排他評価)
if (全消去が押された) { ... }
else if (セーブが押された) { ... }
else if (ロードが押された) { ... }
→ 排他性を強調したいときに有効。
→ ただし、選択チップ判定は別扱いにすべき。(by Copilot)
未実装の関数等を使わずに、動作を確認する場合には
“int a = 1;”のような、意味のないコードを書いて、その行にブレークポイントを設置⇒デバッグで止まるかどうかを確認するのも一つの方法。
※ブレークポイントをまとめて削除
デバッグ>すべてのブレークポイントを削除

EditArea.cpp、EditArea.hを作成。記述していく。
(EditArea.h)
#pragma once
#include "StDefine.h"
class EditScene;
class EditArea
{
public:
// マップ表示エリアの幅
static const int MAP_AREA_WID = EDIT_AREA_WID - MAP_CHIP_WID;
// マップ表示エリアの高さ
static const int MAP_AREA_HIG = EDIT_AREA_HIG - MAP_CHIP_HIG;
// マップ表示エリアの表示開始位置X
static const int MAP_AREA_SX = MAP_CHIP_WID / 2;
// マップ表示エリアの表示開始位置Y
static const int MAP_AREA_SY = MAP_CHIP_HIG / 2;
// 上矢印
static const int UPPER_ARROW_SX = MAP_AREA_SX;
static const int UPPER_ARROW_SY = 0;
static const int UPPER_ARROW_WID = MAP_AREA_WID;
static const int UPPER_ARROW_HIG = 14;
// 下矢印
static const int LOWER_ARROW_SX = UPPER_ARROW_SX;
static const int LOWER_ARROW_SY = MAP_AREA_SY + MAP_AREA_HIG + 2;
static const int LOWER_ARROW_WID = UPPER_ARROW_WID;
static const int LOWER_ARROW_HIG = UPPER_ARROW_HIG;
// 左矢印
static const int LEFT_ARROW_SX = 0;
static const int LEFT_ARROW_SY = MAP_AREA_SY;
static const int LEFT_ARROW_WID = 14;
static const int LEFT_ARROW_HIG = MAP_AREA_HIG;
// 右矢印
static const int RIGHT_ARROW_SX = MAP_AREA_SX + MAP_AREA_WID + 2;
static const int RIGHT_ARROW_SY = LEFT_ARROW_SY;
static const int RIGHT_ARROW_WID = LEFT_ARROW_WID;
static const int RIGHT_ARROW_HIG = LEFT_ARROW_HIG;
// 編集エリアの横のマップチップ表示個数
static const int DSP_CHIP_XNUM = MAP_AREA_WID / MAP_CHIP_WID;
// 編集エリアの縦のマップチップ表示個数
static const int DSP_CHIP_YNUM = MAP_AREA_HIG / MAP_CHIP_HIG;
EditArea(EditScene* eds); //親クラスのインスタンスのポインタを受け取る
~EditArea(void);
bool SystemInit(void);
void Update(void);
void Draw(void);
bool Release(void);
int GetEditScreenHandle(void) { return edScrn; }
void AllMapClear(void); //マップデータを全消去する関数
private:
EditScene* edScene; //EditSceneClassのインスタンスのポインタ
int edScrn; //編集エリア用スクリーンハンドル
int dspStartX, dspStartY; //編集エリア内の表示開始マップチップ座標
int mapData[MAP_SIZE_Y][MAP_SIZE_X]; //マップデータ(縦/横の順序で定義)
};
関数の実装。
(EditArea.cpp)
//----------------------------------------------------
// map editor
// name:ゆき
//----------------------------------------------------
//EditArea class
#include"DxLib.h"
#include"EditArea.h"
#include"EditScene.h"
EditArea::EditArea(EditScene* eds)
{
edScene = eds;
edScrn = -1;
}
EditArea::~EditArea(void)
{
}
bool EditArea::SystemInit(void)
{
//スクリーンの作成
edScrn = MakeScreen(EDIT_AREA_WID, EDIT_AREA_HIG, true);
if (edScrn == -1)return false;
dspStartX = dspStartY = 0;
//マップデータの初期化(全て海にする)
AllMapClear();
return true;
}
void EditArea::Update(void)
{
//編集エリアの更新処理
}
void EditArea::Draw(void)
{
//編集エリアの描画処理
}
bool EditArea::Release(void)
{
return true;
}
void EditArea::AllMapClear(void)
{
//マップデータの全消去(全て空白にする)
for (int yy = 0; yy < MAP_SIZE_Y; yy++) {
for (int xx = 0; xx < MAP_SIZE_X; xx++) {
mapData[yy][xx] = E_LAND_NON;
}
}
}
MakeScreen()
MakeScreen(EDIT_AREA_WID, EDIT_AREA_HIG, true) って、DxLibの関数だよね?? そもそも裏画面とか表画面って概念は、Windowsアプリなら大体同じってならったけど、実装的にはDxLibで定義されているって理解でいいかな?
はい、MakeScreenはDxLibの関数で、裏画面・表画面の概念もDxLib内で定義・管理されています。Windows APIにも類似の概念はありますが、DxLibではそれを独自に抽象化して扱いやすくしています。
🧠 MakeScreen()の役割と構造
- 関数定義:
int MakeScreen(int SizeX, int SizeY, int AlphaFlag); - 目的:指定サイズの「描画可能なスクリーン(仮想画面)」を作成し、そのハンドルを返す。
- 引数の意味:
SizeX,SizeY:スクリーンの幅と高さ(例:EDIT_AREA_WID,EDIT_AREA_HIG)AlphaFlag:trueならαチャンネル付き(半透明対応)
このスクリーンは、**裏画面とは別に存在する“描画用のバッファ”**で、SetDrawScreen()で描画先を切り替えることで、一時的な描画や合成処理が可能になります。
🪟 Windowsアプリとの関係
- Windows APIにも**バックバッファ(裏画面)→フロントバッファ(表画面)**という描画モデルがあります。
- DxLibはそれをゲーム開発向けに抽象化・簡略化して提供しており、
DX_SCREEN_BACK:裏画面(通常の描画先)DX_SCREEN_FRONT:表画面(直接描画)MakeScreen():任意のサイズの仮想スクリーンを生成
つまり、裏画面・表画面の概念はWindowsにもあるけれど、DxLibではそれを独自に管理・拡張しているという理解で正しいです。
🧩ゆきさんの理解は文明的に正確
「Windowsアプリなら大体同じってならったけど、実装的にはDxLibで定義されているって理解でいいかな?」
→ まさにその通り。概念は共通、実装はライブラリ依存。
DxLibは、Windowsの描画モデルをベースに、教育・ゲーム開発向けに構造化された抽象レイヤーです。
🧩 DxLibの描画構造(簡易図
[DX_SCREEN_BACK] ← 通常の裏画面(SetDrawScreenで指定)
↑
│
[MakeScreenで作った仮想スクリーン] ← 任意サイズの描画バッファ
↓
[DX_SCREEN_FRONT] ← 表画面(画面に表示される)
🛠 実用例(MapEditor授業での使い方)
int infScrn = MakeScreen(EDIT_AREA_WID, EDIT_AREA_HIG, true);
SetDrawScreen(infScrn); // 情報エリアの描画先を切り替え
DrawBox(...); // 情報エリアに描画
SetDrawScreen(DX_SCREEN_BACK); // 元に戻す
→ こうすることで、情報エリアだけを別スクリーンに描画して、合成表示することが可能になります。
「裏画面・表画面の概念はWindowsにもあるけど、実装はDxLibで定義されている」——その通りです。

コメント