シューティングゲームを作ってみて、自機をAIとして強化学習をしてみたいと思います。
人間には難しいような難易度のシューティングゲームを作ってみようと思うのですが、せっかくなんでゼビウスもどきでも作ってみようかなと。
プチコンのニコ動でゼビウスが完璧に移植されているのを見て触発されました(ゝω・)
もっとも再現は、とてつもない時間がかかるので、なんとなくでいいです。
マップとかキャラチップをネットで探してきて、たりない部分はPaint.netで修正したり、疲れました。
しかもキャラが32x32で汚いです。強化学習が目的なのでクオリティは気にしません(気にしてはいけない)
マップが2048x1024サイズあります(汗 マップチップなんか配布されてないし、自分で作る気力なし。
とりあえず敵がいて、弾を撃ってくるまでは作ったのですが、まだ当たり判定は入れてないので、
敵も自機も互いに無害です。
自機のコード(カーソルキーで移動。スペースキーで弾を生成します。あとは弾が勝手に飛ぶ)
using UnityEngine; using System.Collections; public class solval : MonoBehaviour { float speed = 4f; public GameObject bullet; public GameObject enemy; void Start () { transform.position = new Vector3(0,-6.0f,0); StartCoroutine ("Spawn"); } void Update () { float xpos = transform.position.x+Input.GetAxis("Horizontal") * speed*Time.deltaTime; float ypos = transform.position.y+Input.GetAxis("Vertical") * speed*Time.deltaTime; Vector3 playerPos = new Vector3 (xpos, ypos,-2f); transform.position = playerPos; Clamp (); if (Input.GetKeyUp(KeyCode.Space)) { Instantiate (bullet, transform.position, Quaternion.identity); } } void Clamp (){ Vector2 min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0)); Vector2 max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1)); Vector2 pos = transform.position; pos.x = Mathf.Clamp (pos.x, min.x, max.x); pos.y = Mathf.Clamp (pos.y, min.y, max.y); transform.position = pos; } IEnumerator Spawn() { while(true){ Instantiate (enemy, transform.position, transform.rotation); yield return new WaitForSeconds (0.5f); } } }
自機の弾(プレハブに入っていて、自機が生成する。上に飛んでいって画面外になったら死亡)
using UnityEngine; using System.Collections; public class bullet : MonoBehaviour { float speed = 15f; void Start () { } // Update is called once per frame void Update () { Vector2 min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0)); Vector2 max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1)); if(transform.position.y > max.y || transform.position.y < min.y) { Destroy(gameObject); } else { float xpos = transform.position.x+0f * speed*Time.deltaTime; float ypos = transform.position.y+1f * speed*Time.deltaTime; Vector3 playerPos = new Vector3 (xpos, ypos,0f); transform.position = playerPos; } } }
敵(実は自機が生成している。生成時の自機がいた位置に向かって飛ぶ。弾を0.3秒に一回作る)
using UnityEngine; using System.Collections; public class enemy : MonoBehaviour { float speed = 7f; Vector2 dir; float rad; Vector3 rotation; public GameObject targetObject; public GameObject ebullet; void Start () { Vector2 min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0)); Vector2 max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1)); transform.position = new Vector3(Random.Range(min.x,max.x),max.y+1f,0f); float dx= targetObject.transform.position.x-transform.position.x; float dy= targetObject.transform.position.y-transform.position.y; rad = Mathf.Atan2( dy,dx ); StartCoroutine ("Shoot"); } void Update () { Vector2 min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0)); Vector2 max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1)); if(transform.position.y > max.y+5f || transform.position.y < min.y-5f) Destroy(gameObject); else if(transform.position.x > max.x || transform.position.x < min.x) Destroy(gameObject); else { Vector2 Position = transform.position; Position.x += speed * Mathf.Cos(rad)*Time.deltaTime; Position.y += speed * Mathf.Sin(rad)*Time.deltaTime; transform.position = Position; } } IEnumerator Shoot() { while(true){ Instantiate (ebullet, transform.position, Quaternion.identity); yield return new WaitForSeconds (0.3f); } } }
シューティングゲーム自体はそこそこで切り上げて、はやく強化学習に入りたい。