当前位置: 首页 > news >正文

【Unity游戏】——1.俄罗斯方块

搭建场景

使用任意方块、纯色瓦片或者其他图形作为背景,设置其大小与目标大小一致或者更大,设置左下角为场景顶点,并放置在(0,0)处。调整摄像机至合适位置。

制作游戏预制体

每个方块预制体包含有4个小方块以及一个围绕旋转的节点。先设置一个小方块的坐标为(0,0),在此基础上摆放其他小方块,设置一个合适的旋转节点。

脚本

思路

实现方块自由下落        -> Block.cs

实现方块左右移动、加速下落、旋转        -> Block.cs

限制方块移动范围         -> Block.cs

把方块加入到场景中        -> Board.cs

禁用该方块的脚本       -> Block.cs

检测方块是否满行         -> Board.cs

满行则消除该行         -> Board.cs

下移该行上面的方块        -> Board.cs

实现代码

Block.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum MoveType
{Move,Rotate,MoveDown,MoveRight,MoveLeft,Stop
}public class Block : MonoBehaviour
{private float timer = 0;private float moveSpeed = 0.8f;private float moveDownSpeed = 0.2f;private bool isCanMove = true;private Transform rotatePoint = null;private MoveType moveType = MoveType.Move;private void Start(){Init();}private void Update(){if (isCanMove){if (Input.GetKeyDown(KeyCode.W)){controlMove(MoveType.Rotate);}if (Input.GetKeyDown(KeyCode.S)){controlMove(MoveType.MoveDown);}if (Input.GetKeyUp(KeyCode.S)){controlMove(MoveType.Move);}if (Input.GetKeyDown(KeyCode.A)){controlMove(MoveType.MoveLeft);}if (Input.GetKeyDown(KeyCode.D)){controlMove(MoveType.MoveRight);}TryMove(MoveType moveType);}}// 初始化方块public void Init(){// 初始化旋转点rotatePoint = transform.GetChild(transform.childCount - 1);}// 改变移动类型private void controlMove(MoveType moveType){if (isCanMove){this.moveType = moveType;}}// 方块移动private void TryMove(MoveType moveType = MoveType.Move){switch (moveType){case MoveType.Move:MoveFall();break;case MoveType.Rotate:Rotate();break;case MoveType.MoveDown:MoveDown();break;case MoveType.MoveLeft:MoveLeft();break;case MoveType.MoveRight:MoveRight();break;case MoveType.Stop:Stop();break;}}// 检查方块是否可以移动private bool IsCanMove(){// 检查是否超出边界for (int i = 0; i < transform.childCount - 1; i++){int roundX = Mathf.RoundToInt(transform.GetChild(i).position.x);int roundY = Mathf.RoundToInt(transform.GetChild(i).position.y);if (roundY < 0 || roundX < 0 || roundX >= 10){return false;}// 检查是否与其他方块重叠if (Board.grid[roundX, roundY] != null){return false;}}return true;}// 方块下落private void MoveFall(){timer += Time.deltaTime;if (timer >= moveSpeed){transform.position += Vector3.down;if (!IsCanMove()){transform.position -= Vector3.down;moveType = MoveType.Stop;}timer = 0;}}// 方块加快下落private void MoveDown(){timer += Time.deltaTime;if (timer >= moveDownSpeed){transform.position += Vector3.down;if (!IsCanMove()){transform.position -= Vector3.down;moveType = MoveType.Stop;}timer = 0;}}// 方块向左移动private void MoveLeft(){transform.position += Vector3.left;if (!IsCanMove()){transform.position -= Vector3.left;}moveType = MoveType.Move;}// 方块向右移动private void MoveRight(){transform.position += Vector3.right;if (!IsCanMove()){transform.position -= Vector3.right;}moveType = MoveType.Move;}// 方块旋转private void Rotate(){transform.RotateAround(rotatePoint.position, Vector3.forward, -90);if (!IsCanMove()){transform.RotateAround(rotatePoint.position, Vector3.forward, 90);}moveType = MoveType.Move;}// 方块停止private void Stop(){isCanMove = false;// Debug.Log("Stop");for (int i = 0; i < transform.childCount - 1; i++){int roundX = Mathf.RoundToInt(transform.GetChild(i).position.x);int roundY = Mathf.RoundToInt(transform.GetChild(i).position.y);// 添加方块到Board中Board.Instance.AddBlock(roundX, roundY, transform.GetChild(i));}// 检查游戏是否结束Debug.Log("检查游戏是否结束!");Board.Instance.IsGameOver(transform);// 消除行Debug.Log("检查是否消除行!");Board.Instance.CheckLine();// 生成新方块Board.Instance.SpawnBlock();enabled = false;}
}

Board.cs

这里继承了一个单例模式的泛型类,简而言之就是这里需要创建单例模式。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Board : SingletonMono<Board>
{public static int width = 10;public static int height = 15;public static Transform[,] grid = new Transform[width, height + 5];private int randIndex;       // 随机生成方块的索引private float timer = 0f;         // 计时器private float countdown = 1f;// 倒计时private GameObject generatorPoint;private Vector3 createPos;private GameObject[] blocks;private List<GameObject> blockList;protected override void Awake(){base.Awake();Init();}private void Start(){// Debug.Log(blockList.Count);SpawnBlock();}private void Update(){timer += Time.deltaTime;if (timer >= countdown){ClearNullBlock();timer = 0;}}// 初始化private void Init(){generatorPoint = new GameObject();createPos = new Vector3(width / 2 - 1, height + 1, 0);generatorPoint.transform.position = createPos;// generatorPoint.transform.parent = transform;blockList = new List<GameObject>();blocks = Resources.LoadAll<GameObject>("Prefabs/Block");foreach (GameObject block in blocks){blockList.Add(block);}}// 生成方块public void SpawnBlock(){randIndex = Random.Range(0, blockList.Count);if (blockList[randIndex].GetComponent<Block>() == null){blockList[randIndex].AddComponent<Block>();}Instantiate(blockList[randIndex], generatorPoint.transform.position, Quaternion.identity, transform);}// 添加方块public void AddBlock(int x, int y, Transform block){grid[x, y] = block.transform;}// 检查游戏是否结束public void IsGameOver(Transform block){if (block.position.y >= createPos.y){Debug.Log("Game Over");}}// 检查是否有可以消除的行public void CheckLine(){for (int i = height - 1; i >= 0; i--){if (IsLineFull(i)){RemoveLine(i);}}}// 检查行是否满private bool IsLineFull(int y){for (int i = 0; i < width; i++){if (grid[i, y] == null){return false;}}return true;}// 消除方块public void RemoveLine(int x){for (int i = 0; i < width; i++){Destroy(grid[i, x].gameObject);grid[i, x] = null;}MoveBlockdown(x);}// 下移方块public void MoveBlockdown(int h){for (int i = h; i < height; i++){for (int j = 0; j < width; j++){if (grid[j, i] != null){grid[j, i - 1] = grid[j, i];grid[j, i] = null;grid[j, i - 1].position += Vector3.down;}}}}// 清理空对象private void ClearNullBlock(){for (int i = 1; i < transform.childCount; i++){if (transform.GetChild(i).childCount == 1){Destroy(transform.GetChild(i).gameObject);}}}
}

了解更多

【日志】unity俄罗斯方块(一)——边界限制检测-CSDN博客【日志】unity俄罗斯方块(二)——方块碰撞检测-CSDN博客

http://www.dtcms.com/a/303123.html

相关文章:

  • Apache Ignite的分布式计算(Distributed Computing)
  • 基于Milvus和BGE-VL模型实现以图搜图
  • 第17章——多元函数积分学的预备知识
  • odoo欧度小程序——修改用户和密码
  • RabbitMQ+内网穿透远程访问教程:实现异地AMQP通信+Web管理
  • 基于springboot的大创管理系统(源码+论文+开题报告)
  • 项目任务如何分配?核心原则
  • 银行个人贷款接受度分析
  • el-upload开启picture形式列表展示上传的非图片文件自定义缩略图
  • 网络层描述
  • Leetcode_349.两个数组的交集
  • Word VBA快速制作试卷(2/2)
  • 【华为机试】5. 最长回文子串
  • 学习人工智能所需知识体系及路径详解
  • 记录几个SystemVerilog的语法——随机
  • 五自由度磁悬浮轴承转子:基于自适应陷波器的零振动攻克不平衡质量扰动的终极策略
  • (45) QT 提供了一个功能,以同步现代操作系统的编辑功能,在标题栏上显示 * 占位符,以显示窗体上发生了未被保存的修改
  • 三维插件 Forest 深度解析:打造高效逼真的自然环境
  • 命令执行漏洞
  • 计算机毕设分享-基于SpringBoot的健身房管理系统(开题报告+前后端源码+Lun文+开发文档+数据库设计文档)
  • USRP-X440 雷达目标发生器
  • 深入解析 Java Stream 设计:从四幕剧看流水线设计与执行机制
  • 对于ui=f(state)的理解(react)
  • Redis四种GetShell方式完整教程
  • 使用Docker在Rocky Linux 9.5上在线部署LangFlow
  • 【STM32编码器接口测速】实现测速功能
  • 删除二维特征图中指定区域的样本
  • linux系统----Ansible中的playbook简单应用
  • 【Java EE】多线程-初阶-线程的状态
  • java里List链式编程