AIプログラムとかUnityゲーム開発について

探索や学習などを活用したAI系ゲームを作りたいと思います。

ゼビウスもどき開発(2)

  • 敵機がアニメーションするようになる
  • 敵機を2秒に5機出す
  • 敵機が右側に曲がる、左側に曲がるをランダムに作る
  • 地上の砲台をランダムに配置(弾も撃ってくる)

書き出してみるとあまり進んでないな(´・ω・`)
そもそも強化学習やろうと思っただけなのに……
f:id:yasu9780:20160122204757p:plain

地上の敵(弾は空中兵器と共通)

public class ground_enemy : MonoBehaviour {
	public GameObject ebullet;
	Vector2 min;
	Vector2 max;

	void Start () {
		min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0));
		max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1));
		StartCoroutine ("Shoot");
	}
	void Update () {
		if( transform.position.y < min.y-5f)
			Destroy(gameObject);
		else
		{
			transform.Translate(0,-Time.deltaTime , 0);
		}
	}
	IEnumerator Shoot() {
		while(true){
			Instantiate (ebullet, transform.position,  Quaternion.identity);
			yield return new WaitForSeconds (1.5f);
		}
	}
}

敵の弾

using System.Collections;

public class ebullet : MonoBehaviour {
    float speed = 4f;
	float rad;
	public GameObject targetObject;
	Vector2 min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0));
	Vector2 max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1));

	void Start () {
		float dx= targetObject.transform.position.x-transform.position.x;
		float dy= targetObject.transform.position.y-transform.position.y;
		rad = Mathf.Atan2( dy,dx );
	}
	
	// Update is called once per frame
	void Update () {
		if(transform.position.y > max.y+5f || transform.position.y < min.y-5f)
			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;
		}
	}
}

ゲームマスター作りました。シングルトンってやつ?
スプライトはGMが読み込んで、静的変数に格納。敵はこれを利用してアニメーションしてます。

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

public class GM : MonoBehaviour {
	public static GM instance = null;
	public GameObject solval;
	public GameObject enemy;
	public GameObject ground_enemy;
	public Text GameTime;
	public static Sprite[] sp;

	Vector2 min;
	Vector2 max;
	float gameTime=0;
	int kazu=5;

	void Awake () {
		if (instance == null)
			instance = this;
		else if (instance != this)
			Destroy (gameObject);
	}
	void Start () {
		min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0));
		max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1));
		sp = Resources.LoadAll<Sprite>("xevious_chara_chip_32x32");
		Instantiate (solval, transform.position,  Quaternion.identity);

		for(int i=0;i<=10;i++)
		{
			Vector3 pos = new Vector3(
				Random.Range(min.x+1f,max.x-1f),
				max.y+Random.Range(10f,50f),0f);
			Instantiate (ground_enemy, pos, Quaternion.identity);
		}
	}
	void Update () {
		gameTime+=Time.deltaTime;
		GameTime.text = "GameTime: " + gameTime.ToString();
		if( kazu>0 && ((int)gameTime % 2)==0 )
		{
			Instantiate (enemy, transform.position, Quaternion.identity);
			kazu--;
		}
		if( ((int)gameTime % 2)==1 ) kazu=5;
	}
}

空中の敵

using UnityEngine;
using System.Collections;

public class enemy : MonoBehaviour {
    float speed = 3f;
	public GameObject targetObject;
	public GameObject ebullet;

	Vector2 min;
	Vector2 max;
	float vx=0.1f;
	float vy=1f;
	SpriteRenderer sr;
	int animIndex=8;

	void Start () {
		min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0));
		max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1));
		transform.position = new Vector3(
			Random.Range(min.x,max.x),
			max.y+Random.Range(1f,3f),0f);
		StartCoroutine ("Shoot");
		sr=GetComponent<SpriteRenderer>();
		vx = Random.Range(-3f,3f)/10f;
		vy = Random.Range(1f,2f);
	}
	
	void Update () {
		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
		{
	        float xpos = transform.position.x + vx * speed*Time.deltaTime;
	        float ypos = transform.position.y - vy * speed*Time.deltaTime;
			Vector3 Position = new Vector3 (xpos, ypos,0f);
			transform.position = Position;
			if(vx>0)
				vx+=0.15f*speed*Time.deltaTime;
			else
				vx-=0.15f*speed*Time.deltaTime;
		}
		sr.sprite = GM.sp[animIndex];
		animIndex++;if(animIndex>15)animIndex=8;
	}
	IEnumerator Shoot() {
		while(true){
			Instantiate (ebullet, transform.position,  Quaternion.identity);
			yield return new WaitForSeconds (1.5f);
		}
	}
}

敵のアニメーションは、GMが読んでる静的配列を参照して切り替えています。
8から15で回転表現。敵によってチップ上の位置が違う。
このへんはプチコンのspanimみたいに汎用化の部品にしたい。
プチコンならUV座標。

sr=GetComponent<SpriteRenderer>();
sr.sprite = GM.sp[animIndex];
animIndex++;if(animIndex>15)animIndex=8;

マップを動かしてるので、地上の敵も同様に動かしてるけど、表示領域を動かしたほうがいいかも?