ゲーム実装で身に付くプログラミング 8

色ブロックをクリックしたら背景色を反映させる

色ブロックをクリックしたら背景色を反映させる

色ブロックをクリックしたら消して、その色を背景色に混ぜます(図5)。背景色はクリックした色ブロックの赤緑青の1色が加算されてより明るくなります。色ブロックをクリックで消して、1個もなくなったらゲームオーバーです。

図5:背景色を反映

・サンプルコード「ColorBlock.h」ファイル

#pragma once

#include "raylib.h"
#include <vector>

class ColorBlock
{
public:
	float x, y, width, height, vx, vy;
	int color;

	ColorBlock(int c,int w,int h);
	int Draw(std::vector<Texture> img);
	bool IsClicked();
};

【サンプルコードの解説】
「ColorBlock」クラスに「IsClicked」メソッドを追加します。

・サンプルコード「ColorBlock.cpp」ファイル

#include "ColorBlock.h"
#include <vector>
#include <cstdlib>

ColorBlock::ColorBlock(int c,int w,int h) {
(中略)
}

int ColorBlock::Draw(std::vector<Texture> img) {
(中略)
}

bool ColorBlock::IsClicked() {
	Vector2 mouse = GetMousePosition();
	Rectangle rect = { x, y, width, height };
	if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && CheckCollisionPointRec(mouse, rect)) return true;
	return false;
}

【サンプルコードの解説】
IsClickedメソッドでマウス座標を「mouse」変数に、色ブロックの正方形のサイズを「rect」変数にそれぞれ取得します。マウスの左ボタンがクリックされた時にmouseがrectの範囲に入っていればクリック成功で、戻り値としてtrueを返します。それ以外はfalseを返します。

・サンプルコード「main.cpp」ファイル

#include "ColorBlock.h"
#include "resource_dir.h"
#include <cstdlib>

enum GameState { TITLE, MAIN_LOOP, GAME_OVER, STAGE_CLEAR };
GameState game_state = TITLE;
std::vector<Texture> img;
std::vector<Sound> snd;
std::vector<ColorBlock> colors;
int stage = 2;
float rgb[3];
Color bg = { 255, 255, 255, 255 };

void init() {
	colors.clear();
	for (int i = 0; i < stage * 3; i++) colors.push_back(ColorBlock(i % 3, img[0].width, img[0].height));
	rgb[0] = 0;
	rgb[1] = 0;
	rgb[2] = 0;
	while (rgb[0] == rgb[1]) {
		rgb[0] = rand() % stage;
		rgb[1] = rand() % stage;
		rgb[2] = rand() % stage;
	}
}

void title() {
(中略)
}

void main_loop() {
	int flg = 0;
	for (auto it = colors.begin(); it != colors.end(); it++) flg += it->Draw(img);
	for (auto it = colors.begin(); it != colors.end(); it++) {
		if (it->IsClicked()) {
			PlaySound(snd[0]);
			rgb[it->color]++;
			colors.erase(it);
			break;
		}
	}
	if (flg == 0) {
		game_state = GAME_OVER;
		PlaySound(snd[2]);
	}
}

void bg_color() {
	int max = (rgb[0] < rgb[1]) ? (rgb[1] < rgb[2] ? 2 : 1) : (rgb[0] < rgb[2] ? 2 : 0);
	float ratio = 255.0 / rgb[max];
	unsigned char r = rgb[0] * ratio;
	unsigned char g = rgb[1] * ratio;
	unsigned char b = rgb[2] * ratio;
	bg = { r, g, b, 255 };
	if (r == g && g == b) {
		game_state = STAGE_CLEAR;
		PlaySound(snd[3]);
	}
}

void game_over() {
(中略)
}

int main() {
(中略)
	while (!WindowShouldClose()) {
		BeginDrawing();
		ClearBackground(bg);
		switch (game_state) {
			case TITLE: title(); break;
			case MAIN_LOOP:
				main_loop();
				bg_color();
				break;
			case GAME_OVER: game_over(); break;
		}
		EndDrawing();
	}
(中略)
}

【サンプルコードの解説】
「rgb」配列を宣言します。
「init」関数でrgbの3要素にランダムな値を代入します。
「main_loop」関数で色ブロックがクリックされたら"Mix.ogg"サウンドを再生し、rgb配列のクリックした色をインクリメントして色ブロックを消します。
「bg_color」関数で、例えば(赤,緑,青)=(3,2,1)なら(r,g,b)=(255*3/3, 255*2/3, 255*1/3)というように計算します。背景色が真っ白になったらgame_stateをステージクリアにし、"StageClear.ogg"サウンドを再生します。
「main」関数のメインループ内のゲームループ中で、bg_color関数を呼び出します。

ステージクリア画面を表示する

最後にステージクリア画面を実装して今回は終わりです(図6)。他のプログラミング言語の時はコード量が増えてしまい、ステージクリア画像を表示しなかったり、ステージクリアサウンドを再生しなかったり、クリックで画面遷移しなかったり色々省略しましたが、今回は第1回のようにこれらも実装します。

図6:ステージクリア画面を表示

・サンプルコード「main.cpp」ファイル

(前略)

void init() {
(中略)
}

void title() {
(中略)
}

void main_loop() {
(中略)
}

void bg_color() {
(中略)
}

void game_over() {
(中略)
}

void stage_clear() {
	Vector2 mouse = GetMousePosition();
	if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
		game_state = MAIN_LOOP;
		stage++;
		init();
		PlaySound(snd[1]);
	}
	DrawTexture(img[5], (1800 - img[5].width) / 2, (900 - img[5].height) / 2, WHITE);
}

int main() {
(中略)
	while (!WindowShouldClose()) {
		BeginDrawing();
		ClearBackground(bg);
		switch (game_state) {
			case TITLE: title(); break;
			case MAIN_LOOP:
				main_loop();
				bg_color();
				break;
			case GAME_OVER: game_over(); break;
			case STAGE_CLEAR: stage_clear(); break;
		}
		EndDrawing();
	}
(中略)
}

【サンプルコードの解説】
「stage_clear」関数で"StageClear.png"画像を描画します。マウスの左ボタンがクリックされたらgame_state変数をゲームループにセットし、ステージをインクリメントし、ステージ開始処理をして"GameStart.ogg"サウンドを再生します。
「main」関数で、メインループ中のステージクリアの際にstage_clear関数を呼び出します。

【コラム】マーク・ザッカーバーグ

Metaのマーク・ザッカーバーグは12才の時、歯科医院をしていた親のために受付から診療書をネット経由でメッセージするシステムを作ってあげたそうです。「30年前の病院ではまず見かけないシステムだ」と、看護師だった母が言っていました。

おわりに

今回はプログラミング言語「C/C++」の2Dグラフィックスライブラリ「RayLib」でコンソールゲーム「Color」を開発しました。最も難しいプログラミング言語の1つである「C/C++」でも、ライブラリを使えばここまでシンプルに実装できるんですね。

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored