neoacoさんの ゲーム作ったよ報告書

いつでも ねむい  げーむ ちょっとつくる

unity一週間ゲームジャム (お題:ふえる)のソースコードを公開する流行りに乗りたい

この8月にやっていたunity一週間ゲームジャム (お題:ふえる)が終わった後、ツイッターでソースを公開するのが流行っているようなので便乗してみます。

作ったゲーム

ふえるだけですむとおもうな unityroom.com
玉がどんどん増えていくブロック崩しです。
玉が増えるだけだとすぐ終わっちゃうし面白くないので、消したブロックがどんどん復活するようにしました。
復活するだけだとすぐ終わっちゃうし面白くないので、復活した奴がどんどん固くなるようにしました。全5段階。

ソース

秘伝のたれ……というほどのことでもないんだけど、オープニングとかエンディングとかその辺は見ても面白くないと思うので、
ゲームの全体をコントロールしてるところとかだけにします。

・全部で四つ
・プレイヤー(棒)、ブロック総合、ブロック個別、弾が死んだと判断するところ
・頑張ったのはブロック関連

player.cs(棒)
------------
#pragma warning disable 649
// SerializeFieldを使ってると、使ってるのに使ってないとうるさいので、
// ビルドする前にこれをつけることにしている

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

public class playerCtrl : MonoBehaviour{

    Vector3 pos = new Vector3(0,-7.15f,0);
    Animator Anim;
    bool isPlay=false;
    [SerializeField]
    GameObject DeadLine;
    [SerializeField]
    GameObject GameEndObject;
    [SerializeField]
    GameObject GameClearObject;
    [SerializeField]
    GameObject ResultBoardObject;
    [SerializeField]
    GameObject PlayerResultObject;
    [SerializeField]
    GameObject GiveUpObject;
    [SerializeField]
    GameObject GiveUpButton;
    bool CanGiveUp = false;
    [SerializeField]
    Text PlayTime;
    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
    TimeSpan TotalDateTime;
    int playTime;
    GameObject[] BGM;
    [SerializeField]
    GameObject BGMobject;

    private void Awake() {
        // BGMのチェック
        BGM = GameObject.FindGameObjectsWithTag("BGM");
        if (BGM.Length < 1) { Instantiate(BGMobject); BGM = GameObject.FindGameObjectsWithTag("BGM"); }
        DontDestroyOnLoad(BGM[0]);
    }

    void Start(){
        // ボール出すアニメ
        Anim = transform.GetChild(0).GetComponent<Animator>();
        Anim.speed = 0;
        GameEndObject.SetActive(false);
        GameClearObject.SetActive(false);
        ResultBoardObject.SetActive(false);
        GiveUpObject.SetActive(false);
        GiveUpButton.SetActive(false);
    }

    void FixedUpdate(){
            pos = Input.mousePosition;
            pos = Camera.main.ScreenToWorldPoint(pos);
            pos.y = -7.15f;
            pos.z = 0;
            if (pos.x < -9) {
                pos.x = -9;
            }
            if (pos.x > 9) {
                pos.x = 9;
            }
            transform.localPosition = pos;
        if (isPlay) {
            TotalDateTime = sw.Elapsed;
            PlayTime.text = TotalDateTime.ToString(@"mm\:ss\.ff");
            if (!CanGiveUp && sw.ElapsedMilliseconds > 300000) { GiveUpButton.SetActive(true); }
            // ストップウォッチ関数最高
        }
    }

    void MoreIncrease() {
        Anim.speed /= 0.95f;
        if (Anim.speed > 5) { Anim.speed = 5; }
    }

    void GameStart() {
        isPlay = true;
        Anim.speed = 1;
        sw.Start();
    }

    void GameEnd() {
        Anim.speed = 0;
        isPlay = false;
        sw.Stop();
        // 死んだ球数を数えないようにする
        DeadLine.SendMessage("GameEnd");
        // ゲーム終了処理用UI
        GameEndObject.SetActive(true);
    }

    void GameClear() {
        Anim.speed = 0;
        isPlay = false;
        sw.Stop();
        DeadLine.SendMessage("GameEnd");
        GameClearObject.SetActive(true);
    }

    void SendScore() {
        playTime = (int) sw.ElapsedMilliseconds;
        PlayerResultObject.SendMessage("GetScore",playTime);  // 確かこれがランキングに値を渡してるんじゃなかったかな(曖昧な記憶)
    }

    public void CallGiveUp() {
        Anim.speed = 0;
        isPlay = false;
        sw.Stop();
        DeadLine.SendMessage("GameEnd");
        GiveUpObject.SetActive(true);
    }
}
blockCtrl.cs(ブロック総合)
---------
#pragma warning disable 649

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
using System.Data;

public class blockCtrl : MonoBehaviour{

    [SerializeField]
    GameObject block;
    GameObject[,] blockArray;
    int[,] statusArray;
    [SerializeField]
    Text BlockText;

    int statusA;
    int statusB;
    int statusC;

    int yoko = 9;
    int tate = 7;
    int lastBlock;

    GameObject Player;
    bool isPlay = false;

    void Start(){
        // ブロックの配置
        blockArray = new GameObject[yoko, tate];
        statusArray = new int[yoko, tate];
        Player = GameObject.FindGameObjectWithTag("Player");
        for (int xx = 0; xx < yoko; xx++) {
            for (int yy = 0; yy < tate; yy++) {
                GameObject bl = Instantiate(block, new Vector3(-8 + xx*2, 8.8f - yy*1.5f, 0), Quaternion.identity);
                bl.transform.name = xx + "," + yy;
                bl.transform.parent = this.gameObject.transform;
                blockArray[xx,yy] = bl;
                statusArray[xx,yy] = 1;
                if (yy == 0) { bl.SendMessage("UpStatus"); statusArray[xx, yy] = 2; }
            }
        }
        lastBlock = yoko * tate;
        BlockText.text = lastBlock.ToString();
    }

    void FixedUpdate(){
        if (isPlay) {
            lastBlock = 0;
            foreach (int i in statusArray) {
                if (i != 0) { lastBlock += 1; }
            }
            if (lastBlock == 0) {
                //gameclear
                isPlay = false;
                Player.SendMessage("GameClear");
            }
            BlockText.text = lastBlock.ToString();
        }
    }

    void GetDeadBall() {
        // ランダムで選んだブロックを一段階固くする
        int xxx = UnityEngine.Random.Range(0,yoko);
        int yyy = UnityEngine.Random.Range(0,tate);
        statusArray[xxx,yyy] += 1;
        GameObject UpBlock = GameObject.Find(xxx + "," + yyy);
        UpBlock.SendMessage("UpStatus");
    }

    void GetBlockStatus(string blockName) {
        // 各ブロックのステータスの管理
        // ブロックの名前は xx,yy という名前になっているので、分割してどの場所のブロックなのかを特定している
        string[] arr = blockName.Split(',');
        statusA = Int32.Parse(arr[0]);
        statusB = Int32.Parse(arr[1]);
        statusC = Int32.Parse(arr[2]);
        statusArray[statusA,statusB] = statusC;
    }

    void NoBall() {
        isPlay = false;
    }

    void GameStart() {
        isPlay = true;
    }
}
eachBlock.cs(ブロック個別)
---------
#pragma warning disable 649

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

public class eachBlock : MonoBehaviour{

    int status = 1;
    GameObject BC;
    string report;
    [SerializeField]
    Sprite status1;
    [SerializeField]
    Sprite status2;
    [SerializeField]
    Sprite status3;
    [SerializeField]
    Sprite status4;
    [SerializeField]
    Sprite status5;
    Collider2D col;
    SpriteRenderer spr;
    AudioSource AS;
    [SerializeField]
    AudioClip AC;

    void Start(){
        BC = GameObject.FindGameObjectWithTag("GameController");
        col = GetComponent<Collider2D>();
        spr = GetComponent<SpriteRenderer>();
        AS = GetComponent<AudioSource>();
    }

    void Update() {
        if (status == 5) {
            spr.sprite = status5;
            col.isTrigger = false;
            spr.color = new Color(1, 1, 1, 1);
        } else if (status == 4) {
            spr.sprite = status4;
            col.isTrigger = false;
            spr.color = new Color(1, 1, 1, 1);
        } else if (status == 3) {
            spr.sprite = status3;
            spr.color = new Color(1, 1, 1, 1);
            col.isTrigger = false;
        } else if (status == 2) {
            spr.sprite = status2;
            spr.color = new Color(1, 1, 1, 1);
            col.isTrigger = false;
        } else if (status == 1) {
            spr.sprite = status1;
            spr.color = new Color(1, 1, 1, 1);
            col.isTrigger = false;
        } else {
            spr.color = new Color(1, 1, 1, 0);
            col.isTrigger = true;
        }
    }

	private void OnCollisionEnter2D(Collision2D collision) {
        status -= 1;
        if (status < 1) { status = 0; AS.PlayOneShot(AC);}
        report = transform.name + "," + status;
        BC.SendMessage("GetBlockStatus",report);
        // SendMessageは一つの値しか送れないので、ブロック名(xx,yy)にステータスをくっつけてstringとして送信
    }

    void UpStatus() {
        status += 1;
        if (status > 5) { status = 5; }
        report = transform.name + "," + status;
        if (BC != null) {
            BC.SendMessage("GetBlockStatus", report);
        }
    }
}
DeadLineRepoat.cs(玉を殺すところ)
---------
#pragma warning disable 649

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

public class deadLineReport : MonoBehaviour{

    GameObject BC;
    GameObject Player;
    bool isPlay = true;
    int ballcounter;
    int deadBallCounter;
    [SerializeField]
    Text LiveBallText;
    [SerializeField]
    Text DeadBallText;

    void Start(){
        ballcounter = 1;
        deadBallCounter = 0;
        BC = GameObject.FindGameObjectWithTag("GameController");
        Player = GameObject.FindGameObjectWithTag("Player");
        LiveBallText.text = ballcounter.ToString();
        DeadBallText.text = deadBallCounter.ToString();
    }

	private void OnCollisionEnter2D(Collision2D collision) {
        if (collision.transform.tag == "ball") {
            if (isPlay) {
                BC.SendMessage("GetDeadBall");
                Player.SendMessage("MoreIncrease");
                ballcounter -= 1;
                deadBallCounter += 1;
                if (ballcounter == 0) {
                    //gameOver
                    BC.SendMessage("NoBall");
                    Player.SendMessage("GameEnd");
                    GameEnd();
                }
                LiveBallText.text = ballcounter.ToString();
                DeadBallText.text = deadBallCounter.ToString();
            }
        }
	}

    void popBall() {
        if (isPlay) {
            ballcounter += 1;
            LiveBallText.text = ballcounter.ToString();
        }
    }

    void GameEnd() {
        isPlay = false;
    }
}


こんなもんですかね。まるっと公開するのはちょっと恥ずかしいですな。
一番工夫を凝らしたと思っているところはブロックのステータスを受け渡しするところです。
ブロックを復活させるにはDestroyしてはいけないので、どうしたものかと考えていたんですが、
GWにゲームつくった時に文字列を分割したな、と思いだして、採用しました。
ランキング周りは作ってもらったんでナンモワカランです。
他にはボールのコントロールするやつ、ゲームの背景を設定するやつ、タイトル画面、カウントダウンのアニメにつけるやつなど、スクリプトファイル数だけで言えば16個作りました。中身がほとんどコピペのやつもある。

いや~~~昔よりはマシな書き方をしていると思いたいですけどね。
昔はひどかったからね。関数名とか何をつけていいのかわからなくてsusieとかsasoribi とかつけてたからね。
いまだに一行で「if (status < 1) { status = 0; AS.PlayOneShot(AC);}」とか書くけど、これはマジで例外で、本当に一文しかないしこれ以上発展しないやつだけです。何行にもわたってる方が見辛いやつもあるやん、こう、同じ数値が縦に並んでてほしいときとかあるやん。wasdでプレイヤーを移動させるときとかさぁ。(言い訳)


以上、独りぼっちゲーム開発のneoacoさんのソースでした。
最近は夫を巻き込みつつあるので、独りぼっちって言いづらくなってきたが、発注しないと何もしてもらえないのでやはり独りぼっちであってると思う。