基于Unity3D开发的打飞碟小游戏

演示视频: 

打飞碟演示视频

代码仓库:lab7-playingfrisbee · CongWey/3D-Game-Design - 码云 - 开源中国

UML类图:


 一.游戏玩法

1.随机从游戏视角的左下或右下抛射飞碟,玩家鼠标点击即可销毁飞碟;

2.鼠标点击成功销毁会增加游戏分数,游戏一共五轮,每一轮飞碟数量递增;

3.飞碟是刚体,受重力影响做类抛物线运动;

4.不同颜色的飞碟有不同的分数,游戏分数实时显示。

二.对象池

        对象池是一种设计模式,主要用于管理和重用对象,以减少频繁创建和销毁对象所带来的性能开销。其基本原理是在程序运行时维护一个对象的集合(池),当程序需要一个对象时,它会从池中获取一个已存在的对象,而不是新创建一个;当对象不再使用时,它会被返回到池中,以便后续使用。

        本项目中的飞碟工厂类(DiskFactory)就是一种简易的对象池。它预设了若干随机参数的飞碟实体,需要创建时直接从飞碟工厂类中按数量读取即可。

        GetDisk()函数为读取飞碟对象提供了接口,主控制器(FirstController)调用此函数读取相应数量的飞碟。 GetDisk()通过飞碟列表检查是否有已创建的的飞碟实体,若有则直接读取,若无则新建。

        public GameObject GetDisk(int round){
        GameObject disk;
        // 检查有无已创建飞碟,若无则新建,若有则调用
        if(free.Count != 0){
            disk = free[0];
            free.Remove(disk);
        }
        else{
            disk = GameObject.Instantiate(Resources.Load("Prefabs/disk",typeof(GameObject))) as GameObject;
            disk.AddComponent<DiskAttributes>();
        }
        // 随机方向
        disk.transform.localEulerAngles = new Vector3(-rand.Next(40,70),0,0);
        DiskAttributes attri = disk.GetComponent<DiskAttributes>();
        // 随机分数
        attri.score = rand.Next(1,4);
        // 分数影响碟飞碟的参数
        attri.speedX = (rand.Next(20,50) + attri.score + round)*0.2f;
        attri.speedY = (rand.Next(6,12) + attri.score + round)*0.2f;

        if(attri.score == 1){
            disk.transform.localScale = new Vector3(2f, 0.1f, 2f);
            disk.GetComponent<Renderer>().material.color = Color.blue;
        }
        else if(attri.score == 2){
            disk.transform.localScale = new Vector3(2f, 0.1f, 2f);
            disk.transform.localScale += new Vector3(-0.4f, 0, -0.4f);
            disk.GetComponent<Renderer>().material.color = Color.green;
        }
        else if(attri.score == 3){
            disk.transform.localScale = new Vector3(2f, 0.1f, 2f);
            disk.transform.localScale += new Vector3(-0.8f, 0, -0.8f);
            disk.GetComponent<Renderer>().material.color = Color.red;
        }

        // 飞碟的飞入方向
        int direction = rand.Next(1,3);
        if (direction == 1) {
            disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(0, Camera.main.pixelHeight * 0f, 8)));
            attri.speedY =rand.Next(10,15);
        }
        else if (direction == 2) {
            disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(Camera.main.pixelWidth, Camera.main.pixelHeight * 0f, 8)));
            attri.speedX *= -1;
            attri.speedY =rand.Next(10,15);
        }
        used.Add(disk);
        disk.SetActive(true);
        return disk;
    }

三.运动实现

由于内容较多,下列只描述相对重要的代码部分。

1.CCFlyAction

(1)GetSSAction是一个静态方法,用于创建 CCFlyAction的实例并设置其速度属性。

(2)Start() 方法在动作开始时被调用。这里会向每个飞碟施加一个向下的冲量(AddForce),以防止物体“起飞”,保持在一个合理的行为范围内。同时设置重力系数 为 0.4,模拟一定的重力效果。最后设置物体的速度,由X、Y两轴向上的速度构成。

(3)Update()方法在每一帧中被调用。主要负责检查飞碟的激活状态并飞碟判定是否超出了摄像机的视野。如果超出,标记销毁并调用回调通知。

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

public class CCFlyAction : SSAction
{
    public float speedX;
    public float speedY;
    public static CCFlyAction GetSSAction(float x, float y){
        CCFlyAction action = ScriptableObject.CreateInstance<CCFlyAction> ();
        action.speedX = x;
        action.speedY = y;
        return action;
    }
    public override void Start()
    {
        // gameObject.GetComponent<Rigidbody2D>().isKinematic = false;
        Rigidbody2D rb = this.transform.gameObject.GetComponent<Rigidbody2D>();
        rb.velocity = new Vector2(speedX, speedY);
        rb.gravityScale = 0.4f; // 重力系数
        Vector2 force = new Vector2(0, -8);
        rb.AddForce(force, ForceMode2D.Impulse);    // 给予向下的冲量,以防“起飞”
    }

    public override void Update()
    {
        if(this.transform.gameObject.activeSelf == false){
            // Debug.Log("飞碟销毁");
            this.destory = true;
            this.callback.SSActionEvent(this);
            return;
        }

        Vector3 vec3 = Camera.main.WorldToScreenPoint(this.transform.position);
        if(vec3.x <-100 || vec3.x>Camera.main.pixelWidth+100 || vec3.y<-100 || vec3.y>Camera.main.pixelHeight+100){
            // Debug.Log("飞碟出界");
            this.destory= true;
            this.callback.SSActionEvent(this);
            return;
        }
    }
    
}

2.CCActionManager:继承自 SSActionManager 并实现了 ISSActionCallback 接口。这个类主要负责提供管理和执行动作的接口。

3.SSActionManager:主要负责实现游戏循环中的动作管理和执行。

4.FirstController:主控制器类,负责管理游戏的主要逻辑,包括游戏轮次、计时、用户输入处理等。

5.ScoreController:记分员类,负责记录游戏分数。

四.场景布置

        在场景中布置了地面(Ground),并设置其标签为finish。

        在场景中布置了天空盒,并使用了从网络上下载的素材。

在五花八门的游戏分类中,益智游戏是不可或缺的一大板块;而在益智游戏这个分类中,消除合成类游戏又是当之无愧的No.1。从考古级别的《俄罗斯方块》到现在风靡全国的《开心消消乐》,消除合成类游戏经久不衰,并且不断地涌现出新的经典作品,带给我们新的启发和乐趣。作为Unity3D的初级开发者,从头到尾独立完成一款简单的2D棋盘消除合成小游戏是你初级实战的最好选择。既能全面而详细的检验你的基础框架能力、C#编程能力、UGUI适配技巧,又可以在此基础上,较为深入的学习协程方法、DoTween插件和消除合成类的核心算法,一举数得。一言以蔽之,消除合成类游戏不难,但要写好却并不容易。它琐碎的功能逻辑、层出不穷的延时操作以及复杂的状态控制很容易让人顾此失彼,手忙脚乱,最后的结果往往是,费劲九牛二虎之力把功能实现好了,但代码已经乱成一团糟,定位Bug难、扩展新功能难,甚至自己读起来也难。本课程的最大目的,就是帮初级开发者梳理逻辑,写出规范而有条理的代码,避免陷入以上尴尬境地。条理捋清楚了,你就会觉得一切似乎变得简单了,很多地方都会顺理成章。本课程没有什么高深的编程技巧,更没有炫酷的视觉效果,只是一步一步教你如何踏踏实实、稳稳当当的完成一款《简单消消乐》。因此,资深大牛你就别进了,想学高深知识的你就别点了,自认为消除小case、分分钟搞定的高手你也趁早走人。在这门课程里,你能够学到的,只有以下几点:1、如何使用UGUI搭建棋盘游戏的基础阵列;2、如何快速的实现通用的三消逻辑;3、如何使用Dotween插件实现物体的位移、缩放、旋转动画;4、如何熟练的使用协程方法完成延时操作逻辑;5、数组、集合、引用类型、Prefab等基础知识的巩固;6、如何写出规范而有条理的代码;7、益智小游戏的通用模板。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值