素材下载
作业需求
STARTO!
游戏画面设计
新建一个 2D Unity 专案
更改 MainCamera 颜色为黑色,大小调整为 8,位置 X = 4.5 ,Y = 7.5
将开头下载的素材丢进专案
选取两张图片
将每单位像素数改为 32
选取套用
拖曳两个 border.png 到阶层视窗
将 border 物件的位置 X = -0.5,Y = 10,缩放 Y = 40
将 border (1) 物件的位置 X = 9.5,Y = 10,缩放 Y = 40
将开头下载的 05_Swoosh.mp3 拉进专案视窗
将 MainCamera 增加元件>音讯>音讯源
将 AudioClip 设定为 05_Swoosh.mp3
在阶层视窗按下滑鼠右键>UI>文字
设定 Canvas 的渲染模式为萤幕空间 – 摄影机,渲染摄影机设为 MainCamera
设定 Text 物件的属性字型大小为30,颜色白色,水平与垂直溢出设定为 Overflow
调整一下 Text 的位置
画面设计完成
俄罗斯方块物件制作
在阶层视窗按下滑鼠右键>建立空物件
拉四次 block.png 到 Gameobject 底下
修改四个物件的位置属性如下
- block 物件 X = 0,Y = 0
- block (1) 物件 X = 0,Y = 1
- block (2) 物件 X = 1,Y = 0
- block (3) 物件 X = 1,Y = 1
重新命名 GameObject 物件名称为 GroupO
将 GroupO 拉到专案资料夹制作预制物件
重复以上过程,制作 GroupI、GroupJ、GroupL、GroupS、GroupT、GroupZ
GroupI 属性
- block 物件 X = 0,Y = 0
- block (1) 物件 X = 0,Y = 1
- block (2) 物件 X = 0,Y = 2
- block (3) 物件 X = 0,Y = 3
GroupJ 属性
- block 物件 X = 0,Y = 0
- block (1) 物件 X = 0,Y = 1
- block (2) 物件 X = 0,Y = 2
- block (3) 物件 X = -1,Y = 0
GroupL 属性
- block 物件 X = 0,Y = 0
- block (1) 物件 X = 0,Y = 1
- block (2) 物件 X = 0,Y = 2
- block (3) 物件 X = 1,Y = 0
GroupS 属性
- block 物件 X = 0,Y = 0
- block (1) 物件 X = 0,Y = 1
- block (2) 物件 X = 1,Y = 1
- block (3) 物件 X = -1,Y = 0
GroupZ 属性
- block 物件 X = 0,Y = 0
- block (1) 物件 X = 0,Y = 1
- block (2) 物件 X = -1,Y = 1
- block (3) 物件 X = 1,Y = 0
GroupT 属性
- block 物件 X = 0,Y = 0
- block (1) 物件 X = 1,Y = 0
- block (2) 物件 X = 2,Y = 0
- block (3) 物件 X = 1,Y = -1
制作生成器 (Spawner)
在阶层视窗按下滑鼠右键>建立空物件
命名为 Spawner
设定 Spawner 属性,位置 X = 5,Y = 14
新建一个 Scripts 资料夹
建立一个脚本名为 Spawner.cs 并加入以下程式码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour
{
// Start is called before the first frame update
public GameObject[] groups;
void Start()
{
spwanNext();
}
public void spwanNext()
{
int i = UnityEngine.Random.Range(0, groups.Length);
Instantiate(groups[i], transform.position, Quaternion.identity);
}
// Update is called once per frame
void Update()
{
}
}储存脚本并将 Spawner.cs 脚本拉进 Spawner 物件底下
点下”组”
大小输入 7
将刚刚制作的七个预制物件拉进去
制作网格 (Grid) 与群组 (Group) 脚本
新建一个脚本 Grid_Scripts.cs 脚本,输入以下程式码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Grid_Scripts : MonoBehaviour
{
// Start is called before the first frame update
public static int w = 10;
public static int h = 20;
public static Transform[,] grid = new Transform[w, h];
public static int score = 0;
private static Text score_display;
public static Vector2 roundVec2(Vector2 v)
{
return new Vector2(Mathf.Round(v.x), Mathf.Round(v.y));
}
public static bool insideBorder(Vector2 pos)
{
return ((int)pos.x >= 0 && (int)pos.x < w && (int)pos.y >= 0);
}
public static void deleteRow(int y)
{
for (int x = 0; x < w; ++x)
{
Destroy(grid[x, y].gameObject);
grid[x, y] = null;
}
}
public static void decreaseRow(int y)
{
for (int x = 0; x < w; ++x)
{
if (grid[x, y] != null)
{
grid[x, y - 1] = grid[x, y];
grid[x, y] = null;
grid[x, y - 1].position += new Vector3(0, -1, 0);
}
}
}
public static void decreaseRowAbove(int y)
{
for (int i = y; i < h; ++i)
{
decreaseRow(i);
}
}
public static bool isRowFull(int y)
{
for (int x = 0; x < w; ++x)
{
if (grid[x, y] == null)
return false;
}
return true;
}
public static void deleteFullRows()
{
for (int y = 0; y < h; ++y)
{
if (isRowFull(y))
{
score++;
deleteRow(y);
decreaseRowAbove(y + 1);
--y;
set_score();
}
}
}
static void set_score()
{
score_display = GameObject.Find("Text").GetComponent<Text>();
score_display.text = score.ToString();
}
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}新增一个 Group.cs 脚本,输入以下程式码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Group : MonoBehaviour
{
// Start is called before the first frame update
float lastFall = 0;
bool isValidGridPos()
{
foreach (Transform child in transform)
{
Vector2 v = Grid_Scripts.roundVec2(child.position);
if (!Grid_Scripts.insideBorder(v))
return false;
if (Grid_Scripts.grid[(int)v.x, (int)v.y] != null &&
Grid_Scripts.grid[(int)v.x, (int)v.y].parent != transform)
return false;
}
return true;
}
void updateGrid()
{
for (int y = 0; y < Grid_Scripts.h; ++y)
for (int x = 0; x < Grid_Scripts.w; ++x)
if (Grid_Scripts.grid[x, y] != null)
if (Grid_Scripts.grid[x, y].parent == transform)
Grid_Scripts.grid[x, y] = null;
foreach (Transform child in transform)
{
Vector2 v = Grid_Scripts.roundVec2(child.position);
Grid_Scripts.grid[(int)v.x, (int)v.y] = child;
}
}
void Start()
{
if (!isValidGridPos())
{
Debug.Log("Game Over");
Destroy(gameObject);
}
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
transform.position += new Vector3(-1, 0, 0);
if (isValidGridPos())
updateGrid();
else
transform.position += new Vector3(1, 0, 0);
}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{
transform.position += new Vector3(1, 0, 0);
if (isValidGridPos())
updateGrid();
else
transform.position += new Vector3(-1, 0, 0);
}
else if(Input.GetKeyDown(KeyCode.UpArrow))
{
transform.Rotate(0, 0, -90);
if (isValidGridPos())
updateGrid();
else
transform.Rotate(0, 0, 90);
}
else if(Input.GetKeyDown(KeyCode.DownArrow) || Time.time - lastFall >= 1)
{
transform.position += new Vector3(0, -1, 0);
if (isValidGridPos())
updateGrid();
else
{
transform.position += new Vector3(0, 1, 0);
Grid_Scripts.deleteFullRows();
FindObjectOfType<Spawner>().spwanNext();
enabled = false;
}
lastFall = Time.time;
}
}
}将七个预制物件选取起来
增加元件>脚本>Group
完成,看看结果吧! (上课资料)
完成,看看结果吧! (作业)

- 受保护的内容: NAS 版 Mathbot 管理网站与 Linebot 启动方法 - 2024 年 11 月 15 日
- Realtime 啥鬼的 - 2021 年 6 月 15 日
- nodejs 数学游戏 - 2021 年 6 月 8 日







































