第05回 関数による処理の整理
3 / 3 総合確認と次の教材への接続
このステップの目的
値、条件、関数の働きを使って変更箇所を自分で選び、実行結果を説明します。
理解度確認の総合課題
本実習で学んだ内容が定着しているかを確認するため、次の4つの課題に取り組んでみましょう。
- 青いロボットの移動速度の変更: キー入力による移動量を、1フレームあたり3ピクセルから5ピクセルに変更してください。
- オレンジ色のロボットの初期進行方向の変更: オレンジ色のロボットが起動直後から左方向へ進むように変更してください。
- 境界判定関数の動作トレース: 式
KeepInside(700, 592)を評価した際、どの行の判定が真となり、最終的にどのような値が返されるか説明してください。 - 描画と状態更新の分離検証: オレンジ色のロボットを描画している行
DrawCharacter(walkerX, walkerY, walker);をコメントアウト(無効化)した場合、オレンジ色の画像読み込みや座標更新walkerX = walkerX + speed;は実行されるかどうかを理由とともに説明してください。
各課題の解答と解説
- 課題1の解説: 関数
ReadMoveの内部にある- 3および+ 3を、それぞれ- 5および+ 5に変更します。関数として処理を一元化しているため、呼び出し側(上下・左右)の両方に一括で変更が反映されます。 - 課題2の解説: オレンジ色のロボットの速度変数
speedの初期値を2から-2に変更します。青いロボットを動かすロジックには一切手を触れずに変更できます。 - 課題3の解説: 第1引数
valueに 700、第2引数limitに 592 が渡されます。条件式value > limit(700 > 592)が真となるため、直後のreturn limit;が実行され、値592が返却されます。 - 課題4の解説: 実行されます。画像の読み込みはループの前にあり、座標の加算と境界判定も無効にしていないためです。画面にロボットは映りませんが、
walkerXは変化し続けます。描画する行を元に戻すと、再び往復するロボットが表示されます。
確認を終えたら、変更した移動量と初期値を戻し、無効にした描画の行も元に戻してください。以降のコード例は、この状態を基準に読み進めます。
次の教材で扱う内容
ゲーム制作の題材として、シューティングゲーム制作教材も選べます。基礎実習で書いた入力・更新・描画を使い、プレイヤー、弾、敵を順に作ります。
処理とデータをまとめるクラスや、経過時間を使う移動は、次の教材で必要になったときに学びます。今は、関数へ渡す値と戻り値を追い、総合課題で変更する行を選べることを確認してください。
チェックリスト
- 総合確認課題の4問について、コードの根拠をもとに動作結果を説明できる
- 移動量や初期値を変える行を自分で選び、期待した結果になったか確認できる
- 実験用の変更を戻し、2体の移動と描画を維持している
参考実装
本実習の全工程を完了した main.cpp の完成版コードです。
main.cpp の参考実装
cpp
#include <DxLib.h>
int ReadMove(int minusKey, int plusKey)
{
int move = 0;
if (CheckHitKey(minusKey) != 0)
move = move - 3;
if (CheckHitKey(plusKey) != 0)
move = move + 3;
return move;
}
int KeepInside(int value, int limit)
{
if (value < 0)
return 0;
if (value > limit)
return limit;
return value;
}
void DrawCharacter(int x, int y, int image)
{
DrawGraph(x, y, image, TRUE);
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
ChangeWindowMode(TRUE);
SetGraphMode(640, 480, 32);
SetMainWindowText(L"C++ Basics");
if (DxLib_Init() == -1)
return -1;
SetDrawScreen(DX_SCREEN_BACK);
SetBackgroundColor(245, 248, 252);
int image = LoadGraph(L"Assets/Images/Robot.png");
if (image == -1)
{
MessageBoxW(nullptr, L"Assets/Images/Robot.png を読み込めません。", L"画像の確認", MB_OK);
DxLib_End();
return -1;
}
int x = 160;
int y = 120;
int walker = LoadGraph(L"Assets/Images/Walker.png");
if (walker == -1)
{
MessageBoxW(nullptr, L"Assets/Images/Walker.png を読み込めません。", L"画像の確認", MB_OK);
DeleteGraph(image);
DxLib_End();
return -1;
}
int walkerX = 320;
int walkerY = 300;
int speed = 2;
while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0)
{
x = x + ReadMove(KEY_INPUT_LEFT, KEY_INPUT_RIGHT);
y = y + ReadMove(KEY_INPUT_UP, KEY_INPUT_DOWN);
x = KeepInside(x, 640 - 48);
y = KeepInside(y, 480 - 48);
walkerX = walkerX + speed;
if (walkerX > 640 - 48)
{
walkerX = 640 - 48;
speed = -speed;
}
if (walkerX < 0)
{
walkerX = 0;
speed = -speed;
}
ClearDrawScreen();
DrawCharacter(x, y, image);
DrawCharacter(walkerX, walkerY, walker);
ScreenFlip();
WaitTimer(16);
}
DeleteGraph(walker);
DeleteGraph(image);
DxLib_End();
return 0;
}