今回の目標
変数を扱えるようになったところで今回はc++では条件分岐、DxLibではキー入力を使えるように頑張りましょう!
変数が使えることが前提の内容になるので前回の内容は習得しておくとスムーズに進むと思います(*'▽')
前回の記事 : C++の勉強しながらDxLibで2Dゲーム作ってみない?(実践編)①
この記事の対象
・Dxlibを使いゲーム開発をしてみたい方
・C++を始めたばかりの初心者の方で作りながら覚えたい方
・何かしらのライブラリやツールを使ってゲーム開発をしてみたい人方
#前回のおさらい
前回は変数と描画関数について触れました。
その中でint型
(整数型)というのが出てきましたがこれは宣言して代入や四則演算ができましたね?
またインクリメントやでクリメントなんて使い方もありました。
具体的に変数はこのように扱います。
※前回も当たり前のように登場していた//
や/**/
ですがこれはコメントアウトといいプログラムにコメントを追加する機能です。(説明不足)
//int型のxという変数を宣言し0で初期化(代入)
int x = 0;
//int型のyという変数を宣言し10で初期化(代入)
int y = 10;
//int型変数xにint型変数yを加算
x += y;
//int型変数xをインクリメント(+1)
x++;
今回はこれらの変数と条件分岐を使い"スクリーンセーバーのあれ"を作りましょう。
おそらく作ってたら気づきます。
条件分岐(if-else文)
C++ではif
という条件分岐が存在します。
このifは基本的にこのような使い方になります。
if(/*条件式*/){
//処理
}
if
の( )
内に書かれた条件式がtrue(真)
の場合{ }
内の処理がされます。
例えば変数x
が100より大きくなった場合のif
文はこのように書きます。
if(x > 100){
//処理
}
このコードではx
が100
より大きくならないと実行されませんが、そうじゃない場合の処理も書く場合はこのようになります。
if(x > 100){
//処理
}
else{
//処理
}
この場合はif
文で条件がtrue
にならなかった場合else
内の処理が実行されます。
また、このif
文での条件式に使われる記号は演算子といいます。
C++ではいくつかの演算子が存在しますが変数より数が少なく説明しやすいので今回は記事中で説明してみます。
以下の表では式が成立した場合true(真)
を、そうでなかった場合はfalse(偽)
を返します
演算子 | 式 | 意味 |
---|---|---|
< | x < y | xがyより小さい場合 |
> | x > y | xがyより大きい場合 |
<= | x <= y | xが以下の場合 |
>= | x >= y | xがy以上の場合 |
== | x == y | xとyが等しい場合 |
!= | x != y | xよyが等しくない場合 |
ここまで使えるようになると"スクリーンセーバーのあれ"が作れるようになります。
まずはこのようなコードを書いてみてください。
else if
がでてきますが 後程説明します。
#include "DxLib.h"
const char *TITLE = "Untitled";
const int WIN_WIDTH = 960;
const int WIN_HEIGHT = 540;
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
ChangeWindowMode(true);
SetWindowSizeChangeEnableFlag(false, false);
SetMainWindowText(TITLE);
SetGraphMode(WIN_WIDTH, WIN_HEIGHT, 32);
SetWindowSizeExtendRate(1.0);
SetBackgroundColor(35, 35, 35);
SetDrawScreen(DX_SCREEN_BACK);
if (DxLib_Init() == -1) { return -1; }
int speed_x = 5;
int speed_y = 5;
int x = 100;
int y = 100;
int size = 50;
while (true) {
ClearDrawScreen();
if (x <= 0) {
speed_x = -speed_x;
}
else if (x >= WIN_WIDTH - size) {
speed_x = -speed_x;
}
if (y <= 0) {
speed_y = -speed_y;
}
else if (y >= WIN_HEIGHT - size) {
speed_y = -speed_y;
}
x += speed_x;
y += speed_y;
DrawBox(x, y, x + size, y + size, GetColor(255, 255, 255), true);
ScreenFlip();
WaitTimer(20);
if (ProcessMessage() == -1) { break; }
if (CheckHitKey(KEY_INPUT_ESCAPE) == 1) { break; }
}
DxLib_End();
return 0;
}
今回はx方向に5、y方向に5を加算し、壁に当たったら跳ね返るという処理を書きました。
x,yどちらも処理がたいして変わらないためxだけ説明していきます。
x方向の条件式ではこのように書かれています。
if (x <= 0) {
speed_x = -speed_x;
}
else if (x >= WIN_WIDTH - size) {
speed_x = -speed_x;
}
この部分ではspeed_x
という変数をx
が壁に当たったら反転する処理をしています。
最初のifではx
が0
以下になった場合(左側の壁に当たった場合)変数speed_x
をの値を反転します。
こうすることで壁に当たった場合壁とは反対側に四角形を移動するようにしています。
次のelse if
というのは上のif
がfalse(偽)であり、なおかつelse if()
の()
内の条件がtrue(真)の場合に実行されます。
else
にただif
がくっついただけです。
そしてこのelse if
では右側の壁に当たった場合の処理をしています。
WIN_WIDTH
が画面サイズなので画面サイズから四角形の一辺のサイズを引くことで左上をもとに描画しているため右の壁に四角形の右側の辺が当たった場合変数speed_x
を反転し反対側に四角形を移動するようにしています。
そしてこのコードを実行するとこのような動きになります。
これ、見たことありませんか?
"スクリーンセーバーのあれ"です。
条件分岐を使えるとこんなことができるようになります。
それでは次のキー入力でさらに応用していきましょう。
キー入力
おそらく多くのゲームではキーボードやマウス、それにコントローラーなどキー入力をしてプレイヤーを操作しますよね。
ゲームにおいてキー入力は必須といっても過言ではないかと思います(一部そうではないゲームはありますが...)
ですのでこのキー入力と条件分岐を応用してプレイヤーの操作をしていきましょう。
・CheckHitKey関数
CheckHitKey
はDxLibで用意されている関数でこれを使うことによりキー入力を知ることができます。
そして便利なことにDxLibではキーがマクロ登録されているのでスペースキーが押されているか知りたい場合はCheckHitKey
にKEY_INPUT_SPACE
というマクロを引数で渡してあげるだけでわかります。
先ほどのコードを一部変えてこのようなコードを書いてみてください。
#include "DxLib.h"
const char *TITLE = "Untitled";
const int WIN_WIDTH = 960;
const int WIN_HEIGHT = 540;
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
ChangeWindowMode(true);
SetWindowSizeChangeEnableFlag(false, false);
SetMainWindowText(TITLE);
SetGraphMode(WIN_WIDTH, WIN_HEIGHT, 32);
SetWindowSizeExtendRate(1.0);
SetBackgroundColor(35, 35, 35);
SetDrawScreen(DX_SCREEN_BACK);
if (DxLib_Init() == -1) { return -1; }
int speed_x = 5;
int speed_y = 5;
int x = 100;
int y = 100;
int size = 50;
while (true) {
ClearDrawScreen();
if (x <= 0) {
speed_x = -speed_x;
}
else if (x >= WIN_WIDTH - size) {
speed_x = -speed_x;
}
if (y <= 0) {
speed_y = -speed_y;
}
else if (y >= WIN_HEIGHT - size) {
speed_y = -speed_y;
}
if (CheckHitKey(KEY_INPUT_SPACE)) {
x += speed_x;
y += speed_y;
}
DrawBox(x, y, x + size, y + size, GetColor(255, 255, 255), true);
ScreenFlip();
WaitTimer(20);
if (ProcessMessage() == -1) { break; }
if (CheckHitKey(KEY_INPUT_ESCAPE) == 1) { break; }
}
DxLib_End();
return 0;
}
このコードでは以下の部分でスペースが押されると座標xやyに変数speed_x
や変数speed_y
を加算し、動かす処理をしています。
if (CheckHitKey(KEY_INPUT_SPACE)) {
x += speed_x;
y += speed_y;
}
ですがいちいちCheckHitKey
を呼び出しのも"なんだかなぁ..."と思うのです。
ですのですべてのキー情報を格納する変数を作りすべてのキー情報を教えてくれる関数で格納していきましょう。
・GetHitKeyStateAll関数
GetHitKeyStateAll
関数を使えばすべてのキー情報が分かります。
この関数に引数をとしてchar型
の配列を渡すことでキー情報を格納できるのですが、この仕組みを説明するとポインタ
やアドレス
、配列の仕組みやアドレスと配列の関係性を説明しなけれならないのでもう少し先に進んだら説明します。
まずはこうすることによって格納できるという事だけわかっていただければ十分です。
では以下のコードを書いてみてください。
#include "DxLib.h"
extern const char *TITLE = "Untitled";
extern const int WIN_WIDTH = 960;
extern const int WIN_HEIGHT = 540;
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
ChangeWindowMode(true);
SetWindowSizeChangeEnableFlag(false, false);
SetMainWindowText(TITLE);
SetGraphMode(WIN_WIDTH, WIN_HEIGHT, 32);
SetWindowSizeExtendRate(1.0);
SetBackgroundColor(35, 35, 35);
SetDrawScreen(DX_SCREEN_BACK);
if (DxLib_Init() == -1) { return -1; }
int x = 100;
int y = 100;
const int speed = 5;
const int size = 50;
char keys[256];
while (true) {
ClearDrawScreen();
//すべてのキー情報を格納
GetHitKeyStateAll(keys);
//キー操作
if (keys[KEY_INPUT_A]) {
x -= speed;
}
else if (keys[KEY_INPUT_D]) {
x += speed;
}
if (keys[KEY_INPUT_W]) {
y -= speed;
}
else if (keys[KEY_INPUT_S]) {
y += speed;
}
//四角形描画
DrawBox(x, y, x + size, y + size, GetColor(255, 255, 255), true);
ScreenFlip();
WaitTimer(20);
if (ProcessMessage() == -1) { break; }
if (CheckHitKey(KEY_INPUT_ESCAPE) == 1) { break; }
}
DxLib_End();
return 0;
}
んふwそれっぽくなってきましたね!(キモい)
早速説明です。
keys[256]
というchar型
の変数がありますが今はおまじないです。
簡単に説明すると256個のchar型の変数がこれです。
そしてGetHitKeyStateAll(keys)
でkeys
にキーの情報を格納しています。
こうすることによって後のコードがすっきりしますしいちいちCheckHitKey
関数を呼ばずに済むようになります。
そしてこの変数たちを使いキー入力でキャラクターを操作している部分がこちらです。
if (keys[KEY_INPUT_A]) {
x -= speed;
}
else if (keys[KEY_INPUT_D]) {
x += speed;
}
if (keys[KEY_INPUT_W]) {
y -= speed;
}
else if (keys[KEY_INPUT_S]) {
y += speed;
}
一目瞭然のコードなので説明はいりませんねw
まぁ簡単に説明すると
次回
とうとう条件分岐とキー入力ができるようになりましたね!
ここまで来たら次回は一度変数に戻り配列をやるか当たり判定をやるか悩むところですが次回までに考えておきますw
当たり判定の場合は数学的要素が加わるので√(平方根)
アレルギーの方は覚悟しておいてくださいw
まぁ自分で計算するわけではないので身構えなくても大丈夫ですがw...
次回まで少々お待ちください!
あとがき
正直プログラミングって変数と条件分岐を習得すると一定以上のものが作れるようになるので応用していろいろ作ってみたり動作を確認してみるといいかもしれません(*'▽')
これから難しくなってきますがね...フ フ フ フ フ フ
(フ フ フ フ フ フがわかるプログラマーはこの記事読んでないでデバッグやら頑張ってください)
###作者について
詳しくはわんころメソッド();HPにどうぞ(*'▽')
・わんころメソッド();HP
・Twitter(まゆC#)
・GitHub(まゆC#)
コミュニティ
Discordで雑談から質問まで様々なチャンネルがあるまゆC#のコミュニティサーバーがあります!
わからないことがあればこちらでもお答えするのでぜひ!