横スクロールジャンピングゲームの作成 - C言語とelで様々なゲームを作ろう
目次
- C言語とelで様々なゲームを作ろう
- Visual C++ .NET での設定
- テンプレートファイルの解説
- シューティングゲームの作成(チュートリアル)
- パックマン的ゲームの作成(チュートリアル)
- ブロック崩しの作成
- 15パズルの作成
- 横スクロールジャンピングゲームの作成
- オセロの作成
- 神経衰弱の作成
- 7ならべの作成
- テトリスの作成
- ぷよぷよの作成
ソース・プロジェクトファイル
ソースファイルプロジェクトファイル(Visual C++ 6.0)
ゲームの説明
シンプルな横スクロールのジャンプアクションゲームです。方向キーの左右でキャラクタを動かしてスペースキーでジャンプし、穴をよけてください。だんだん穴が大きくなって難しくなります。
プログラムの解説
定数・グローバル変数
#define ACCEL_X 0.6
x 方向の加速度です。この数値を上げるとより機敏な動きになります。
#define MAX_SPEED 8
最高速度です。
#define JUMP_POWER 20
ジャンプ力です。この数値を下げると低いジャンプとなり、この数値を上げると高いジャンプとなります。
DDOBJ jiki;
自機のスプライトオブジェクトです。ウインドウ生成関数
jiki = elDraw::LoadObject("chr.bmp");
自機画像をスプライトに読み込んでいます。メイン画面 変数
static int jx = 160, jy = 280;
自機の座標です。
static double vx = 0.0, vy;
自機の速度です。double 型にすることによって、微妙な速度の増加や減少を表わすことができます。
static bool jumpFlag = false;
自機がジャンプ中なら true になるフラグ変数です。
static int kl = FREE_KEY;
static int kr = FREE_KEY;
static int ks = FREE_KEY;
カーソルキー左・右・スペースキーの状態が入る変数です。
static int mw[20] = {1000};
地面の幅を表わす配列です。mw[0] が画面の最も左の地面または穴の幅、mw[1] が画面の左から2番目の地面または穴の幅…という風に格納されています。mw[0] つまり最初の地面の幅を 1000 ピクセルに初期化しています。
static int mnum = 1;
画面上に出ている地面と穴の合計の数が入ります。
static int mkt = 1;
画面の左端に地面があれば 1、穴があれば 0 が入ります。
static bool overFlag = false;
自機が穴に落ちた、つまりゲームオーバーなら true になる変数です。
static int score = 0;
得点です。一歩あるくたびに1点ずつ入ります。メイン画面 自機移動
if (kl != FREE_KEY) {
vx -= ACCEL_X;
if (vx < -MAX_SPEED) vx = -MAX_SPEED;
左キーが押されたとき、速度から加速度を引き、最高速度を超えないようにしています。
} else if (kr != FREE_KEY) {
vx += ACCEL_X;
if (vx > MAX_SPEED) vx = MAX_SPEED;
右キーが押されたとき、速度に加速を加え、最高速度を超えないようにしています。
} else {
if (vx < 0) vx++;
else if (vx > 0) vx--;
左右どちらのキーも押されていないとき、だんだん速度が遅くなるようにしています。
jx += int(vx);
自機の座標に速度を加えて自機を移動します。
if (jx < 0) {jx = 0; vx = 0;}
else if (jx > 576) {jx = 576; vx = 0;}
自機が画面端からはみださないようにしています。
if (!jumpFlag) {
if (ks != FREE_KEY) {
vy = -JUMP_POWER;
jumpFlag = true;
}
ジャンプ中でなければスペースキーが押されたかチェックし、押されていたら縦方向の速度を設定し、ジャンプフラグをセットしています。
} else {
vy++;
jy += int(vy);
if (jy > 280) {
jy = 280;
jumpFlag = false;
}
}
ジャンプ中ならば下向きの速度を加え(重力加速度)、自機の座標に速度を加えて自機を移動します。地面に着地したらジャンプフラグをクリアします。メイン画面 マップ描画
int mk = mkt;
現在描画中のマップの種類が入ります。0 が穴、1 が地面です。
int mx = 0;
現在描画中の穴または地面の左端の x 座標が入ります。
for (i = 0; i < mnum; i++) {
mnum つまり現在画面に出ているマップの分だけ以下の処理を繰り返します。
if (mk) elDraw::Box(mx, 344, mw[i] + mx, 360, RGB(255, 255, 200), RGB(100, 255, 150), 1);
マップが地面なら描画処理を行ないます。elDraw::Box は塗り潰し四角形を描画するメソッドです。
else if (!jumpFlag && mx <= jx && mw[i] + mx >= jx + 64) overFlag = true;
マップが穴なら自機が落下したかのチェックを行ないます。ジャンプ中でなく、かつ自機の座標が完全に穴の座標の内側に入っていれば落下したと見なし、ゲームオーバーフラグを立てています。
mk = 1 - mk;
現在のマップの種類が穴ならば次のマップの種類を地面、現在のマップの種類が地面ならば次のマップの種類を穴に設定しています。
mx += mw[i];
描画 x 座標に現在の地面または穴の幅を加え、次の描画 x 座標を算出しています。
if (mx < 640) {
描画ループが終了したときに描画 x 座標が画面右端に到達していなかったとき、つまりマップが足りなくなったときに、新しいマップを継ぎ足している部分です。
int ml = score / 50;
if (ml > 200) ml = 200;
スコアが増えていくごとに穴を大きくしたいので、その変数を設定しています。
if (mk) mw[mnum] = 315 - ml - rand() % 100;
次のマップの種類が地面ならば、スコアが増えていくごとに地面が小さくなるように値を設定しています。
else mw[mnum] = 64 + ml + rand() % 100;
次のマップの種類が穴ならば、スコアが増えていくごとに穴が大きくなるように値を設定しています。
mnum++;
マップの数をひとつ増やします。
mw[0] = mw[0] - 4;
マップをスクロールしている部分です。左端の地面または穴を -4 だけ小さくしてスクロールしているように見せかけています。
if (mw[0] <= 0) {
mw[1] += mw[0];
for (i = 0; i < mnum - 1; i++) mw[i] = mw[i + 1];
mnum--;
mkt = 1 - mkt;
}
スクロールした結果、左端の地面が無くなった場合の処理です。配列の要素を全てシフトし、マップの数をひとつ減らし、マップの先頭の穴と地面の種類を入れ替えています。
int y = 0;
if (overFlag) y = 32;
elDraw::Layer(jx, jy + y, jiki, 0, 0, 64, 64);
自機を描画しています。ゲームオーバーのときは穴に落ちた感じを出すために、少し下にずらして描画しています。