ヤマカサのプログラミング勉強日記

プログラミングに関する日記とどうでもよい雑記からなるブログです。

Unity4.6/5.0でつくる 2Dゲーム制作入門 [改訂第二版] その2

Chapter1 ミニゲームの作成

著者の自作クラスを理解するのに大変です。

たこ焼きが食べたくなるゲームですね。

進めたSection

  • 1.9 クリックすると消滅するようにする

  • 1.10 たこ焼きを複数配置する

  • 1.11 パーティクルの追加

  • 1.12 パーティクルの動きを作る

  • 1.13 Particleオブジェクトをプレハブ 化する

  • 1.14 ゲームクリア判定を作る

本ではstaticメソッドになっていますが、自分書いたものは非staticメソッドになっているものがあります。あとで直そう。

コード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour {

    
    public GameObject enemy;    // Enemyのゲームオブジェクト
    public static int Count = 0;

    private Rigidbody2D rbody;
    private SpriteRenderer eRenderer;
    private float wid;
    private float hei;
    // Use this for initialization
    void Start () {
        // 生存数を増やす
        Count++;
        // ランダムな方向に移動する
        // 方向をランダムに決める 0~359度
        float dir = Random.Range(0, 359);
        // 速さは2
        float spd = 2;
        // x軸, y軸の速さを計算し、Rigidbodyに設定する。
        Vector2 v = new Vector2(Util.CosEx(dir)*spd, Util.SinEx(dir)*spd);
        rbody = GetComponent<Rigidbody2D>();
        rbody.velocity = v;
        eRenderer = enemy.GetComponent<SpriteRenderer>();
        wid = eRenderer.bounds.size.x / 2;
        hei = eRenderer.bounds.size.y / 2;


        
    }
    
    // Update is called once per frame
    void Update () {
        // 画面の端で跳ね返るようにする。

        // ビューポート座標からワールド座標へ変換する。
        // ビューポート座標では、左下が(0, 0)、右上が(1, 1)となる。
        // カメラの左下座標を取得する。
        Vector2 min = Camera.main.ViewportToWorldPoint(Vector2.zero);
        // 自身の大きさを考慮する
        min.x += wid;
        min.y += hei;
        // カメラの右上座標を取得
        Vector2 max = Camera.main.ViewportToWorldPoint(Vector2.one);
        // 自身の大きさを考慮
        max.x -= wid;
        max.y -= hei;

        // 敵の速度を一定(=2)に保つ。他のたこ焼きとぶつかると速度が変わるため。弾性衝突?
        float v_temp = Mathf.Sqrt(Mathf.Pow(rbody.velocity.x, 2) + Mathf.Pow(rbody.velocity.y, 2));
        rbody.velocity = new Vector2(rbody.velocity.x * 2 / v_temp, rbody.velocity.y * 2/ v_temp);

        // オブジェクトの座標を取得
        float X = enemy.transform.position.x;
        float Y = enemy.transform.position.y;
        if (X < min.x || X > max.x) {
            // 画面外に出たので、X移動量を反転する。
            rbody.velocity = new Vector2(rbody.velocity.x * -1, rbody.velocity.y);

            // 画面内に収まるように制限をかける.
            X = Mathf.Clamp(X, min.x, max.x);
            Y = Mathf.Clamp(Y, min.y, max.y);
            Vector2 pos = transform.position;
            pos.x = X;
            pos.y = Y;

            enemy.GetComponent<Transform>().position = pos;
        }
        if(Y < min.y || Y > max.y) {
            // 画面外に出たので、Y移動量を反転する。
            rbody.velocity = new Vector2(rbody.velocity.x, rbody.velocity.y * -1);

            // 画面内に収まるように制限をかける.
            X = Mathf.Clamp(X, min.x, max.x);
            Y = Mathf.Clamp(Y, min.y, max.y);

            Vector2 pos = transform.position;
            pos.x = X;
            pos.y = Y;

            enemy.GetComponent<Transform>().position = pos;
        }

    }

    public void OnMouseDown() {
        // 生存数を減らす
        Count--;
        Particle p = new Particle();
        for(int i = 0; i < 32; i++) {
            p.Add(enemy.transform.position.x, enemy.transform.position.y);
        }
        Destroy(enemy);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Particle : MonoBehaviour {

    //public GameObject gObj;
    public GameObject pPrefab;

    // 開始。コルーチンで処理を行う
    IEnumerator Start() {
        // 移動する方向と速さをランダムに決める
        float dir = Random.Range(0, 359);
        float spd = Random.Range(10.0f, 20.0f);
        Vector2 v = new Vector2(Util.CosEx(dir) * spd, Util.SinEx(dir) * spd);
        pPrefab.GetComponent<Rigidbody2D>().velocity = v;

        // 見なくなるまで小さくする
        while(pPrefab.GetComponent<Transform>().localScale.x > 0.01f) {
            // 0.01秒毎にゲームループに制御を返す
            yield return new WaitForSeconds(0.01f);
            // だんだん小さくする
            pPrefab.GetComponent<Transform>().localScale *= 0.9f;
            // だんだん減速する
            pPrefab.GetComponent<Rigidbody2D>().velocity *= 0.9f;
        }
        Destroy(pPrefab);
    }

    public  Particle Add(float x, float y) {
        // prefabからインスタンスを生成
        pPrefab = Resources.Load("Prefabs/" + "Particle") as GameObject;
        Vector3 p = new Vector3(x, y, 0);
        GameObject g = Instantiate(pPrefab, p, Quaternion.identity) as GameObject;

        Vector2 v0 = new Vector2(0, 0);
        g.GetComponent<Rigidbody2D>().velocity = v0;
        
        return g.GetComponent<Particle>();
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameMgr : MonoBehaviour {

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        
    }

    private void OnGUI() {
        if(Enemy.Count == 0) {
            // 敵が全滅した
            // フォントサイズ設定
            GUIStyle gUIStyle = new GUIStyle();
            gUIStyle.fontSize = 32;
            gUIStyle.alignment = TextAnchor.MiddleCenter;
            // フォントの位置
            float w = 127;
            float h = 32;
            float px = Screen.width / 2 - w / 2;
            float py = Screen.height / 2 - h / 2;

            // フォント描画
            Rect rect = new Rect();
            rect.x = px;
            rect.y = py;
            rect.width = w;
            rect.height = h;

            GUI.Label(rect, "Game Clear!", gUIStyle);
      
        }
    }
}

成果物

youtu.be

感想

正直消化しきれていないので、本の指示通りに記述したほうが良かったのかもしれないです。

利用したもの

おめが試作設計局 / Omega Experimental Design Bureau

Unity4.6/5.0でつくる 2Dゲーム制作入門 [改訂第二版]

Unity4.6/5.0でつくる 2Dゲーム制作入門 [改訂第二版]