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

news2025/3/13 13:48:22

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

游戏画面

项目结构目录

部分核心代码

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/1850856.html

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

相关文章

(2024)豆瓣电影详情页内容爬虫详解和源码

&#xff08;2024&#xff09;豆瓣电影详情页内容爬虫详解和源码 这是一个Python爬虫程序&#xff0c;用于抓取豆瓣电影详情页面如https://movie.douban.com/subject/1291560/的数据。它首先发送GET请求&#xff0c;使用PyQuery解析DOM&#xff0c;然后根据<br>标签分割H…

C语言第17篇:预处理详解

1、预定义符号 C语言设置了一些预定义符号&#xff0c;可以直接使用。预定义符号也是在预处理期间处理的。 __FILE__ //进行编译的源文件 __LINE__ //文件当前的行号 __DATE__ //文件被编译的日期 __TIME__ //文件被编译的时间 __STDC__ //如果编译器遵循ANSI…

LaTeX中添加矩阵分块虚线并设置虚线疏密

对于大型矩阵&#xff0c;有时需要添加分块虚线。 方法为使用arydshln宏包&#xff0c;然后在array环境中设置虚线。需要注意的是&#xff0c;使用矩阵环境需要搭配amsmath宏包使用&#xff0c;且需放在amsmath宏包之后。即导言区设置为 \usepackage{amsmath} \usepackage{ary…

人人讲视频如何下载

一、工具准备 1.VLC media player 2.谷歌浏览器 二、视频下载 1.打开人人讲网页&#xff0c;需要下载的视频 谷歌浏览器打开调试窗口 搜索m3u8链接 拷贝到VLCplayer打开网络串流方式打开测试是否能正常播放 2.下载视频 能正常播放后&#xff0c;切换播放为转换选择mp4格式…

【CPP】归并排序

目录 1.归并排序简介代码分析归并的非递归形式 1.归并排序 归并排序&#xff08;MERGE-SORT&#xff09; 是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide andConquer&#xff09;的一个非常典型的应用。 将已有序的子序列合并&#xff0c;得到…

扩散模型 GLIDE:35 亿参数的情况下优于 120 亿参数的 DALL-E 模型

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#x…

com域名注册多少钱

COM域名注册价格视具体注册商而定&#xff0c;不同的注册商可能会有不同的收费标准。一般来说&#xff0c;COM域名注册价格在10美元到20美元之间&#xff0c;可根据不同的需求选择注册时间的长短&#xff0c;从1年到10年等不同时间段的注册费用也不同。以下是关于COM域名注册价…

Python爬虫学习 | Scrapy框架详解

一.Scrapy框架简介 何为框架&#xff0c;就相当于一个封装了很多功能的结构体&#xff0c;它帮我们把主要的结构给搭建好了&#xff0c;我们只需往骨架里添加内容就行。scrapy框架是一个为了爬取网站数据&#xff0c;提取数据的框架&#xff0c;我们熟知爬虫总共有四大部分&am…

【LLM之KG】KoPA论文阅读笔记

研究背景 知识图谱补全&#xff08;KGC&#xff09;是通过预测知识图谱中缺失的三元组来完善知识图谱的信息。传统方法主要基于嵌入和预训练语言模型&#xff0c;但这些方法往往忽视了知识图谱的结构信息&#xff0c;导致预测效果不佳。 研究目标 本文的研究目标是探索如何将…

海外短剧系统如何征服观众心

海外短剧系统要征服观众的心&#xff0c;需要综合考虑多个方面。 1、紧凑的剧情设计&#xff1a; 短小精悍&#xff1a;海外短剧通常每集时长不超过半小时&#xff0c;甚至有的仅有几分钟。这种紧凑的剧情设计让观众能够在短时间内迅速沉浸在故事中&#xff0c;无需花费大量时间…

分页查询前端对接

文章目录 添加角色修改角色当点击修改按钮后,那么就会弹出对话框,所以要设置显示为true点击修改的时候就是 要显示对话框 制作用户管理页面开发后端接口用户查询前端整合新增接口功能实现修改 添加角色 首先添加 添加表单的组件 那么总结一下 就是使用 组件 然后再使用变量接…

docker简单快速使用上手

1.Docker是什么&#xff1f; Docker 是一个开源的容器化平台&#xff0c;主要用于开发、运输和运行应用程序。它通过提供轻量级的虚拟化机制&#xff0c;使得开发者可以在一个隔离的环境中运行和管理应用程序及其依赖项。Docker 的核心组件包括镜像&#xff08;Image&#xff…

FOC方案大合集!

获取链接&#xff01;&#xff01;&#xff01; 本次小编给大家带来了一份FOC的方案大合集。此套方案是基于峰岹科技FU68系列MCU的系列方案&#xff0c;包含常用的无感&#xff0c;有感无刷电机的应用&#xff0c;每份方案都包含了原理图&#xff0c;PCB&#xff0c;代码文件&…

游戏大厂“脱钩”安卓商店: 独立渠道TapTap们能否渔利

一纸公告将游戏厂商与渠道的博弈再度摆上了台面。 近日&#xff0c;腾讯控股旗下手游《地下城与勇士&#xff1a;起源》&#xff08;下称“DNF手游”&#xff09;运营团队发布公告称&#xff0c;自6月20日起&#xff0c;DNF手游将不再上架部分安卓平台的头部应用商店。 下架的…

Google Vortex流式存储引擎分析

作者&#xff1a;archimekai&#xff0c;转载请注明出处 参考文献&#xff1a; Edara, P., Forbesj, J., & Li, B. (2024). Vortex: A Stream-oriented Storage Engine For Big Data Analytics. Companion of the 2024 International Conference on Management of Data, 17…

ClickHouse 24.5.3:全面解析与RPM单节点轻松部署!

简介 ClickHouse是由俄罗斯的Yandex公司开发的开源列式数据库管理系统。它最早于2016年开源&#xff0c;主要用于实时数据分析。ClickHouse通过列存储、向量化执行、并行计算等技术&#xff0c;实现了对大规模数据集的快速查询和分析&#xff0c;特别适合实时数据分析和商业智能…

LayoutSystem布局系统

简介: LayoutSystem,是UGUI中由CanvasUpdateSystem发起(m_LayoutRebuildQueue中大部分都是LayoutRebuilder)的关于布局排列的处理系统。 类图: 布局过程 核心代码讲解: LayoutRebuilder

001.VMware Workstation Pro虚拟平台安装

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…

探秘企业成功的秘密武器:这个知识库搭建攻略你必须知道

在数字化浪潮中,你的企业还在用传统的信息管理方式吗?别落后了!最新的企业知识库搭建攻略来了,它将是你提升企业竞争力、创新能力和员工效率的强力工具。让我们一起探索如何构建自己的知识王国,解锁企业成功的秘诀! 一、为什么你的企业需要立刻行动搭建知识库? 信息孤…

GWO-CNN-SVM,基于GWO灰狼优化算法优化卷积神经网络CNN结合支持向量机SVM数据分类(多特征输入多分类)

GWO-CNN-SVM&#xff0c;基于GWO灰狼优化算法优化卷积神经网络CNN结合支持向量机SVM数据分类(多特征输入多分类) 1. GWO灰狼优化算法 灰狼优化算法&#xff08;Grey Wolf Optimizer, GWO&#xff09;是一种启发式优化算法&#xff0c;模拟了灰狼群体的社会行为&#xff0c;包…