LoginSignup
5
4

More than 5 years have passed since last update.

学校へ急ごう!(2Dスクロールアクションゲーム)

Last updated at Posted at 2018-10-31

はじめに

こんにちは。もっちゃそです。
Weekend Engineer(WE)の10月分の開発として、2Dスクロールアクションゲームを制作しました。
WEの開発プロダクトは、今回で2個目となります。

デモ動画

以下のような流れで撮影しました。

  • 敵をファイアボールで撃破しつつ普通にクリアー
  • 敵に4回(ライフ0の状態で)ぶつかってゲームオーバー
  • ステージから落下してゲームオーバー

Qiita掲載データ.gif

きっかけ

前回の記事と重複しますがご容赦ください・・・)
当コミュニティでは以下のステップに従って経験を積んでいきます。

  1. アイデア出し:渡辺さん、開発:メンバー(@Mocchaso)
  2. アイデア出し・開発:メンバー + 渡辺さんのヘルプ
  3. アイデア出し・開発:メンバー + 基本ヘルプ無し

ステップ2まで進み、いよいよ自分でアイデア出しをする段階に入りました。
来年度からゲーム制作の仕事をさせてもらえることになり、その経験を積もうと考えました。

「ゲーム制作といえばUnityが多いよな」→「前に3~4か月間触っただけだし実装しやすいゲームにするか」ということで、2Dスクロールアクションゲームを選択しました。
それだけだとオリジナリティが無いので、完全に苦し紛れですが、ストーリーを設定しました。

仕組み

ストーリー

主人公が寝坊したので、授業が始まるまでに学校へ急ぐというもの。
画像と音楽の追加まで間に合わなかったため、ゲームやっただけだと全く分かりません・・・。

ゲームのルール

ステージ右端の赤い物体に触れればクリアー、ステージから落下する or 時間切れになる or プレイヤーのライフが無くなるとゲームオーバーとなります。

操作方法は以下の通りです。

  • 移動:左右の矢印キー
  • ジャンプ:Spaceキー
  • ファイアボール(攻撃):fキー

システム図

システム図.jpg

実装

タイトル画面

ゲーム画面だけだとゲームっぽくないと思い、作成しました。
Spaceキーを押すとゲーム画面へ移るようにしました。

TitleManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class TitleManager : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        // Spaceキー押下でゲーム画面に遷移
        if (Input.GetKey(KeyCode.Space)) {
            SceneManager.LoadScene("Main");
        }
    }
}

ゲーム画面

ステージ上の物体(プレイヤー、敵、床など)

Unityの各ビューを使い、よしなに配置しました。
Unityエディタ.jpg

ゲームクリアー

ステージ右端に赤いCubeオブジェクトGoalを配置し、"Goal"タグを付けました。
PlayerController.csでプレイヤーがGoalに触れたかどうかを検出し、GameManager.cs内のクリアーフラグを更新しています。
PlayerController.csをPlayerオブジェクトにアタッチすることで正常に動作しています。

  • void OnTriggerEnter2D(Collider2D obj)
    別のオブジェクトに接触した際、objにそのオブジェクトの情報が格納されます。
    このメソッドで検出できるのは接触のみで、衝突などの物理現象はvoid OnCollisionEnter2D(Collision2D collision)を使うことで検出することができます。
PlayerController.cs
// 略
    void OnTriggerEnter2D(Collider2D obj) {
        if (obj.gameObject.tag == "Goal") { // ぶつかったオブジェクトの判別
            GameManager.isGoaled = true;
        }
    }
}

ゲームオーバー

ステージから落下する or 時間切れになる or プレイヤーのライフが無くなる状態を、以下のように検出しました。

ステージの下部に適当なオブジェクトを配置し、プレイヤーがそのオブジェクトに衝突したら落下していると見なします。

PlayerController.cs
/*
 * ステージから落下する
*/
// 略
    void OnCollisionEnter2D(Collision2D collision) {
        if (collision.gameObject.tag == "Enemy") { // ぶつかったオブジェクトの判別
            GameManager.damaged++;
        } else if (collision.gameObject.tag == "GameOver") {
            // 落下したらゲームオーバー
            GameManager.isGameOver = true;
        }
    }
// 略

時間切れに関しまして、次の前半部分で1秒ごとに残り時間の表示を更新しています。
それが0秒になったら時間切れとしています。
プレイヤーのライフ切れに関しましては、PlayerController.csOnCollisionEnter2D(上記参照)で敵との衝突を検出し、その都度GameManager.cs内のダメージ変数を更新しています。
ライフの最大値 - ダメージ変数の値 >= 0となったらライフ切れとしています。

GameManager.cs
/*
 * 時間切れになる、プレイヤーのライフが無くなる
*/
    void Update () {
        // 残り時間のカウントダウン
        countdown_timer -= Time.deltaTime;
        if (countdown_timer <= 0) {
            tmp_time -= 1; // 残り時間を1秒減らす
            time_text.text = "TIME: " + tmp_time + " s"; // 残り時間の表示を更新
            if (tmp_time == 0) {
                // 残り時間が0になったらゲームオーバー
                isGameOver = true;
            }
            countdown_timer = 1f; // タイマーのリセット
        }

        // 残りライフの表示を更新
        if (lifemax - damaged >= 0) {
            life_text.text = "LIFE: " + (lifemax - damaged);
        } else {
            // 残りライフが0になったらゲームオーバー
            isGameOver = true;
        }

        if (isGameOver || isGoaled) {
            // ゲームオーバー or ゲームクリア時にリザルト画面に遷移
            SceneManager.LoadScene("Result");
        }
    }

ファイアボールを撃つ

発射のキー入力の実装は、タイトル画面のSpaceキー押下部分と概ね同じです。
fキーが押されたら、Prefab(プレハブ)化したファイアボールのゲームオブジェクトをインスタンス化します。

  • Instantiate(gameObject, transform.position, transform.rotation)
    transform.positionの位置、transform.rotationの回転で、プレハブ化しているgameObjectをインスタンス化する
PlayerController.cs
// このメソッドをUpdate()で呼び出している
    void ShootFireBall() {
        // fキー押下でファイアボールを撃つ
        if (Input.GetKeyDown("f")) {
            Instantiate(fireball, transform.position, transform.rotation);
        }
    }

プレイヤーのテクスチャの向きを対応させる(+α)

現在のプレイヤーの向きと1フレーム前のプレイヤーの向きを比較し(横方向のみ)、
向きが変わっていたらx軸方向のスケールを-1倍します。
これにより、プレイヤーが向いている向きに応じてテクスチャの向きも反転します。
※向きが変わったと判定するのは、設置している時のみに限定しています

PlayerController.cs
// このメソッドをUpdate()で呼び出している
    void ReversePlayerSprite() {
        if (isLeft != prev_isLeft) { // 現在のプレイヤーの向きが1フレーム前と異なっていたら
            Vector3 now_scale = transform.localScale;
            now_scale.x *= -1;
            transform.localScale = now_scale;
        }
    }

リザルト画面

タイトル画面と同様の経緯で作成しました。
Spaceキーを押すとタイトル画面へ移るようにしました。
実装コードはタイトル画面と同じなので割愛させていただきます。

参考にしたサイト

調べたサイトが多いため、1つのセクションとしてまとめたいと思います。

ゲームの全体像

ゲーム画面(メインシーン)

タイトル画面、リザルト画面

最後に

感想

簡単なゲームでも1人でつくるのは大変でしたが、ゲーム制作には何が必要かを入念に考えることができました。ゲーム内容の企画、デザイン、サウンドの導入、コーディング、テストプレイなど。
前回よりも時間配分に気を付けることはできましたが、研究を優先していたためビジュアルやサウンドの導入、アイテムの設置までは至りませんでした・・・。
ただ、全ての工程を1人でこなす必要があったので、力はついたような気がします。

※コード全体はこちらをご参照ください
Unity 2Dスクロールアクションゲーム:学校へ急ごう!

Weekend Engineerとは

渡辺大智さん (@ahpjop) 率いる開発コミュニティ。
「どんなアイデアもカタチにする」ことに焦点を置いて活動しています。
ホームページはこちら。このホームページも、WEのメンバーが制作しました。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4