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

news2024/11/25 2:32:02

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

游戏画面

项目结构目录

部分核心代码

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: 经典游戏:植物大战僵尸

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字图像分析(第一部分)

文章目录 第2章 图像数字化数字化采样与量化像素的邻域像素的距离图像采集网络**离散直线性**距离变换**第3章 图像变换可分离和正交图像变换2D DFT变换及其本质**哈达玛变换KL变换(PCA)第4章 形态学二值形态学膨胀和腐蚀开启和闭合击中-击不中变换二值形态学实用算法噪声滤除目…

DWC USB2.0协议学习1--产品概述

本章开始学习记录DWC_otg控制器&#xff08;新思USB2.0&#xff09;的特点、功能和应用。 新思USB 2.0 IP主要有两个文档需要参考&#xff1a; 《DesignWare Cores USB 2.0 Hi-Speed On-TheGo (OTG) Data book》 《DesignWare Cores USB 2.0 Hi-Speed On-TheGo (OTG) Progra…

数值分析笔记(三)函数逼近

最佳平方逼近 函数逼近是使用一种简单易算的函数来近似表示一个复杂函数。 该问题可转化为求解线性方程组 G n C F n ​ G_{n}CF_{n}​ Gn​CFn​​ 其中&#xff0c;系数 C ( c 0 , c 1 , ⋯ , c n ) T , F n ( ( f , φ 0 ) , ( f , φ 1 ) , ⋯ , ( f , φ n ) ) T C(c…

私域电商的新篇章:构建深度连接与高效生态

大家好&#xff0c;我是电商领域的探索者&#xff0c;今天我想和大家分享关于私域电商的一些心得与洞见。在这个数字化飞速发展的时代&#xff0c;如何构建与用户之间更为紧密、深入的连接&#xff0c;以及如何通过私域生态来挖掘用户的更大价值&#xff0c;成为了我们关注的焦…

Studio One 6.6.2中文破解版安装图文激活教程

Studio One 6.6.2中文破解版做为新生代音乐工作站&#xff0c;凭借更低的价格和完备的功能&#xff0c;获得了音乐人和直播行业工作者的青睐&#xff0c;尤其是对硬件声卡的适配支持更好&#xff0c;特别适合用来配合线上教学和电商带货。 最近网上出现不少关于StudioOne不能用…

springboot民宿信息管理系统-计算机毕业设计源码08818

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对民宿信息管理系统等问题&#xff0c;对民宿…

Nuxt3 的生命周期和钩子函数(一)

title: Nuxt3 的生命周期和钩子函数&#xff08;一&#xff09; date: 2024/6/25 updated: 2024/6/25 author: cmdragon excerpt: 摘要&#xff1a;本文是关于Nuxt3的系列文章之一&#xff0c;主要探讨Nuxt3的生命周期和钩子函数&#xff0c;引导读者深入了解其在前端开发中…

Windows server 由于没有远程桌面授权服务器可以提供许可证,远程会话连接已断开。

问题现象&#xff1a; 解决办法 临时远程方式1: 打开 mstsc 时带上 /admin 等参数&#xff0c;如下图所示&#xff1a; 使用“mstsc /admin /v:目标ip”来强制登录服务器&#xff0c;但只能是管理员身份。 远程方式2&#xff1a; 通过VM远程登陆系统后&#xff0c;运行输入R…

如何将本地的Django项目部署到阿里云服务器上?

场景&#xff1a;在本地的pycharm上已经写好了一个Django架构的网站&#xff0c;现在要把它放到公网上 一、阿里云服务器 选择云服务器ECS&#xff0c;新用户可以免费使用三个月 购买时选择预装宝塔面板 买好后&#xff0c;进入云服务器控制台 重置实例密码 远程连接至服务…

【ACM出版】第13届亚洲膜计算会议(ACMC2024)暨 2024年机器学习、模式识别与自动化工程国际学术会议(MLPRAE 2024,8月7日-9)

第13届亚洲膜计算会议&#xff08;ACMC2024&#xff09;暨2024年机器学习、模式识别与自动化工程国际学术会议(MLPRAE 2024) 将于2024年8月7日-9日在新加坡举行。它致力于为机器学习、模式识别与自动化工程领域的专家和学者之间的学术交流创造一个平台。 会议的理念是让来自世…

JVM专题十:JVM中的垃圾回收机制

在JVM专题九&#xff1a;JVM分代知识点梳理中&#xff0c;我们主要介绍了JVM为什么采用分代算法&#xff0c;以及相关的概念&#xff0c;本篇我们将详细拆分各个算法。 垃圾回收的概念 垃圾回收&#xff08;Garbage Collection&#xff0c;GC&#xff09;确实是计算机编程中的…

视频录制软件哪个好用?5款简单好用软件推荐

在我们的日常生活中&#xff0c;都有哪些好用的视频录制软件&#xff1f;在很多场合中我们都会用电脑记录下重要的时刻。比如&#xff0c;在电脑上听老师讲解一道难题的方法时&#xff0c;怕自己会忘记&#xff0c;想要录制下来进行重复的观看。这时&#xff0c;选择一款好用的…

震惊!CURRENT_TIMESTAMP不能乱用

事情发生在签到和查询签到记录. 设置mysql时间默认值为CURRENT_TIMESTAMP可以随系统生成默认时间戳,即生成该数据的时间戳, 但是有些特殊场景要避免由mysql给我们生成默认时间: 1、首先签到成功之后返回给前端, 2、前端收到执行成功之后立马去查询签到记录, 3、发现并没有…

【软件工具】Xshell安装教程

1、安装软件&#xff1a;Xshell-5.0.1337p.exe&#xff0c;双击安装即可&#xff0c;可以选择安装到D盘&#xff1b; 2、在D盘安装完成后&#xff0c;将文件nslicense.dll拷贝到对应的安装目录下&#xff1b; 3、打开快捷方式即可打开应用软件。

“代码规范”这样做【高级前端必备软技能之一】

✨在前端开发领域&#xff0c;良好的代码规范是团队协作、项目可维护性的基石。最近在梳理我们团队关于代码规范相关的一些文档&#xff0c;顺便给大家分享一下我们是从哪些方面入手来从一个草台班子&#xff0c;到开发规范的高效团队。 ✨本文旨在提供一份详尽的前端代码规范指…

Linux的免交互

交互&#xff1a;我们发出指令控制程序的运行&#xff0c;程序在接收到指令之后按照指令的效果做出对应的反应。 免交互&#xff1a;间接的通过第三方的方式把指令传送给程序&#xff0c;不用直接的下达指令。 1、here document免交互 ere document免交互&#xff1a;是命令…

Studying-代码随想录训练营day20| 235.二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

第二十天&#xff0c;二叉树part07&#xff0c;二叉树搜索树加油加油&#x1f4aa; 目录 235.二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点 拓展&#xff1a;普通二叉树的删除方式 总结 235.二叉搜索树的最近公共祖先 文档讲解&…

在FlowUs息流,让知识库为你所用|如何打造个人知识库|如何打造企业知识库

&#x1f389; 在 FlowUs 的世界中&#xff0c;知识绽放出无限的可能&#xff01;&#x1f680; 在当今信息爆炸的时代&#xff0c;知识的更新换代速度极快&#xff0c;我们每天都面临着海量的信息冲击。拥有一个属于自己的知识库变得至关重要。 首先&#xff0c;打造自己的知…

Linux_应用篇(27) CMake 入门与进阶

在前面章节内容中&#xff0c;我们编写了很多示例程序&#xff0c;但这些示例程序都只有一个.c 源文件&#xff0c;非常简单。 所以&#xff0c;编译这些示例代码其实都非常简单&#xff0c;直接使用 GCC 编译器编译即可&#xff0c;连 Makefile 都不需要。但是&#xff0c;在实…

解决IMX6ULL GPIO扩展板PWM7/8中的pwm0/period后卡死问题

前言 本篇文章主要是记录解决百问网论坛上面设置 IMX6ULL GPIO扩展板PWM7/8中的pwm0/period后卡死问题&#xff0c;如下图&#xff1a; 一、查看原理图&#xff0c;找出对应引脚 在这里我们如何确定哪个扩展口中的引脚输出PWM波呢&#xff1f;我们可以通过查看原理图。 查看…