そう、ずいぶん前に「ブロック崩しを作る」なんて言ってましたね。
高校生の春休みは長い。 そう。 やはり作らねばならんのです。(何で
とりあえず。C++っぽい書き方に慣れるためにもとりあえずという形で作ってみることにしました。
1.どんなゲームにするか?
さて、とりあえずブロック崩しといっても様々な形があるでしょうし、アイテムとか、他の要素も追加されていくことでしょう。
こないだ書いた日記にて、様々な方から意見を聞きました。 どれも面白そうなんですけど...ちょっと処女作としては敷居が高いですね。(言い訳
というわけで、普通のブロック崩しを作ることにしました。ゲーム性は求めない。とりあえずスタンダードなブロック崩し。
2.で、次はなにすればいいの
ゲームなんて作ったことないので、ゲームプログラムがどういう風に回ってるとか、そういう基本的なモノしかわからず。設計もわからん。なんもわからん状態です。
でもまぁとりあえず最初だしどうでもいいや()というわけでございまして。せっせとプログラムを書いてたわけですよ。
するとですね。ほぼすべての情報をmain関数が持ち、main関数内で計算して、main関数内で描画して。 関数なんて分けないでとりあえず書いてたらまぁそりゃ醜くなったわけです。
スタンダードなブロック崩しとは言っていますが、機能追加、つまりスコア機能、アイテムの導入、等の事は今後当然の用に行われていくことでしょう。
3.オブジェクト指向
つか、ブロック崩しにオブジェクト指向って使うべきなの? わからんけどとりあえずC++を学ぶことが目的なんだからコレを取り入れないわけにはいかんだろ。
というわけで機能追加とかにもmain関数に直接書くよりははるかにマシ...のはずだと思いオブジェクト指向なるものを取り入れたいのです。つまり
こういうカッコイイ書き方をしてみたい! ってわけで以前作ったmain関数に全部ぶっこんでるやつをとりあえず画面上にあるであろうオブジェクトごとに分ける作業を行いました。
まず。
1.ボール
2.ブロック
3.バー
この三つに分かれるのではと思い、とりあえずその三つのクラスを作成、さくっと必要そうな情報を書き入れつつ、コンストラクタの用意。
初期化、更新、描画をそれぞれ行うメンバ関数を用意、適当にゲッターも作っとく。
それらのクラスをmain関数に持たせて、いつも通りに初期化、更新、描画、......
3.あたり判定ってどうすんのさ
ここにおけるあたり判定はゲーム設計上のあたり判定であり、実際のあたり判定を行う処理は指していません。
ってか、あたり判定を行うところは各クラス内の更新に当たる関数なのでしょうが、もちろんとある二つのオブジェクト間のあたり判定を行う場合、
双方の情報を知る必要がありますし、変更する必要があります。 ....どうすんのこれ。←今ココ
4.結論
つまり現時点ではゲームの設計自体で行き詰っているというところです。今のところの改善案としては、このボール、ブロック、バーというオブジェクトを、「ゲームフィールド」とかいうオブジェクトで覆ってしまって
ゲームフィールドが情報を握ってしまえば大丈夫かもしれない、とかいう考えですが、んなことしてたらタイトル画面作ろうとしたとき、ゲームフィールドというオブジェクトは一つのシーンという形でまた外側
を覆わなければいけなくなりそうそしてそのオブジェクトはまた「ゲーム本体」というオブジェクトで...つまりどんどん遠のいてる気がするんですよねぇ、main関数から。果たしてそれはいいことなのか
もう一つの改善案として、単なる関数としてあたり判定を行うというものです。値を投げれば当たっているか否かを返してくれる、とか、それでもってもやはり個々のオブジェクトの値を変更するコードはどこに書けばいいのか...
わからんことばっかりです。
とりあえず現時点でのコードをぺったり。 週一程度の更新を目指して...
► スポイラーを表示
CODE:
#include "../DxLib/DxLib.h"
#include "KeyBoard.h"
/******************全体で使う値*******************/
const int WINDOW_X = 640;
const int WINDOW_Y = 480;
/**********************クラス宣言***********************/
class Bar_t
{
private:
int x; //座標
int y;
int rect_x; //サイズ
int rect_y;
int color;
bool flag; //何かに使うかもしれない
public:
Bar_t();
~Bar_t(){}
int get_x(){ return x; }
int get_y(){ return y; }
int get_rect_x(){ return rect_x; }
int get_rect_y(){ return rect_y; }
void Init();
void Update();
void Draw();
};
class Ball_t
{
private:
//初期位置と現在位置用に二つ
float x[2]; //座標
float y[2];
float v_x[2]; //軸の速度
float v_y[2];
int r[2];
int color[2];
bool flag[2]; //何かに使うかもしれない
public:
Ball_t();
~Ball_t();
float get_x(){ return x[0]; }
float get_y(){ return y[0]; }
void Init(float arg_x, float arg_y, float arg_v_x, float arg_v_y, int arg_r);
void Reset();
void Update();
void Draw();
};
class Blocks_t
{
private:
typedef struct Block
{
int x;
int y;
int rect_x;
int rect_y;
int color;
bool flag;
}Block;
const int block_x = 16;
const int block_y = 16;
const int blocksize_x = (int)580 / block_x;
const int blocksize_y = (int)256 / block_y;
const int space = (int)64 / block_x;
Block block[16][16];
public:
Blocks_t();
~Blocks_t();
void Init();
void Reset();
void Update();
void Draw();
};
/*************クラスの中身*************/
Bar_t::Bar_t()
{
x = WINDOW_X / 2;
y = WINDOW_Y - 40;
rect_x = 96;
rect_y = 16;
color = GetColor(64, 255, 255);
}
void Bar_t::Init()
{
}
void Bar_t::Update()
{
GetMousePoint(&x, NULL);
}
void Bar_t::Draw()
{
DrawBox(x, y, x + rect_x, y + rect_y, color, true);
}
Ball_t::Ball_t()
{
x[0] = 0.0;
y[0] = 0.0;
v_x[0] = 0.0;
v_y[0] = 0.0;
r[0] = 0;
color[0] = GetColor(255, 64, 32);
}
void Ball_t::Init(float arg_x,float arg_y,float arg_v_x,float arg_v_y,int arg_r)
{
x[0] = arg_x;
y[0] = arg_y;
v_x[0] = arg_v_x;
v_y[0] = arg_v_y;
r[0] = arg_r;
//初期位置に代入
x[1] = x[0];
y[1] = y[0];
v_x[1] = v_x[0];
v_y[1] = v_y[0];
r[1] = r[0];
}
void Ball_t::Reset()
{
//現在位置を初期位置に
x[0] = x[1];
y[0] = y[1];
v_x[0] = v_x[1];
v_y[0] = v_y[1];
r[0] = r[1];
}
void Ball_t::Update()
{
x[0] += v_x[0];
y[0] += v_y[0];
//ブロックやバー、壁とのあたり判定?
}
void Ball_t::Draw()
{
DrawCircle(x[0], y[0], r[0], color[0]);
}
Blocks_t::Blocks_t()
{
for (int i = 0; i Init(320, 400, 4.0, 4.0, 4);
while (SystemUpdate())
{
bar->Update();
ball->Update();
blocks->Update();
bar->Draw();
ball->Draw();
blocks->Draw();
}
DxLib_End();
return 0;
}