【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.pswp.cn/web/90903.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/90903.shtml

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

相关文章

【C++进阶】---- 二叉搜索树

1.二叉搜索树的概念 ⼆叉搜索树⼜称⼆叉排序树&#xff0c;它或者是⼀棵空树&#xff0c;或者是具有以下性质的⼆叉树: • 若它的左⼦树不为空&#xff0c;则左⼦树上所有结点的值都⼩于等于根结点的值 • 若它的右⼦树不为空&#xff0c;则右⼦树上所有结点的值都⼤于等于根结…

基于 OpenCV 与 sklearn 的数字识别:KNN 算法实践

在计算机视觉领域&#xff0c;数字识别是一个经典问题&#xff0c;广泛应用于邮政编码识别、车牌识别等场景。本文将介绍如何使用 OpenCV 进行图像处理&#xff0c;并结合 KNN&#xff08;K 近邻&#xff09;算法实现数字识别&#xff0c;同时对比 OpenCV 内置 KNN 与 scikit-l…

利用径向条形图探索华盛顿的徒步旅行

利用径向条形图探索华盛顿的徒步旅行 import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np import pandas as pdfrom matplotlib.cm import ScalarMappable from matplotlib.lines import Line2D from mpl_toolkits.axes_grid1.inset_locator impor…

火狐浏览器中国特供版关闭,如何下载 Firefox 国际版?如何备份数据?

火狐浏览器中国特供版关闭&#xff0c;如何下载 Firefox 国际版&#xff1f;如何备份数据&#xff1f;各位火狐老用户注意了&#xff01;7 月 27 日北京谋智火狐正式发布公告&#xff1a;2025 年 9 月 29 日 24:00 起&#xff0c;中国特供版账户服务将彻底关闭&#xff0c;所有…

C语言操作符详解:从基础到进阶

在C语言中&#xff0c;操作符是构建表达式的基础&#xff0c;掌握各类操作符的用法、优先级及特性&#xff0c;对写出高效且正确的代码至关重要。本文将系统梳理C语言操作符的核心知识点&#xff0c;包含实例代码与详细解析&#xff0c;助你彻底搞懂操作符。 1. 操作符的分类 C…

鸿蒙平台运行Lua脚本

1. 目标 使用 rust 在移动端实现 Lua 脚本的运行。 2. 核心步骤 [Rust Host App]│├── [mLua VM] (通过 mlua 或 rlua 库嵌入)│ ├── 独立Lua状态&#xff08;隔离执行&#xff09;│ ├── 受限标准库&#xff08;禁用危险函数&#xff09;│ └── 内存/CPU限…

【Ubuntu】发展历程

Ubuntu 是一个基于 Debian 的 Linux 发行版&#xff0c;由 Canonical 公司开发和维护。它以其易用性、稳定性和强大的社区支持而著称。以下是 Ubuntu 从发布以来的主要版本和发展历程&#xff1a;1. Ubuntu 4.10 "Warty Warthog" (2004)发布日期&#xff1a;2004年10…

k8s下springboot-admin 监控服务部署,客户端接入

踩坑及解决以下问题 1、客户端监控信息不显示,需要暴露监控检查接口路径 2、服务端不显示客户端日志,需要启用日志,并指定日志路径 3、解决在k8s下,客户端多实例注册id相同,如2个实例只显示一个 整体架构 springboot-admin 由服务端和客户端组成 服务端负责 1、提供 We…

git删除远程分支和本地分支

1. git删除远程分支 git push origin --delete [branch_name]2. 删除本地分支 2.1 git branch -d 会在删除前检查merge状态&#xff08;其与上游分支或者与head&#xff09;。 git branch -d [branch_name] 2.2 git branch -D 直接删除 git branch -D 是 git branch --delete…

Go 的时间包:理解单调时间与挂钟时间

Go 的时间包&#xff1a;理解单调时间与挂钟时间 &#x1f4c5; 引言 Go 语言自版本 1.9 起在 time.Time 中同时支持 “挂钟时间&#xff08;wall‑clock&#xff09;” 和 “单调时间&#xff08;monotonic clock&#xff09;”&#xff0c;用于分别满足时间戳与时间间隔测量…

Android启动时间优化大全

1 修改Android mksh默认的列长度 不修改这个参数&#xff0c;adb shell后&#xff0c;输入超过80个字符&#xff0c;就不能看到完整的命令行。external/mksh/src/sh.h EXTERN mksh_ari_t x_cols E_INIT(80); EXTERN mksh_ari_t x_lins E_INIT(24);2 Kernel优化 2.1 内核驱动模块…

matplotlib.pyplot: 底层原理简析与进阶技巧

文章目录 1 底层实现原理 1.1 核心架构 1.1 渲染流程 2 基础用法 2.1 基本绘图 2.2 多子图系统 2.3 高阶用法 2.3.1 自定义Artist对象 2.3.2 高级动画技术 2.3.3 事件处理系统 2.3.4 混合渲染技术 3 性能优化技巧 4 扩展模块 5 总结 5.1 底层原理关键点 5.2 进阶技巧 1 底层实现…

深入理解现代前端开发中的 <script type=“module“> 与构建工具实践

引言&#xff1a;模块化开发的演进在早期的前端开发中&#xff0c;JavaScript 缺乏原生的模块化支持&#xff0c;开发者不得不依赖 IIFE&#xff08;立即调用函数表达式&#xff09;或第三方库&#xff08;如 RequireJS&#xff09;来实现代码组织。随着 ES6&#xff08;ES2015…

yolo--qt可视化开发

qt5可能不支持我们的cuda版本&#xff0c;改用qt6 YOLO11QT6OpencvC训练加载模型全过程讲解_yolov11 模型转换成opencv c模型-CSDN博客 下面是qt5版本的案例&#xff0c;和yolo及cuda有冲突 安装qt 切换到虚拟环境&#xff0c;例如pyqt&#xff0c;conda activate pyqt pip …

SQL性能优化

show [session|global] status : 查看服务器状态 show global status like Com_ : 查看各种语句的执行次数 开启慢查询: 在 MySQL 配置文件&#xff08;/etc/my.cnf&#xff09;配置: #开启MySQL慢日志查询开关 slow_query_log1 #设置慢日志的时间为2秒&#xff0c;SQL语句执…

ctfshow pwn40

目录 1. 分析程序 2. 漏洞编写 3. 漏洞验证 1. 分析程序 首先检查程序相关保护&#xff0c;发现程序为32位且只开启了一个NX保护 checksec pwn 使用IDA进行逆向分析代码&#xff0c;查看漏洞触发点&#xff1a; 在main函数中&#xff0c;有一个ctfshow函数&#xff0c;这里…

SQL173 店铺901国庆期间的7日动销率和滞销率

SQL173 店铺901国庆期间的7日动销率和滞销率 SQL题解&#xff1a;店铺动销率与滞销率计算 关键&#xff1a;只要当天任一店铺有任何商品的销量就输出该天的结果&#xff0c;即使店铺901当天的动销率为0。 潜台词&#xff1a;​输出逻辑与店铺901的销售情况无关&#xff0c;只取…

PytorchLightning最佳实践基础篇

PyTorch Lightning&#xff08;简称 PL&#xff09;是一个建立在 PyTorch 之上的高层框架&#xff0c;核心目标是剥离工程代码与研究逻辑&#xff0c;让研究者专注于模型设计和实验思路&#xff0c;而非训练循环、分布式配置、日志管理等重复性工程工作。本文从基础到进阶&…

Apache Flink 实时流处理性能优化实践指南

Apache Flink 实时流处理性能优化实践指南 随着大数据和实时计算需求不断增长&#xff0c;Apache Flink 已经成为主流的流处理引擎。然而&#xff0c;在生产环境中&#xff0c;高并发、大吞吐量和低延迟的业务场景对 Flink 作业的性能提出了更高要求。本文将从原理层面深入解析…

ubuntu上将TempMonitor加入开机自动运行的方法

1.新建一个TempMonitor.sh文件&#xff0c;内容如下&#xff1a;#!/bin/bashcd /fjrobot/ ./TempMonitor &2.执行以下命令chmod x TempMonitor chmod x TempMonitor.sh rm -rf /etc/rc2.d/S56TempMonitor rm -rf /etc/init.d/TempMonitor cp /fjrobot/TempMonitor.sh /etc/…