射箭游戏:
靶对象为 5 环,按环计分,最内环为5分,最外环为1分,出靶则-2分;
箭对象,射中后要插在靶上;
游戏无限轮,每轮10 trials达到要求分数即可进入下一轮 ;
增强要求:
靶对象为 5 环,按环计分,最内环为5分,最外环为1分,出靶则-2分;
箭对象,射中后要插在靶上;
游戏无限轮,每轮10 trials达到要求分数即可进入下一轮 ;
增强要求:
添加一个风向和强度标志,提高难度
游戏成品图
首先讲下靶的建立,新建一个空对象,下面挂上5个圆柱体,让他们粗细不一方便触发器触发判断相应的分数。弓和箭则是我上网下载的模型
首先编写Target.js
public class Target : MonoBehaviour {
public int num;//每个靶都有特定的分数
public Emit3 EmitDisk;
public ShootController sceneController;//场记
public void Start()
{
sceneController = (ShootController)SSDirector.getInstance().currentScenceController;
}
void OnTriggerEnter(Collider other)
{
Debug.Log(other.gameObject.tag);
if (other.gameObject.tag == "Arrow")
{
if (!other.gameObject.GetComponent<DiskData3>().hit)
{
other.gameObject.GetComponent<DiskData3>().hit = true;
Debug.Log(num);
sceneController.score += num;//加分
}
EmitDisk = (Emit3)other.gameObject.GetComponent<DiskData3>().action;
//print(this.gameObject);
other.gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;//插在箭靶上
EmitDisk.Destory();//动作完成
}
}
}
我们可以直接复用SSDirector,SSAction,SSActionManager,Singleton。这些我就不列出内容了,之前的博客有。
我们需要编写ShootControler
public class ShootController : MonoBehaviour, ISceneController, IUserAction
{
public ShootAction actionManager { get; set; }
public DiskFactory1 factory { get; set; }
public GameObject Arrow;
public GameObject Bow;
public Emit3 EmitDisk;
public int score = 0;
public int round = 0;//轮数
public int game = 0;//记录游戏进行情况
public int num = 0;//换风的方向
public int time = 0;//每轮箭的个数
public Text GameText;//倒计时文本
public Text FinalText;//结束文本
public Text RoundText;//轮数文本
public Text ScoreText;//分数文本
public Text WindText;//风向文本
private string Horizontal = "";
private string Vertical = "";
public static float directionX;
public static float directionY;
public int CoolTimes = 3; //准备时间
void Awake()
//创建导演实例并载入资源
{
SSDirector director = SSDirector.getInstance();
director.setFPS(60);
director.currentScenceController = this;
director.currentScenceController.LoadResources();
}
// Use this for initialization
void Start () {
round = 1;
directionX = Random.Range(-1, 1);//设置风的水平方向
directionY = Random.Range(-1, 1);//设置风的竖直方向
}
// Update is called once per frame
void Update () {
RoundText.text = "Round:" + round.ToString();//显示轮数
ScoreText.text = "Score:" + score.ToString();//本来应该写一个记分员的但我偷懒写在场记这里
if(directionX > 0)
{
Horizontal = "EAST";
}
else if(directionX < 0)
{
Horizontal = "WEST";
}
if (directionY > 0)
{
Vertical = "NORTH";
}
else if(directionY < 0)
{
Vertical = "SOUTH";
} 根据大小显示相应的东南西北
WindText.text = "WindDirection: " + Vertical + " " + Horizontal;
if(time == 10)
{ //每轮10箭判断分数是否达标
if(score > 35 * round)
{
round++;
time = 0;
num = 0;
}
else
{
GameOver();
game = 2;
}
}
if (num == 3)//每3个箭变一次风的方向
{
num = 0;
directionX = Random.Range(-1, 1);
directionY = Random.Range(-1, 1);
}
}
public void GameOver()
{
FinalText.text = "Game Over!!!";
}
public void StartGame()
{
num = 0;
if (game == 0)
{
game = 3;
StartCoroutine(waitForOneSecond());
}
}
public IEnumerator waitForOneSecond()
{
while (CoolTimes >= 0 && game == 3)
{
GameText.text = CoolTimes.ToString();
print("还剩" + CoolTimes);
yield return new WaitForSeconds(1);
CoolTimes--;
}
GameText.text = "";
game = 1;
}
public void ReStart()
{
SceneManager.LoadScene("task2");
game = 0;
}
public void ShowDetail()
{
GUI.Label(new Rect(220, 50, 350, 250), "Press Enter to Emit a Arrow,10 Arrow for each round.Press up,down,left,right to change your position.Try to get Good Grade!!!");
}
public void hit()
{
if(game == 1)
{
actionManager.playArrow();
num++;
time++;
}
} //载入资源
public void LoadResources()
{
Instantiate(Resources.Load("prefabs/Target"));
Arrow = Instantiate(Resources.Load("prefabs/Arrow01"))as GameObject;
Bow = Instantiate(Resources.Load("prefabs/Bow01")) as GameObject;
Arrow.transform.parent = Bow.transform;
Arrow.transform.localEulerAngles = new Vector3(90, 0, -90);
}
}
再写Diskfactory1
public class DiskFactory1 : MonoBehaviour {
private static DiskFactory1 _instance;
public ShootController sceneControler { get; set; }
public Recorder scoreRecorder;
GameObject arrow;
public List<GameObject> used;
public List<GameObject> free;
private void Awake()
{
if (_instance == null)
{
_instance = Singleton<DiskFactory1>.Instance;
_instance.used = new List<GameObject>();
_instance.free = new List<GameObject>();
}
}
// Use this for initialization
void Start () {
sceneControler = (ShootController)SSDirector.getInstance().currentScenceController;
sceneControler.factory = this;
arrow = Instantiate(Resources.Load("prefabs/Arrow01")) as GameObject;
arrow.transform.parent = sceneControler.Bow.transform;
arrow.transform.localEulerAngles = new Vector3(90, 0, -90);
free.Add(sceneControler.Arrow);
}
public GameObject getArrow(int round)
{
GameObject newArrow;
if (free.Count == 0)
{
newArrow = GameObject.Instantiate(Resources.Load("prefabs/Arrow01")) as GameObject;
}
else
{
newArrow = free[0];
free.Remove(free[0]);
}
newArrow.transform.position = arrow.transform.position;
newArrow.transform.parent = sceneControler.Bow.transform;
newArrow.transform.localEulerAngles = new Vector3(90, 0, -90);
used.Add(newArrow);
return newArrow;
}
public void freeArrow(GameObject arrow1)
{
for (int i = 0; i < used.Count; i++)
{
if (used[i] == arrow1)
{
used.Remove(arrow1);
arrow1.SetActive(true);
free.Add(arrow1);
}
}
return;
}
}
然后编写ShootActionManager
public class ShootActionManager : SSActionManager, ISSActionCallback, ShootAction
{
public ShootController sceneController;
public DiskFactory1 ArrowFactory;
public Recorder scoreRecorder;
public GameObject Arrow;
public Emit3 EmitArrow;
protected void Start()
{
sceneController = (ShootController)SSDirector.getInstance().currentScenceController;
ArrowFactory = sceneController.factory;
sceneController.actionManager = this;
}
protected new void Update()
{
base.Update();
}
public void playArrow()
{
EmitArrow = Emit3.GetSSAction();
Arrow = ArrowFactory.getArrow(sceneController.round);
this.RunAction(Arrow, EmitArrow, this);
Arrow.GetComponent<DiskData3>().action = EmitArrow;
}
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0, string strParam = null, Object objectParam = null)
{
ArrowFactory.freeArrow(source.gameobject);
Debug.Log("free");
source.gameobject.GetComponent<DiskData3>().hit = false;
}
}
ShootAction接口
public interface ShootAction
{
void playArrow();
}
Emit3
public class Emit3 : SSAction
{
int count = 0;
bool enableEmit = true;
Vector3 force;
public ShootController sceneControler = (ShootController)SSDirector.getInstance().currentScenceController;
public static Emit3 GetSSAction()
{
Emit3 action = ScriptableObject.CreateInstance<Emit3>();
return action;
}
// Use this for initialization
public override void Start()
{
force = new Vector3(0, 0.3f, 2);
gameobject.transform.parent = null;
}
// Update is called once per frame
public override void Update()
{
}
public void Destory()
{
this.destroy = true;
this.callback.SSActionEvent(this);
Destroy(gameobject.GetComponent<BoxCollider>());
}
public override void FixedUpdate()
{
count++;
if (!this.destroy)
{
if (enableEmit)
{
gameobject.GetComponent<Rigidbody>().velocity = Vector3.zero;
gameobject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);
enableEmit = false;
}
}
if(count == 60) //60帧之后才加碰撞器
{
gameobject.AddComponent<BoxCollider>();
}
}
}
UserGUI
public class UserGUI1 : MonoBehaviour {
private IUserAction action;
public bool isButtonDown = false;
// Use this for initialization
void Start()
{
action = SSDirector.getInstance().currentScenceController as IUserAction;
}
void OnGUI()
{
GUIStyle fontstyle1 = new GUIStyle();
fontstyle1.fontSize = 50;
fontstyle1.normal.textColor = new Color(255, 255, 255);
if (GUI.RepeatButton(new Rect(0, 0, 120, 40), "Shooting"))
{
action.ShowDetail();
}
if (GUI.Button(new Rect(0, 60, 120, 40), "STARTGAME"))
{
action.StartGame();
}
if (GUI.Button(new Rect(0, 120, 120, 40), "RESTART"))
{
action.ReStart();
}
if (Input.GetMouseButtonDown(0) && !isButtonDown)
{
action.hit();
isButtonDown = true;
}
else if(Input.GetMouseButtonDown(0) && isButtonDown)
{
isButtonDown = false;
}
}
}
为了弓移动我编写了MoveBow
public class MoveBow : MonoBehaviour {
public float speedX = 0.01f;
public float speedY = 0.01f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float translationY = Input.GetAxis("Vertical") * speedY;
float translationX = Input.GetAxis("Horizontal") * speedY;
translationY *= Time.deltaTime;
translationX *= Time.deltaTime;
transform.Translate(0, translationY, 0);
transform.Translate(0, 0, -translationX);
}
}
为了产生风,在箭与靶之间加了透明区域的触发器,在触发器内会产生风
public class CreatWind : MonoBehaviour {
public ShootController sceneController;
public void Start()
{
sceneController = (ShootController)SSDirector.getInstance().currentScenceController;
}
private void OnTriggerStay(Collider other)
{
if (other.gameObject.tag == "Arrow")
{
other.gameObject.GetComponent<Rigidbody>().AddForce(new Vector3(ShootController.directionX * sceneController.round, ShootController.directionY * sceneController.round, 0));
Debug.Log("wind");
}
}
}
这样就大功告成了~~~
有兴趣的可以去我的GIthub看,这是
传送门