经典游戏案例:仿植物大战僵尸

学习目标:仿植物大战僵尸核心玩法实现

游戏画面

项目结构目录

部分核心代码

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


public enum ZombieType
{
    Zombie1,   
    ConeHeadZombie,
    BucketHeadZombie,
}

[Serializable]
public struct Wave
{
    [Serializable]
    public struct Data
    {
        public ZombieType zombieType;
        public uint count;
    }

    public bool isLargeWave;

    [Range(0f,1f)]
    public float percentage;
    public Data[] zombieData;
}


public class GameController : MonoBehaviour
{

    public GameObject zombie1;
    public GameObject BucketheadZombie;
    public GameObject ConeheadZombie;
    private GameModel model;
    public GameObject progressBar;
    public GameObject gameLabel;
    public GameObject sunPrefab;
    public GameObject cardDialog;
    public GameObject sunLabel;
    public GameObject shovelBG;
    public GameObject btnSubmitObj;
    public GameObject btnResetObj;

    public string nextStage;

    public float readyTime;
    public float elapsedTime;
    public float playTime;
    public float sunInterval;
    public AudioClip readySound;
    public AudioClip zombieComing;
    public AudioClip hugeWaveSound;
    public AudioClip finalWaveSound;
    public AudioClip loseMusic;
    public AudioClip winMusic;
    
    public Wave[] waves;

    public int initSun;
    private bool isLostGame = false;

    void Awake()
    {
        model = GameModel.GetInstance();
    }
	void Start ()
	{
        model.Clear();
     
	    model.sun = initSun;
        ArrayList flags=new ArrayList();
	    for (int i = 0; i < waves.Length; i++)
	    {
	        if (waves[i].isLargeWave)
	        {
	            flags.Add(waves[i].percentage);
	        }
	    }
        progressBar.GetComponent<ProgressBar>().InitWithFlag((float[])flags.ToArray(typeof(float)));
	    progressBar.SetActive(false);
        cardDialog.SetActive(false);
        sunLabel.SetActive(false);
        shovelBG.SetActive(false);
        btnResetObj.SetActive(false);
        btnSubmitObj.SetActive(false);
	    GetComponent<HandlerForShovel>().enabled = false;
	    GetComponent<HandlerForPlants>().enabled = false;
        StartCoroutine(GameReady());

    }

   

    Vector3 origin
    {
        get
        {
            return new Vector3(-2f,-2.6f);
        }
    }

    void OnDrawGizmos()
    {
              // DeBugDrawGrid(origin,0.8f,1f,9,5,Color.blue);
    }

    void DeBugDrawGrid(Vector3 _orgin,float x,float y,int col,int row,Color color)
    {
        for (int i = 0; i < col+1; i++)
        {
            Vector3 startPoint = _orgin + Vector3.right*i*x;
            Vector3 endPoint = startPoint + Vector3.up*row*y;
            Debug.DrawLine(startPoint,endPoint,color);
        }
        for (int i = 0; i < row+1; i++)
        {
            Vector3 startPoint = _orgin + Vector3.up * i * y;
            Vector3 endPoint = startPoint + Vector3.right * col * x;
            Debug.DrawLine(startPoint, endPoint, color);
        }
    }



    public void AfterSelectCard()
    {
        btnResetObj.SetActive(false);
        btnSubmitObj.SetActive(false);
        Destroy(cardDialog);
        GetComponent<HandlerForShovel>().enabled = true;
        GetComponent<HandlerForPlants>().enabled = true;
        Camera.main.transform.position=new Vector3(1.1f,0,-1f);
        StartCoroutine(WorkFlow());
        InvokeRepeating("ProduceSun", sunInterval, sunInterval);
    }


    IEnumerator GameReady()
    {
        yield return new WaitForSeconds(0.5f);
        MoveBy move = Camera.main.gameObject.AddComponent<MoveBy>();
        move.offset=new Vector3(3.55f,0,0);
        move.time = 1f;
        move.Begin();
        yield return  new WaitForSeconds(1.5f);
        sunLabel.SetActive(true);
        shovelBG.SetActive(true);
        cardDialog.SetActive(true);
        btnResetObj.SetActive(true);
        btnSubmitObj.SetActive(true);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            model.sun += 50;
        }
        if (!isLostGame)
        {
            for (int row = 0; row < model.zombieList.Length; row++)
            {
                foreach (GameObject zombie in model.zombieList[row])
                {
                    if (zombie.transform.position.x<(StageMap.GRID_LEFT-0.4f))
                    {
                        LoseGame();
                        isLostGame = true;
                        return;
                    }
                    
                }
            }  
        }

    }

    IEnumerator WorkFlow()
    {
        gameLabel.GetComponent<GameTips>().ShowStartTip();
        AudioManager.GetInstance().PlaySound(readySound);
        yield return new WaitForSeconds(readyTime);
        ShowProgressBar();
        AudioManager.GetInstance().PlaySound(zombieComing);

        for (int i = 0; i < waves.Length; i++)
        {
            yield return StartCoroutine(WaitForWavePercentage(waves[i].percentage));
            if (waves[i].isLargeWave)
            {
                StopCoroutine(UpdateProgress());
                yield return StartCoroutine(WaitForZombieClear());
                yield return new WaitForSeconds(3.0f);
                gameLabel.GetComponent<GameTips>().ShowApproachingTip();
                AudioManager.GetInstance().PlaySound(hugeWaveSound);
                yield return new WaitForSeconds(3.0f);
                StartCoroutine(UpdateProgress());
            }
            if (i+1==waves.Length)
            {
                gameLabel.GetComponent<GameTips>().ShowFinalTip();
                AudioManager.GetInstance().PlaySound(finalWaveSound);
            }

            yield return StartCoroutine(WaitForZombieClear());
            CreatZombies(ref waves[i]);
        }

        yield return StartCoroutine(WaitForZombieClear());
        yield return new WaitForSeconds(2f);
        WinGame();

    }

    IEnumerator WaitForZombieClear()
    {
        while (true)
        {
            bool hasZombie = false;
            for (int row = 0; row < StageMap.ROW_MAX; row++)
            {
                if (model.zombieList[row].Count!=0)
                {
                    hasZombie = true;
                    break;
                }
            }
            if (hasZombie)
            {
                yield return new WaitForSeconds(0.1f);
            }
            else
            {
                break;
            }
        }
    }

    IEnumerator WaitForWavePercentage(float percentage)
    {
        while (true)
        {
            if ((elapsedTime/playTime)>=percentage)
            {
                break;
            }
            else
            {
                yield return 0;
            }
        }
    }

    IEnumerator UpdateProgress()
    {
        while (true)
        {
            elapsedTime += Time.deltaTime;  
            progressBar.GetComponent<ProgressBar>().SetProgress(elapsedTime/playTime);          
            yield return 0;
        }
    }

    void ShowProgressBar()
    {
        progressBar.SetActive(true);
        StartCoroutine(UpdateProgress());
    }
   

    void CreatZombies(ref Wave wave)
    {
        foreach (Wave.Data data in wave.zombieData)
        {
            for (int i = 0; i < data.count; i++)
            {
                CreatOneZombie(data.zombieType);
            }
        }
    }

    void CreatOneZombie(ZombieType type)
    {

        GameObject zombie=null;

        switch (type)
        {
            case ZombieType.Zombie1:
                zombie = Instantiate(zombie1);
                break;            
            case ZombieType.ConeHeadZombie:
                zombie = Instantiate(ConeheadZombie);
                break;
            case ZombieType.BucketHeadZombie:
                zombie = Instantiate(BucketheadZombie);
                break;               
        }

        
        int row = Random.Range(0, StageMap.ROW_MAX);      
        zombie.transform.position = StageMap.SetZombiePos(row);
        zombie.GetComponent<ZombieMove>().row = row;
        zombie.GetComponent<SpriteDisplay>().SetOrderByRow(row);
        model.zombieList[row].Add(zombie);
    }

    void ProduceSun()
    {
        float x = Random.Range(StageMap.GRID_LEFT, StageMap.GRID_RIGTH);
        float y = Random.Range(StageMap.GRID_BOTTOM, StageMap.GRID_TOP);
        float startY = StageMap.GRID_TOP + 1.5f;
        GameObject sun = Instantiate(sunPrefab);
        sun.transform.position=new Vector3(x,startY,0);
        MoveBy move = sun.AddComponent<MoveBy>();
        move.offset=new Vector3(0,y-startY,0);
        move.time = (startY - y)/1.0f;
        move.Begin();
    }

    void LoseGame()
    {
        gameLabel.GetComponent<GameTips>().ShowLostTip();
        GetComponent<HandlerForPlants>().enabled = false;
        CancelInvoke("ProduceSun");
        AudioManager.GetInstance().PlayMusic(loseMusic,false);
    }

    void WinGame()
    {
        CancelInvoke("ProduceSun");
        AudioManager.GetInstance().PlayMusic(winMusic, false);
        Invoke("GotoNextStage",3.0f);
    }

    void GotoNextStage()
    {       
        SceneManager.LoadScene(nextStage);
    }
}

下载链接:PlantsVsZombies: 经典游戏:植物大战僵尸

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/742849.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CSS打印设置页眉页脚

之前写过一篇文章CSS实现自动分页打印同时每页保留重复的自定义内容&#xff0c;可以实现window.print()打印时多张页面保留相同的内容&#xff08;如header、footer&#xff09;&#xff0c;但其并不是真正意义上的页眉页脚&#xff0c;footer内容在最后一张页面未撑满时不能置…

Java高级重点知识点-12-Collection、iterator迭代器、泛型

文章目录 Collection集合Iterator迭代器泛型&#xff08;难点&#xff09; Collection集合 集合是java中提供的一种容器&#xff0c;可以用来存储多个数据。 集合框架 单列集合java.util.Collection双列集合java.util.Map 集合类继承体系图&#xff1a; List集合的特点&am…

【大数据】大数据的核心特征与挑战:Volume、Velocity、Variety、Veracity

目录 Volume&#xff1a;海量数据的挑战与机遇 挑战 技术挑战 机遇 Velocity&#xff1a;数据处理的速度与实时性 挑战 技术挑战 机遇 Variety&#xff1a;数据类型的多样性与复杂性 挑战 技术挑战 机遇 Veracity&#xff1a;数据的真实性与质量控制 挑战 技术挑…

【Chapter7】虚拟存储系统,计算机操作系统教程,第四版,左万利,王英

文章目录 [toc]零、前言一、外存资源管理1.1 外存空间划分1.2 外存空间分配1.2.1 空闲块链(慢)1.2.2 空闲块表(UNIX)1.2.3 字位映像图 1.3 进程与外存对应关系 二、虚拟页式存储系统2.1 基本原理2.2 内存页框分配策略2.3 外存块的分配策略2.4 页面调入时机2.5 置换算法2.5.1 最…

Oracle详情数据库索引事务视图触发器分区发生死锁数据字典【Oracle】

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

乐鑫ESP32-WROOM-32E模组设备低功耗控制方案,启明云端乐鑫代理商

在数字化浪潮的推动下&#xff0c;物联网&#xff08;IoT&#xff09;正迅速成为我们日常生活的一部分。而在这个领域中&#xff0c;ESP32-WROOM-32E模组以其卓越的性能和多功能性&#xff0c;成为了开发者和制造商的选择。 ESP32-WROOM-32E模组集成了ESP32-D0WD-V3芯片&#…

宝塔面板部署前端项目

部署前端项目 1 打包自己的项目2 登录宝塔面板3 添加站点4 设置域名5 进入当前站点对应的文件目录中6 上传打包后的文件7 访问网站 1 打包自己的项目 2 登录宝塔面板 点击左侧“网站”菜单进入对应页面 点击“添加站点” 3 添加站点 填写域名&#xff0c;如果没有域名的&am…

重生奇迹MU 谁才是真正的全能职业

重生奇迹MU中&#xff0c;游戏的奥妙就在于职业的选择。不同职业间各有千秋&#xff0c;可远可近&#xff0c;全都是玩家们心中的全能职业。本文就将为你分析重生奇迹MU中的各个职业&#xff0c;为你解答谁才是真正的全能职业。 每次新开一个服务器时&#xff0c;玩家们总会纠结…

为什么不推荐在自动化测试中使用单例模式

简述 尽管在国内大量的代码中使用单例这种简单的方式&#xff0c;但在自动化测试过程中会导致很多问题。因此&#xff0c;在自动化测试中&#xff0c;不推荐使用单例模式。 什么是单例&#xff1f; 《设计模式&#xff1a;可复用面向对象软件的基础》一书&#xff08;通常被称为…

2024地理信息相关专业大学排名

在开始之前&#xff0c;不得不提一下今年福耀科技大学不能招生的遗憾&#xff0c;不知道明年是否能一切准备就绪开始招生呢&#xff1f; 如果这所大学能招生了&#xff0c;不知道它有没有地理信息相关专业呢&#xff1f; 言归正转&#xff0c;我们现在就基于公开资料&#xf…

vue:响应式原理解析,深入理解vue的响应式系统

一、文章秒读 vue的响应式系统核心有两个&#xff0c;简单描述就是&#xff1a; 1.在数据变化时重新render依赖相关函数&#xff08;组件&#xff09;。 2.在vue2和vue3中分别使用Object.defineProperty和Proxy进行对象属性的读写。 数据变化时&#xff1a; 二、什么是响应…

解决宝塔linux面板 - 404 Not Found(Nginx)方法

宝塔Linux面板后台登录提示404 Not Found Nginx如何解决&#xff1f;码笔记&#xff1a;这是因为BT面板丢失了安全登录入口&#xff0c;如下图&#xff1a; 宝塔404 Not Found nginx 解决方法&#xff1a; 1、先SSH远程服务器 2、然后执行命令 bt 14 重新获取宝塔面板URL地址安…

Linux安装frp实现内网穿透

Linux运维工具-ywtool 目录 一. 简介二.代理类型三.frp支持的Linux的架构四.安装1.准备工作2.配置frp服务器端(a)下载安装包(b)解压安装包(c)修改配置文件(d)启动服务端 3.配置frp客户端(a)下载安装包并修改配置文件(b)启动客户端 4.测试连接 五.其他1.多端口穿透(a)服务端(b)客…

wireshark工具获取设备IP地址

背景&#xff1a; 一个网口抓包工具&#xff0c;主要是升级XX设备时候不知道网口的ip地址。每次需要一个一个试&#xff0c;比较麻烦。 使用步骤&#xff1a; 1、连接好XX设备与笔记本&#xff0c;在网络连接里面找到以太网&#xff0c;没有出现红色X号&#xff0c;表示网线连…

【道合顺展会预告】2024国际传感器仪器仪表物联网长沙展览会!

传感器技术作为万物互联的基石&#xff0c;正以前所未有的速度驱动着全球各行各业的转型升级。在此背景下&#xff0c;2024国际传感器&仪器仪表&物联网展览会将于6月28日至30日在长沙盛大启幕&#xff0c;道合顺传感将携公司最新技术及科研成果参加展览会&#xff0c;并…

数据库自动备份到gitee上,实现数据自动化备份

本人有个不太好的习惯&#xff0c;每次项目的数据库都是在线上创建&#xff0c;Navicat 连接线上数据库进行处理&#xff0c;最近有一个项目需要二次升级&#xff0c;发现老项目部署的服务器到期了&#xff0c;完蛋&#xff0c;数据库咩了&#xff01;&#xff01;&#xff01;…

开源模型应用落地-FastAPI-助力模型交互-WebSocket篇(一)

一、前言 使用 FastAPI 可以帮助我们更简单高效地部署 AI 交互业务。FastAPI 提供了快速构建 API 的能力,开发者可以轻松地定义模型需要的输入和输出格式,并编写好相应的业务逻辑。 FastAPI 的异步高性能架构,可以有效支持大量并发的预测请求,为用户提供流畅的交互体验。此外,F…

在Qt中,直接include <moc_xxxxx.cpp> 为什么不会出现符号冲突的错误?

在逛Qt官方社区的时候看到这样一个帖子&#xff1a; https://forum.qt.io/topic/117973/how-does-include-moc_-cpp-work 大概的意思是moc_xxx.cpp如果已经被编译器编译&#xff0c;那么在另一个cpp文件中include同一个moc_xxx.cpp应该出现符号冲突才对&#xff0c;但是Qt却能正…

关于如何更好管理好数据库的一点思考

本文尝试从数据库设计理论、ER图简介、性能优化、避免过度设计及权限管理方面进行思考阐述。 一、数据库范式 以下通过详细的示例说明数据库范式的概念&#xff0c;将逐步规范化一个例子&#xff0c;逐级说明每个范式的要求和变换过程。 示例&#xff1a;学生课程登记系统 初始…

提效优化:企业IT人员视角下的SD-WAN经验分享

我是公司IT支持人员&#xff0c;主要职责是确保公司的网络系统运行顺畅&#xff0c;让同事们能够顺利地完成他们的工作。随着公司业务的扩展和远程办公的普及&#xff0c;我工作中面临的挑战也日益严峻。 永无止境的问题流是我们IT人员日常工作中最为常见的现象。从“网络怎么这…