Unity2017 经典游戏开发教程 算法分析与实现 (张帆 著)

https://meta.box.lenovo.com/link/view/82c451b41ce34e81a4b34cb46747d3d5

 

第1章 熟悉Unity软件的操作

第2章 打地鼠 (已看)

第3章 俄罗斯方块

第4章 打砖块 (已看)

第5章 三消 (已看)

第6章 翻牌子 (已看)

第7章 连连看

第8章 拼图 (已看)

第9章 推箱子 (已看)

第10章 炸弹人  (已看)

第11章 华容道

第12章 横板跑酷

第13章 扫雷

第14章 贪吃蛇

第15章 五子棋

第16章 跳棋

第17章 吃豆人

第18章 斗地主

第19章 坦克大战

2111

第1章 熟悉Unity软件的操作

  1.1 可多平台发布的Unity游戏引擎

 

  1.2 Unity游戏引擎的下载和安装

 

    1.2.1 Unity的下载

 

    1.2.2 Unity的安装

 

    1.2.3 Unity的注册

 

    1.2.4 启动Unity

 

  1.3 认识Unity的编辑界面

 

    1.3.1 软件标题栏

 

    1.3.2 主菜单

 

    1.3.3 Project项目资源窗口

 

    1.3.4 Hierarchy层级窗口

 

    1.3.5 Scene场景窗口

 

    1.3.6 Inspector组件属性面板

 

    1.3.7 Game游戏预览窗口

 

    1.3.8 Console控制台

 

  1.4 自定义窗口布局

 

    1.4.1 使用Unity内置的窗口布局功能

 

    1.4.2 自定义窗口布局

 

  1.5 Unity中定义的重要概念

 

    1.5.1 资源(Assets)

 

    1.5.2 工程(Project)

 

    1.5.3 场景(Scenes)

 

    1.5.4 游戏对象(GameObject)

 

    1.5.5 组件(Component)

 

    1.5.6 脚本(Scripts)

 

    1.5.7 预置(Prefabs)

 

第2章 打地鼠

  2.1 游戏简介

《打地鼠》(原名: Whac-A-Mole)最早可以追溯到1976年创意工程股份有限公司(Creative Engineering,Inc.)推出的一款有偿街机游戏.这款游戏能够提高人体大脑和身体的协调能力,增强臂力, 锻炼身体,深受大众的喜爱. 在游戏中, 玩家要在规定时间内,敲打一只只从地洞力冒出头的傻地鼠,从而获得游戏胜利.但是作为掌机,如NDS或智能手机等是不可能直接用锤子去敲打屏幕的, 取而代之的便是NDS触控笔或者手指

  2.2 游戏规则

这个游戏的游戏规则是,在一定的时间内,地鼠随机出现在九个洞口中, 玩家要在它出现的时候击中它,击中加分,反之地鼠会自动消失,时间耗尽则游戏结束

随着游戏时间的减少, 老鼠出现的频率越来越高,存在的时间也越来越短,游戏难度逐步上升

  2.3 程序思路

    2.3.1 洞口的排列

利用一个3 x 3 的二维数组或者一个一维数组来表示地图中的9个洞口

    2.3.2 地鼠出现频率

public void start() {
    InvokeRepeating("canAppear", 0, 5);
}

public void canAppear() {
    InvokeRepeating("地鼠生成函数",0,1);
}
View Code

    2.3.3 单个地鼠设置

if (未被点击) {
    Destroy(this.gameObject, 3.0f);
} else {
    Destroy(this.gameObject);
}
View Code

    2.3.4 游戏时间和分数

    2.3.5 游戏流程图

  2.4 程序实现

    2.4.1 前期准备

    2.4.2 设置洞口

    2.4.3 单只地鼠的出现和消失

    2.4.4 地鼠的随机出现和出现频率

    2.4.5 时间, 分数和其他.

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

/// <summary>
/// 地鼠被击打以后调用该函数
/// </summary>
public class Done_Beaten : MonoBehaviour {

    public int id;
    /// <summary>
    /// 在点击后3.5s销毁该地鼠,将洞口的isAppear值设置为false
    /// </summary>
    void Update () {
        Destroy(gameObject, 0.35f);
        FindObjectOfType<Done_GameControl>().holes[id].isAppear = false;
    }
}


using System.Collections;
using UnityEngine;

/// <summary>
/// 鼠标追踪
/// </summary>
public class Done_ChangeCursor : MonoBehaviour
{
    public Texture2D UserCursor;
    public Texture2D UserClickCursor;
    private bool isClicked = false;

    void Start ()
    {
        //在游戏界面内隐藏系统光标
        Cursor.visible = false;
    }

    /// <summary>
    /// 时时判断鼠标点击状态,便于切换图像
    /// </summary>
    void Update ()
    {
        if (Input.GetMouseButton (0))
        {
            isClicked = true;
        }
        else
        {
            isClicked = false;
        }
    }

    void OnGUI ()
    {
        //获取鼠标当前位置
        Vector2 mouse_pos = Input.mousePosition;

        //鼠标点击与否显示相应的图片
        if (isClicked == false)
        {
            GUI.DrawTexture(new Rect(mouse_pos.x -40f, Screen.height - mouse_pos.y -60f , 100, 100), UserCursor);
        }
        else
        {
            GUI.DrawTexture(new Rect(mouse_pos.x - 40f, Screen.height - mouse_pos.y -60f, 100, 100), UserClickCursor);
        }
    }

}


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

/// <summary>
/// 游戏总控制脚本
/// </summary>
public class Done_GameControl : MonoBehaviour {


    public GameObject Gophers;
    public int PosX, PosY;


    public TextMesh timeLabel;
    public float time = 30.0f;
    public int score = 0;
    

   
    /// <summary>
    /// 设定一个地洞类,存储地洞的坐标以及是否出现的布尔值
    /// </summary>
    public class Hole {
        
        public bool isAppear;
        public int HoleX;
        public int HoleY;
        
    }

    public Hole[] holes;


    /// <summary>
    /// Awake函数实际上比Start函数调用的更早
    /// 在场景初始化的时候,将每个洞口的坐标值存入一维数组中,并将每一个洞口的isAppear值设定为false
    /// (-2,0) (0,0) (2,0)
    /// (-2,-1)(0,-1)(2,-1)
    /// (-2,-2)(0,-2)(2,-2)
    /// </summary>
    void Awake() {
        
        PosX = -2;
        PosY = -2;
        holes = new Hole[9];
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                holes[i * 3 + j] = new Hole();
                holes[i * 3 + j].HoleX = PosX;
                holes[i * 3 + j].HoleY = PosY;
                holes[i * 3 + j].isAppear = false;

                PosY++;
            }
            PosY = -2;
            PosX = PosX + 2;
        }
    }
    /// <summary>
    /// 在游戏场景开始后延时调用canAppear函数,从第0秒开始,每隔十秒调用一次
    /// </summary>
    void Start () {

        InvokeRepeating("CanAppear", 0, 10);

    }

    /// <summary>
    /// 游戏时间控制
    /// </summary>
    void Update () {

        //时间以秒的速度减少,并在timeLabel里显示当前剩余时间(一位小数)
        time -= Time.deltaTime;
        timeLabel.text = "Time: " + time.ToString("F1");

        //当时间耗尽,调用GameOver函数
        if (time < 0) {
            GameOver();
        }
        
    }

    /// <summary>
    /// 从第0秒开始调用函数,每隔1秒调用一次
    /// </summary>
    public void CanAppear() {

        InvokeRepeating("Appear", 0,1);

    }

    /// <summary>
    /// 地鼠生成函数
    /// </summary>
    public void Appear()
    {
        //当前地洞可以生成地鼠的条件: isAppear = false         
        //随机生成i值选择洞口,直到符合条件的洞口被选中
        int i = Random.Range(0, 9);        
        while (holes[i].isAppear == true){
            i = Random.Range(0, 9);
        }
        //debug只是用来打印当前的坐标,便于观察,并不会影响游戏运行(可写可不写)
        Debug.Log(holes[i].HoleX + "," + holes[i].HoleY);

        //选定洞口以后,在洞口的坐标上生成地鼠,传递洞口id,将当前洞口的isAppear值改为true
        Instantiate(Gophers, new Vector3(holes[i].HoleX, holes[i].HoleY + 0.4F, -0.1F), Quaternion.identity);
        Gophers.GetComponent<Done_Gophers>().id = i;
        holes[i].isAppear = true;

       
    }
    
    /// <summary>
    /// 游戏结束函数
    /// </summary>
    void GameOver() {
        time = 0;
        timeLabel.text = "Time: 0";

        //将所有延时调用函数全部取消
        CancelInvoke();

        Debug.Log("game over");
    }
}


using UnityEngine;

/// <summary>
/// 地鼠类
/// </summary>
public class Done_Gophers : MonoBehaviour {
    
    public GameObject beaten;
    
    public int id;

    /// <summary>
    /// 地鼠出现后,如果未被点击,将在三秒后自动销毁,将相应洞口的isAppear值设置为false
    /// </summary>
    void Update () {
        
        Destroy(this.gameObject,3.0f);
        FindObjectOfType<Done_GameControl>().holes[id].isAppear = false;
    }
   
    /// <summary>
    /// 鼠标点击
    /// </summary>
    void OnMouseDown() {
        Debug.Log("点击");

        //在相同的位置生成一个被击打图像的地鼠
        GameObject g;
        g = Instantiate(beaten, gameObject.transform.position, Quaternion.identity);
        g.GetComponent<Done_Beaten>().id = id;

        //增加分数
        FindObjectOfType<Done_GameControl>().score += 1;
        int scores = FindObjectOfType<Done_GameControl>().score;
        GameObject.Find("Score").gameObject.GetComponent<TextMesh>().text = "Score: " +scores.ToString();
        
        //FindObjectOfType<>().text = score.ToString();
        //GetComponentInChildren<TextMesh>().text = score.ToString();
        //scoreLabel.text = "Score: " + score; 

        //在0.1s后摧毁当前生成的地鼠
        Destroy(this.gameObject, 0.1f);
        
    }

    

}


using UnityEngine;
using UnityEditor.SceneManagement;

/// <summary>
/// 重新开始函数
/// </summary>
public class Done_Restart : MonoBehaviour {
    /// <summary>
    /// 按钮被点击以后,重新调用游戏场景
    /// </summary>
    public void OnMouseDown() {
        Debug.Log("restart");
        EditorSceneManager.LoadScene("Done_mole");
    }
}
View Code

第3章 俄罗斯方块

  3.1 游戏简介

 

  3.2 游戏规则

 

  3.3 游戏实现思路

 

    3.3.1 随机生成方块

 

    3.3.2 地图的生成

 

    3.3.3 判断方块是否都在边界内

 

    3.3.4 判断是否碰到其他方块

 

    3.3.5 检查是否满行

 

    3.3.6 删除填满的行

 

    3.3.7 提示下一个方块组

 

    3.3.8 结束判定

 

    3.3.9 游戏流程图

 

  3.4 游戏程序实现

 

    3.4.1 前期准备

 

    3.4.2 制作场景

 

    3.4.3 生成方块组与方块组下落

 

    3.4.4 边界判断

 

    3.4.5 删除一行方块

 

    3.4.6 结束判定

 

    3.4.7 细节完善

 

第4章 打砖块

  4.1 游戏简介

打砖块是一款十分简单的小游戏, 只需要打掉所有的砖块即可获得胜利

《Breakout》,世界第一款打砖块游戏, 1976年由英宝格公司发行. 游戏设计者是后来创立苹果电脑公司的史蒂夫,乔布斯与斯蒂夫,沃兹尼亚克两人,程序设计是Brad Stewart

《Gee Bee》, 日本Namco公司在1978年推出的该公司第一款街机游戏, 合并了打砖块和弹珠台游戏的特色

快打砖块《Arkanoid》, 日本泰托(Taito)公司在1986年推出的街机游戏, 引入了电脑控制的敌机,还有后来打砖块中常见的加强道具(Powerup Item)等元素

  4.2 游戏规则

玩家操作在屏幕底端的横板, 通过反弹小球的方式, 使小球击打并消除砖块,, 只需要打掉所有的砖块即可获得胜利.小球掉落至横板下方即失败

  4.3 程序思路

    4.3.1 地图生成

for (x轴) {
    for (y轴) {
        生成砖块;
    }
}

XXXXXXXXXXXXX
RRRRRRRRRRRRR
YYYYYYYYYYYYY
BBBBBBBBBBBBB
GGGGGGGGGGGGG
PPPPPPPPPPPPP
XXXXXXXXXXXXX
XXXXXXXXXXXXX
XXXXXXXXXXXXX
RRRRRRRRRRRRR
YYYYYYYYYYYYY
BBBBBBBBBBBBB
GGGGGGGGGGGGG
PPPPPPPPPPPPP
XXXXXXXXXXXXX

XXXXRRRRRXXXX
XXXRRRRRRRXXX
XXRRRRRRRRRXX
XRRYRYRYRYRRX
RRRRRRRRRRRRR
XXRRRXRXRRRXX
XXXRXXXXXRXXX
XXXYXXXXXYXXX
XXXXYXXXYXXXX
XXXYYYYYYYXXX
XXYYXYYYXYYXX
XYYYYYYYYYYYX
XYXYYYYYYYXYX
XYXYXXXXXYXYX
XXXXYYXYYXXXX

XXXRRRRRXXXX
XXRRRRRRRRRX
XXGGGYYPYXXX
XGYGYYYPYYYX
XGYGGYYYPYYY
XXGYYYYPPPPX
XXXYYYYYYXXX
XXRRBRRBRRXX
XRRRBRRBRRRX
RRRRBBBBRRRR
YYRBYBBYBRYY
YYYBBBBBBYYY
YYBBBBBBBBYY
XXBBBXXBBBXX
XGGGXXXXGGGX
GGGGXXXXGGGG

GGGGGGGGGGGGG
GGGGGGGGGGGGG
GGXXXGGGXXXGG
GGXXXGGGXXXGG
GGXXXGGGXXXGG
GGGGGXXXGGGGG
GGGGGXXXGGGGG
GGGXXXXXXXGGG
GGGXXXXXXXGGG
GGGXXGGGXXGGG
GGGXXGGGXXGGG
GGGGGGGGGGGGG
GGGGGGGGGGGGG

XXXXXXRRRXXX
XXXXXRRRRRXX
XXXXXRGGGGXX
XXXRRRRRRRRR
XXXXRBBBBBBX
XXXXXBXBYXBX
XXXXXBBYYYBX
XYYXXBBYYYYY
YYYYXBYYYYYX
YYYYBBBBBBXX
XYYBYBBBBBBX
XXYBYBBBBBBB
XXXYBBBBBBXB
XXXXYBBBBBXX
XXXXBBBBBBBX
XXXXBBXXXBBX
XXXYYYXXXYYY
View Code

    4.3.2 砖块控制

    4.3.3 小球控制

float HitFactor {
    return (ballPos.x - racketPos.x) / racketWidth;
}

if (碰撞板) {
    小球的 xSpeed = HitFactor;
}
View Code

    4.3.4 游戏流程图

  4.4 程序实现

    4.4.1 前期准备

    4.4.2 游戏场景设定

    4.4.3 横板控制

    4.4.4 小球控制

    4.4.5 砖块的生成及控制

    4.4.6 道具的控制

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

public class Done_Ball : MonoBehaviour {
    public float BallSpeed = 18f;//如果速度过快,可以减小该值,但是可能受到重力影响,不能弹到上方,可以适当减小重力值,如:速度设置为12,Unity中Physics2D的重力值应为-4.45
    int num = 0;

    // Use this for initialization
    void Start()
    {



    }

    // Update is called once per frame
    void Update()
    {

        if (Input.anyKey && num == 0)//num控制小球是不是第一次离开横板
        {
            GetComponent<Rigidbody2D>().velocity = Vector2.up * BallSpeed;
            num++;
        }


        if (transform.position.y < -8)//小球掉落后重载场景
        {
            SceneManager.LoadScene("Done_Break Out");
        }
    }

    /// <summary>
    /// 发球的碰撞触发器
    /// </summary>
    /// <param name="col"></param>
    private void OnCollisionEnter2D(Collision2D col)
    {
        if (col.gameObject.name == "racket" && num == 1)
        {
            float x = HitFactor(transform.position,
                                col.transform.position, col.collider.bounds.size.x
                                );

            Vector2 dir = new Vector2(x, 1).normalized;
            GetComponent<Rigidbody2D>().velocity = dir * BallSpeed;
        }


    }

    /// <summary>
    /// 球与板接触位置与反弹方向的公式
    /// </summary>
    /// <param name="ballPos"></param>
    /// <param name="racketPos"></param>
    /// <param name="racketWidth"></param>
    /// <returns></returns>
    float HitFactor(Vector2 ballPos, Vector2 racketPos, float racketWidth)
    {
        return (ballPos.x - racketPos.x) / racketWidth;
    }
}


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

public class Done_Block : MonoBehaviour {

    public string color;
    public int hits_required;
}


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

public class Done_BlockController : MonoBehaviour
{
    public GameObject upgradePrefab;
    // Use this for initialization
    void Start()
    {

        string spriteFileName = "sprites/block_" + GetComponent<Done_Block>().color;//获取颜色名称

        this.GetComponent<SpriteRenderer>().sprite = Resources.Load<UnityEngine.Sprite>(spriteFileName);//贴图

    }

    /// <summary>
    /// 球与砖块的碰撞检测
    /// </summary>
    /// <param name="col"></param>
    void OnCollisionEnter2D(Collision2D col)
    {
        GameObject go = GameObject.Find("Main Camera");
        Done_LevelLoader levelLoader = go.GetComponent<Done_LevelLoader>();
        gameObject.GetComponent<Done_Block>().hits_required -= 1;

        if (gameObject.GetComponent<Done_Block>().hits_required == 0)
        {
            Destroy(gameObject);
            levelLoader.block_count--;
            if (Random.value < 0.10)//生成概率
            {
                Instantiate(upgradePrefab,
                            new Vector3(
                                col.gameObject.transform.position.x,
                                col.gameObject.transform.position.y,
                                0),
                            Quaternion.identity);

            }
        }
        
    }
}


using UnityEngine;
using System.Collections;
using System.Text;
using System.IO;

public class Done_LevelLoader : MonoBehaviour
{

    public Done_Block block;
    public int block_count = 0;

    // Use this for initialization
    void Start()
    {
        string level = getRandomLevelName();
        //Debug.Log(level);
        LoadLevel(level);
    }

    public string getRandomLevelName()//随机获取地图名称
    {
        int level = Random.Range(1, 5);

        //通过地图名称读取文件夹中的txt
        return "Assets/_Complete-Game/Levels/level_" + level + ".txt";
    }

    /// <summary>
    /// 载入地图
    /// </summary>
    /// <param name="levelName"></param>
    public void LoadLevel(string levelName)
    {
        try
        {
            string line;
            StreamReader reader = new StreamReader(levelName, Encoding.Default);
            using (reader)
            {
                float pos_x = -5f;//初始克隆方块位置
                float pos_y = 5.8f;
                line = reader.ReadLine();
                whil
  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值