見出し画像

すべってゴールを目指せ!スライドパズルアクションゲームを作ろう!クミタテ式プログラミングドリル(p5JavaScript / Processing)

- スライドにすればゲームが変わる

今回作るのはスライドしていくパズルアクションゲームです。
ツルツル滑る氷の上をすべってゴールを目指します。
パネルを1マスずつではなく、スライドさせることで独特のパズル感を出すことができます。
スマホパズルゲーム「2048」や、ドイツゲームの巨匠アレックスランドルフの「ハイパーロボット」などが代表例でしょう。
学習のポイントとしては、「壁に当たるまで止まれない」というアルゴリズムをどう作っていくか、というのがポイントです。

デモアプリはこちらから。https://openprocessing.org/sketch/1602242

- クミタテ式プログラミングドリルとは?

クミタテ式は英語のp5JavaScriptのコードを、日本語で書かれた図解(通称、図解くん)を使って解説し、プラモデルのように図解通りにコードを組み立てていきながら学習する、テキスト教材型のプログラミング教材です。

- 動画を見ながら学習する

テキスト教材の補助として動画を作成しています。クミタテ式が初めての方は動画と一緒に学習すると良いでしょう。
動画とこのテキスト教材は期間限定で無料公開しています。たくさんのゲームジャンルのプログラミング方法をお伝えしているのでチャンネル登録もよろしくお願いします。

- 開発環境

OpenProcessingを使ったp5js、Processingを環境を前提としています。


■[ここからスタート!]画面のサイズを決める

画面サイズを600x400の固定サイズにしましょう。


■背景を青色で塗りつぶし続ける

drawの中で背景を青色で塗りつぶし続けましょう。drawの中で毎回背景を塗りつぶすことでアニメーションが実現できます。


■プレイヤーとなる四角形を表示する

固定の位置座標(50, 50)に四角形を表示します。


■プレイヤーに目をつける

プレイヤーに目をつけて可愛らしくしましょう。


■プレイヤーの位置を変数で管理する

プレイヤーを動かすに当たって、プレイヤーの位置座標を変数にしておく必要があります。


■プレイヤーを矢印キーで動かす

プレイヤーの移動量を管理する変数dxとdyを用意し、プレイヤーの位置座標を移動量分動かすようにします。
どの矢印キーを押されたかで移動量を決定します。

-ヒント-
初心者はキーを押された時に、直接、位置座標を変更しがちです。
キーが押された瞬間しか移動しないため、ぎこちない動きになってしまいます。移動量を管理する変数を間に挟みましょう。


■マップとなる盤上を表示する

96個の四角形を並べて盤上を表現します。
繰り返し処理forの枠組みを使って96回実行し、四角形を表示しましょう。
横に12個並べたら折り返すため、変数iを12で割っています。


■96個のマス情報を配列で管理して壁とゴールを表示する

96個のマス情報を配列でまとめて管理します。
マス情報が1ならゴール、99なら壁として扱います。

//p5.js
let slotList = [
    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
    99,  0,  0,  0,  0, 99,  0,  0,  0,  0,  0, 99,
    99,  0,  0, 99,  0,  0,  0,  0,  0,  0,  1, 99,
    99,  0,  0,  0,  0,  0,  0,  0, 99,  0,  0, 99,
    99,  0, 99,  0,  0,  0,  0,  0,  0,  0,  0, 99,
    99,  0,  0,  0, 99,  0,  0,  0,  0,  0,  0, 99,
    99,  0,  0,  0,  0,  0,  0, 99,  0,  0,  0, 99,
    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
];

// Processing Java
int[] slotList = new int[]{
    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
    99,  0,  0,  0,  0, 99,  0,  0,  0,  0,  0, 99,
    99,  0,  0, 99,  0,  0,  0,  0,  0,  0,  1, 99,
    99,  0,  0,  0,  0,  0,  0,  0, 99,  0,  0, 99,
    99,  0, 99,  0,  0,  0,  0,  0,  0,  0,  0, 99,
    99,  0,  0,  0, 99,  0,  0,  0,  0,  0,  0, 99,
    99,  0,  0,  0,  0,  0,  0, 99,  0,  0,  0, 99,
    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
};

■ここまでの画面を確認しよう

以下のような実行画面になっていますか?

■当たり判定の関数「isHit」を作る

壁との当たり判定をする前に、当たり判定をになう便利なオリジナル命令、「isHit関数」を作ります。
作り方が難しいので、わからない人はコピペしましょう。

-ヒント-
当たり判定のアルゴリズムは以下です。
1. 左側が、相手の右側より左にある。
2. 右側が、相手の左側より右にある。
3. 上側が、相手の下側より上にある。
4. 下側が、相手の上側より下にある。
以上4つの条件を満たしたとき、2つの四角形は当たっているとみなせます。

// p5.js
function isHit(px, py, pw, ph, ex, ey, ew, eh){
  if(px < ex + ew && px + pw > ex){
    if(py < ey + eh && py + ph > ey){
      return 1;
    }
  }
  return 0;
}

// Processing Java
int isHit(float px, float py, float pw, float ph, float ex, float ey, float ew, float eh){
  if(px < ex + ew && px + pw > ex){
    if(py < ey + eh && py + ph > ey){
      return 1;
    }
  }
  return 0;
}

■壁との当たり判定をする

96個の全てのマスと当たり判定を実行し、当たったマスが壁であればプレイヤーの移動量を0にして止めます。
プレイヤーが壁にめり込んでしまう問題が残る点に注意しましょう。次で解決します。


■壁へのめり込みを回避する

壁で止まることができても、壁にめり込んでしまい身動きが取れません。これはアクションゲームであるあるなバグの1つです。
対策方法としては壁の外側の座標を計算してプレイヤー座標を更新してあげる方法がありますが、
非常に面倒なので、壁に当たる直前までのPreviousな座標を保存しておき、壁に当たってしまったのであれば直前の座標に戻してあげる簡易的な対策をしましょう。


ここから先は図解くんはありません。
自分で頭を整理して課題に取り組んでみてください。

■(★☆☆)課題1. 止まるまで方向転換できないようにしましょう

今のままでは移動中に方向転換できてしまいます。
方向キーを押せるのか押せないのか、フラグで管理すると良いでしょう。

■(★★☆)課題2.ゴール判定をしましょう

注意しなくてはいけないのは、ゴールマスに当たったらゴールではないということです。ゴールを通るだけでなく、ゴールで止まらないといけません。
止まったときにゴールとの当たり判定をしてあげれば良いでしょう。

■(★★☆)課題3.オリジナルステージをレベルデザインしよう

マス情報である配列を編集し、オリジナルのステージを作りましょう。
難易度を調整したステージを作ることを「レベルデザイン」と呼びます。
どうしたら難易度の高いステージを作ることができるでしょうか?考えてみましょう。

- ヒント-
ブロックをたくさん置くことでむしろ簡単になってしまいます。
なるべくブロックを少なく配置するには、1つのブロックを2回以上利用できるようなステージにすると良いでしょう。
一石二鳥にすることで情報の積載量を減らしながら、ゲームとしての情報量を増やすことができます。

■オリジナルゲームに仕上げましょう

1マスずつの移動なら簡単すぎて成立しないパズルも、スライドにすることで一気に難易度があがり、パズルとして成立するようになります。
しかしながらこのスライドパズルは弱点があります。それはイライラすることです。
何をしたら正解なのか、自分の今のルートは正しいのか疑心暗鬼になってゲームをプレイすることで、プレイヤーにとってストレスになります。このストレスをうまく緩和したゲームルールに落とし込めれば名作となり得る余地を存分に残しています。


(有料)完成コード

ここから先は

1,874字

¥ 100

この記事が気に入ったらサポートをしてみませんか?