せまる敵をくぐり抜ける!避けアクションゲームを作ろう!クミタテ式プログラミングドリル(p5JavaScript / Processing)
- 三角関数で周期ジャンプを作る
今回作るのはジャンプを繰り返す敵を潜り抜けるシンプルなアクションゲームです。
敵は周期的にジャンプを繰り返し迫ってきます。「周期的」なものを作るとき、三角関数は役立ちます。
デモアプリはこちらから。https://openprocessing.org/sketch/1769210
- クミタテ式プログラミングドリルとは?
クミタテ式は英語のp5JavaScriptのコードを、日本語で書かれた図解(通称、図解くん)を使って解説し、プラモデルのように図解通りにコードを組み立てていきながら学習するテキスト教材型のプログラミング教材です。
- 動画を見ながら学習する
テキスト教材の補助として動画を作成しています。クミタテ式が初めての方は動画と一緒に学習すると良いでしょう。
動画とこのテキスト教材は期間限定で無料公開しています。たくさんのゲームジャンルのプログラミング方法をお伝えしているのでチャンネル登録もよろしくお願いします。
- 開発環境
OpenProcessingを使ったp5js、Processingを環境を前提としています。
■[ここからスタート!]画面のサイズを決める
画面サイズを600x400の固定サイズにしましょう。
■背景を黄色で塗りつぶし続ける
drawの中で背景を黄色で塗りつぶし続けましょう。drawの中で毎回背景を塗りつぶすことでアニメーションが実現できます。
■プレイヤーとなる四角形を表示する
プレイヤーとなる四角形を、固定の位置座標(100, 370)に表示します。
■位置座標を変数で管理する
プレイヤーを動かす前に、プレイヤーの位置座標を変数で管理しましょう。
変数xは横の位置、変数yは縦の位置を意味します。
■プレイヤーを移動させる
プレイヤーの移動量を管理する変数dxを用意し、位置座標xに加算することでプレイヤーを動かします。
■マウスクリックで移動方向を逆にする
マウスクリックで反対の方向にプレイヤーを移動するようにします。
■敵を表示する
プレイヤーと同じ要領で敵(Enemy)を表示しましょう。
■敵を移動させる
プレイヤーと同じ要領で敵にも移動量を持たせて移動させましょう。
■敵をカーブ移動させる
三角関数sinを使うことでカーブを表現することができます。
敵の縦の位置をsinで制御することでカーブの動きを表現できます。
カーブは360度周期で一周させ、度数をe_angleで管理します。
■カーブではなく、半月の動きにする
360度周期ではなく、180度周期にすることでカーブではなく、半月な動きになります。こうすることで周期的な自然なジャンプを表現することができます。
■敵を再出現させる
敵が画面の左端まで到達したら右端からもう一度出現させましょう。
■当たり判定用の関数を作る
プレイヤーと敵との当たり判定を行う前に、当たり判定を計算するオリジナルの命令「isHit関数」を作りましょう。
■isHit関数を使って当たり判定をする
先ほど作ったisHit関数を使ってプレイヤーと敵との当たり判定をします。
的に当たったら、とりあえずプレイヤーを画面の外に追い出します。
■(★☆☆)課題1.レベルデザインする
敵の動きが全く同じだと作業的になり、飽きが来ます。
敵の動き、速度などを変えて難易度を調整しましょう。
■(★☆☆)課題2.スコアを作る
スコアをつけてあげましょう。
■(★☆☆)課題3.称号を作る
例えば「あなたのスコアは10でした!」と言われてもどれほどすごいことなのかはプレイヤーには伝わりません。
そのスコアがどれほどすごいことなのか、遊び手に伝わるようにRankや称号で伝わるようにしてあげましょう。
ランキングなどを実装してあげるとなお良いですが、ランキングを実装するにはサーバーの知識が必要です。
■(★☆☆)課題4. ゲームオーバーを作る
ゲームオーバーの演出を加え、プレイヤーに「悔しい!」という気持ちにさせましょう。
この悔しいと言う気持ちが「もう一度だ!」というプレイヤーの意欲を掻き立てます。
■オリジナルゲームに仕上げよう
今回はシンプルなアクションゲームに仕上げてみました。
タップだけで遊べ、敵との距離感を調整するゲーム性にとどめてみました。逃げて距離を取るべきか、近づいて距離を縮めるべきか、という駆け引きが生まれます。
アクションゲームというと、マリオのようにジャンプをするゲームがすぐに思いつくところですが、あえてジャンプさせないことで不自由さが生まれ、ゲーム性を発見するきっかけになります。
皆さんも、自由度をあえて取り払って「かけひき」を意識したゲームデザインをしてみてください。
■完成コード
以下の完成コードはどうしてもわからない時に参照しましょう。
let x = 100;
let y = 370;
let dx = 3;
let e_x = 550;
let e_y = 370;
let e_dx = -3;
let e_angle = 0;
let score = 0;
let status = 1;
function setup() {
createCanvas(600, 400);
}
function draw() {
background(255, 200, 0);
textAlign(CENTER, CENTER);
textSize(32);
fill(255);
text(score, 300, 200);
textSize(12);
text("Rank " + getRank(score), 300, 240);
x = x + dx;
if(status == 99){
x = -999;
}
fill(255, 255, 255);
rect(x, y, 30, 30);
// 敵
e_x = e_x + e_dx;
e_angle = e_angle + 5;
e_y = 370 + sin(radians(e_angle % 180)) * -50;
fill(255, 100, 0);
rect(e_x, e_y, 30, 30);
if(e_x < 0){
e_x = 600;
e_dx = random(-10, -3);
if(status == 1){
score = score + 1;
}
}
if(isHit(x, y, 30, 30, e_x, e_y, 30, 30) == 1){
// 当たった時の処理
x = -999;
status = 99;
}
if(status == 99){
textSize(32);
fill(255, 100, 0);
text("GAME OVER", 300, 100);
}
}
function mousePressed(){
dx = dx * -1;
}
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;
}
function getRank(score){
let rank = "D";
if(score >= 1){
rank = "C";
}
if(score >= 5){
rank = "B";
}
if(score >= 10){
rank = "A";
}
if(score >= 20){
rank = "神レベル";
}
return rank;
}
この記事が気に入ったらサポートをしてみませんか?