巡逻兵游戏是一款敏捷类游戏,我将游戏规则制定如下:
- 英雄:玩家
- 怪物:巡逻兵
- 当英雄出现在怪物一定范围内,怪物会开启追捕模式,即速度加快
- 每躲过一个巡逻兵的追捕,获得1分
- 当英雄没有进入怪物的搜寻范围时,怪物随机移动
- 被怪物追捕到即游戏结束
- 创新点:规则简单,游戏地形较复杂
代码
BaseCode.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MyGame
{
public class Director : System.Object
{
private static Director _instance;
public ISceneControl sceneCtrl { get; set; }
public bool playing { get; set; } //
public static Director getInstance()
{
if (_instance == null) return _instance = new Director();
else return _instance;
}
public int getFPS()
{
return Application.targetFrameRate;
}
public void setFPS(int fps)
{
Application.targetFrameRate = fps;
}
}
public class Singleton : MonoBehaviour where T : MonoBehaviour
{
protected static T instance;
public static T Instance
{
get
{
if (instance == null)
{
//instance = new GameObject(typeof(T).Name).AddComponent();
instance = (T)FindObjectOfType(typeof(T));
if (instance == null)
{
Debug.LogError("no scene instance");
}
}
return instance;
}
}
}
public interface ISSActionCallback
{
void ActionDone(SSAction source, bool catchState = false);
}
public interface ISceneControl
{
void LoadPrefabs();
}
public interface IUserAction
{
void heroMove(int dir);
void Restart();
}
public class Diretion
{
public const int UP = 0;
public const int DOWN = 2;
public const int LEFT = -1;
public const int RIGHT = 1;
}
public interface IAddAction
{
void addRandomMovement(GameObject sourceObj, bool isActive);
void addDirectMovement(GameObject sourceObj);
}
public interface IGameStatusOp
{
Transform getHeroPosition();
void heroEscapeAndScore();
void patrolHitHeroAndGameover();
}
}
FirstControl
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using MyGame;
using UnityEngine.SceneManagement;
public class FirstControl : MonoBehaviour, ISceneControl, IGameStatusOp, IUserAction, IAddAction
{
//public ActionManager MyActionManager { get; set; }
public GameEventManager gameEventManager;
public GameModel gameModel;
public PatrolFactory factory { get; set; }
public UserGUI user;
public static float time = 0;
void Awake()
{
Director diretor = Director.getInstance();
diretor.sceneCtrl = this;
}
// Use this for initialization
void Start()
{
Begin();
}
public void LoadPrefabs()
{
}
public void Begin()
{
LoadPrefabs();
//MyActionManager = gameObject.AddComponent() as ActionManager;
gameEventManager = gameObject.AddComponent() as GameEventManager;
//gameModel = gameObject.AddComponent() as GameModel;
Debug.Log("game model init");
user = gameObject.AddComponent();
user.Begin();
}
public void Restart()
{
SceneManager.LoadScene("scene");
}
public void heroMove(int dir)
{
gameModel.heroMove(dir);
}
public void addRandomMovement(GameObject sourceObj, bool isActive)
{
gameModel.addRandomMovement(sourceObj, isActive);
}
public void addDirectMovement(GameObject sourceObj)
{
gameModel.addDirectMovement(sourceObj);
}
public Transform getHeroPosition()
{
return gameModel.getHeroPosition();
}
public void heroEscapeAndScore()
{
gameEventManager.heroEscapeAndScore();
}
public void patrolHitHeroAndGameover()
{
gameEventManager.patrolHitHeroAndGameover();
}
}
GameEventManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
public class GameEventManager : MonoBehaviour {
public delegate void GameScoreAction();
public static event GameScoreAction myGameScoreAction;
public delegate void GameOverAction();
public static event GameOverAction myGameOverAction;
private FirstControl scene;
void Start () {
scene = (FirstControl)Director.getInstance().sceneCtrl;
scene.gameEventManager = this;
}
//hero escape, get score
public void heroEscapeAndScore() {
if (myGameScoreAction != null)
myGameScoreAction();
}
//hero gets caught, game over
public void patrolHitHeroAndGameover() {
if (myGameOverAction != null)
myGameOverAction();
}
}
UserGUI
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using MyGame;
public class UserGUI : MonoBehaviour
{
private IUserAction action;
GUIStyle LabelStyle1;
GUIStyle LabelStyle2;
GUIStyle ButtonStyle;
public int score = 0;
public static float time = 0;
public int round = 1;
public int CoolTimes = 3;
public int game = 0; // status
// Use this for initialization
void Start()
{
action = (IUserAction)Director.getInstance().sceneCtrl;
LabelStyle1 = new GUIStyle();
LabelStyle1.fontSize = 20;
LabelStyle1.alignment = TextAnchor.MiddleCenter;
LabelStyle2 = new GUIStyle();
LabelStyle2.fontSize = 30;
LabelStyle2.alignment = TextAnchor.MiddleCenter;
ButtonStyle = new GUIStyle("Button");
ButtonStyle.fontSize = 20;
}
void Update()
{
//check key input and decide whether the hero should play animation
GameObject hero = ((FirstControl)Director.getInstance().sceneCtrl).gameModel.getHero();
bool keyPressed = false;
if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W))
{
hero.GetComponent().Play("Run");
keyPressed = true;
action.heroMove(Diretion.UP);
}
if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S))
{
hero.GetComponent().Play("Run");
keyPressed = true;
action.heroMove(Diretion.DOWN);
}
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
{
hero.GetComponent().Play("Run");
keyPressed = true;
action.heroMove(Diretion.LEFT);
}
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
{
hero.GetComponent().Play("Run");
keyPressed = true;
action.heroMove(Diretion.RIGHT);
}
if (Input.GetKey(KeyCode.J))
{
keyPressed = true;
hero.GetComponent().Play("Attack");
}
if (Input.GetKey(KeyCode.Space))
{
keyPressed = true;
hero.GetComponent().Play("Jump", PlayMode.StopAll);
}
if (keyPressed == false)
{
hero.GetComponent().Play("idle");
}
//cool time system
time += Time.deltaTime;
if (time < 1)
return;
time = 0;
if (game == 3)
{
if (CoolTimes > 1) CoolTimes--;
else game = 0;
}
}
public void Restart()
{
CoolTimes = 3;
game = 3;
score = 0;
}
public void Begin()
{
Restart();
}
void OnGUI()
{
if (game == 0) // playing
{
GUI.Label(new Rect(Screen.width / 2, Screen.height / 2 - 160, 100, 50), "Score: " + score, LabelStyle1);
}
else if (game == 1) // game over
{
GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 85, 100, 50), "Gameover!", LabelStyle2);
if (GUI.Button(new Rect(Screen.width / 2 - 70, Screen.height / 2, 140, 70), "Restart", ButtonStyle))
{
game = 0;
action.Restart();
}
}
else if (game == 2) // win
{
GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 85, 100, 50), "You win!", LabelStyle2);
if (GUI.Button(new Rect(Screen.width / 2 - 70, Screen.height / 2, 140, 70), "Restart", ButtonStyle))
{
game = 0;
action.Restart();
}
}
else if (game == 3) // ready
{
GUI.Label(new Rect(Screen.width / 2 - 30, Screen.height / 2, 100, 50), CoolTimes.ToString(), LabelStyle2);
}
}
void OnEnable()
{
GameEventManager.myGameScoreAction += getScore;
GameEventManager.myGameOverAction += gameOver;
}
void OnDisable()
{
GameEventManager.myGameScoreAction -= getScore;
GameEventManager.myGameOverAction -= gameOver;
}
void getScore()
{
score++;
}
void gameOver()
{
game = 1;
}
}
PatrolControl
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
public class PatrolControl : MonoBehaviour {
private IAddAction addAction;
private IGameStatusOp gameStatusOp;
public int whichPatrol;
public bool isCatching; //whether found hero
private float CATCH_RADIUS = 3.0f;
// Use this for initialization
void Start () {
addAction = (FirstControl)Director.getInstance().sceneCtrl as IAddAction;
gameStatusOp = (FirstControl)Director.getInstance().sceneCtrl as IGameStatusOp;
whichPatrol = getIndex();
isCatching = false;
}
// Update is called once per frame
void Update () {
//check
if (Vector3.Distance(gameStatusOp.getHeroPosition().position, gameObject.transform.position) <= 20f)
{
//hero go in the area
//start catching
if (!isCatching)
{
Debug.Log(this.gameObject + " is catching");
isCatching = true;
}
//moves direct to the hero
addAction.addDirectMovement(this.gameObject);
}
else
{
if (isCatching)
{
Debug.Log(this.gameObject + " stops catching");
//hero has moved out of the area
//stop catching
gameStatusOp.heroEscapeAndScore();
isCatching = false;
}
//then moves randomly
addAction.addRandomMovement(this.gameObject, false);
}
}
public int getIndex()
{
//get the index of patrol
string name = this.gameObject.name;
return name[name.Length - 1] - '0';
}
void OnCollisionStay(Collision e)
{
//hit other patrol, move to other direction
if (e.gameObject.name.Contains("Patrol"))
{
isCatching = false;
addAction.addRandomMovement(this.gameObject, false);
}
//hit hero, game over
if (e.gameObject.name.Contains("hero"))
{
gameStatusOp.patrolHitHeroAndGameover();
Debug.Log("Game Over!");
}
}
}
Follow
“`csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
public class Follow : MonoBehaviour
{
public Vector3 offset;
private Transform playerBip;
public float smoothing = 0.5f;
// Use this for initialization
void Start()
{
playerBip = GameObject.Find("hero").transform;
offset = transform.position - playerBip.position;
}
// Update is called once per frame
void FixedUpdate()
{
//transform.position = playerBip.position + offset;
Vector3 targetPos = playerBip.position + offset;
transform.position = Vector3.Lerp(transform.position, targetPos, smoothing * Time.deltaTime);
}
}