UNITY 开发日记/教程 俄罗斯方块 (四) 方块下落和落地判定

接上文.

我们拿到要操作的方块之后,事情就变得简单起来,只要用代码来控制现有的UI即可.

首先来实现方块下落.

我们首先需要定义一些字段来实现下落的功能.

fallspeed来控制方块下落速度,将来可以用来控制游戏的难易度.

runFlag用来表示游戏是否正在进行,可以用来做暂停功能,游戏结束等等.在游戏开始时将这个布尔量为真,暂停和gameover时为假.

fallInterval为下落时间间隔.

timeCount用来计游戏流逝时间,timeCount累积达到fallInterval时,使方块下落一格.

squareMap用来保存已经落地之后的正方形的位置.


    [Range(1,10)]
    public float fallSpeed;
    RectTransform myRectTransform { get { return GetComponent<RectTransform>(); } }
    dmBlock nowControlBlock;
    bool runFlag;
    float fallInterval { get { return 1 / fallSpeed; } }
    float timeCount;
    Vector2 nowBlockPos;
    Dictionary<Vector2, GameObject> squareMap = new Dictionary<Vector2, GameObject>();



重构StartGame

    public void StartGame()
    {
        if (nowControlBlock != null)
        {
            blockBuilder.DestroySquares(nowControlBlock);
        }
        if(squareMap != null)
        {
            foreach(Vector2 squareCoord in squareMap.Keys)
            {
                Destroy(squareMap[squareCoord]);
            }
        }
        squareMap.Clear();
        blockBuilder.BuildRandomBlock();
        NextBlock();
        timeCount = 0;
        runFlag = true;
    }
回收上次游戏的残留正方形,然后初始化一些控制用变量的初始值

写Update函数,Unity每一帧会自动调用Update,我们要把帧转换成固定时间,用timeCount变量的累计来做

void Update () {
    if (runFlag)
    {
        timeCount += Time.deltaTime;
        if (timeCount >= fallInterval)
        {
            timeCount -= fallInterval;
            DoFall();               
        }
    }
}

然后实现DoFall() 也就是方块下落.下落之前要先判断目标位置是否能够下落,也就是边界检查,以及和以前下落的正方形的碰撞判断

public void DoFall()
{
    Vector2 targetPos = nowBlockPos + new Vector2(0, 1);
    if(!CheckCollision(nowControlBlock,targetPos))
    {
        MoveBlockTo(nowControlBlock, targetPos);
    }
    else
    {
        FallGround(nowControlBlock);
        NextBlock();
    }
}

然后写边界检查函数


    public bool CheckCollision(dmBlock block,Vector2 targetPos)
    {        
        foreach(Vector2 squareCoord in block.bindBase.squareCoordList)
        {
            Vector2 squarePos = squareCoord + targetPos;
            if(squarePos.y >= areaSize.y || squarePos.x<0 || squarePos.x >= areaSize.x)
            {
                return true;
            }
            if (squareMap.ContainsKey(squarePos)) return true;       
        }
        return false;
    }


无法继续下落时的处理,将当前方块内含的全部正方形存入squareMap中,并让方块的图片变成灰色.

public void FallGround(dmBlock block)
{
    for(int i = 0; i < block.bindBase.squareCoordList.Count;i++)
    {
        squareMap.Add(nowBlockPos + block.bindBase.squareCoordList[i], block.squareList[i]);
        block.squareList[i].GetComponentInChildren<Image>().color = Color.gray;
    }
}

到此为止,下落和落地判定就已经实现了,可以点击PLAY后点击开始游戏按钮进行调试.


本次修改之后,完整的GameArea代码如下


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

public class dmGameArea : MonoBehaviour {
    public dmBlockBuilder blockBuilder;
    public Vector2 areaSize;
    public Vector2 initPos;
    [Range(1,10)]
    public float fallSpeed;
    RectTransform myRectTransform { get { return GetComponent<RectTransform>(); } }
    dmBlock nowControlBlock;
    bool runFlag;
    float fallInterval { get { return 1 / fallSpeed; } }
    float timeCount;
    Vector2 nowBlockPos;
    Dictionary<Vector2, GameObject> squareMap = new Dictionary<Vector2, GameObject>();

    void Start () {
        myRectTransform.sizeDelta = new Vector2(areaSize.x * blockBuilder.squareSize.x, areaSize.y * blockBuilder.squareSize.y);
        runFlag = false;
    }	

    
	// Update is called once per frame
	void Update () {
        if (runFlag)
        {
            timeCount += Time.deltaTime;
            if (timeCount >= fallInterval)
            {
                timeCount -= fallInterval;
                DoFall();               
            }
        }
	}
    public void DoFall()
    {
        Vector2 targetPos = nowBlockPos + new Vector2(0, 1);
        if(!CheckCollision(nowControlBlock,targetPos))
        {
            MoveBlockTo(nowControlBlock, targetPos);
        }
        else
        {
            FallGround(nowControlBlock);
            NextBlock();
        }
    }
    public bool CheckCollision(dmBlock block,Vector2 targetPos)
    {        
        foreach(Vector2 squareCoord in block.bindBase.squareCoordList)
        {
            Vector2 squarePos = squareCoord + targetPos;
            if(squarePos.y >= areaSize.y || squarePos.x<0 || squarePos.x >= areaSize.x)
            {
                return true;
            }
            if (squareMap.ContainsKey(squarePos)) return true;       
        }
        return false;
    }
    public void FallGround(dmBlock block)
    {
        for(int i = 0; i < block.bindBase.squareCoordList.Count;i++)
        {
            squareMap.Add(nowBlockPos + block.bindBase.squareCoordList[i], block.squareList[i]);
            block.squareList[i].GetComponentInChildren<Image>().color = Color.gray;
        }
    }

    public void StartGame()
    {
        if (nowControlBlock != null)
        {
            blockBuilder.DestroySquares(nowControlBlock);
        }
        if(squareMap != null)
        {
            foreach(Vector2 squareCoord in squareMap.Keys)
            {
                Destroy(squareMap[squareCoord]);
            }
        }
        squareMap.Clear();
        blockBuilder.BuildRandomBlock();
        NextBlock();
        timeCount = 0;
        runFlag = true;
    }

    public void NextBlock()
    {
        PutInBlock(blockBuilder.nowBlock);
        blockBuilder.BuildRandomBlock();
    }
    public void PutInBlock(dmBlock block)
    {
        nowControlBlock = block;
        blockBuilder.nowBlock = null;
        foreach(GameObject square in block.squareList)
        {
            square.transform.SetParent(transform);
        }
        MoveBlockTo(block,initPos);
    }
    public void MoveBlockTo(dmBlock onMoveBlock,Vector2 targetPos)
    {
        if (CheckCollision(onMoveBlock, targetPos))
        {
            //GameOver
            runFlag = false;
            return;
        }
        for (int i = 0; i < onMoveBlock.bindBase.squareCoordList.Count; i++)
        {
            Vector2 squareCoord = targetPos + onMoveBlock.bindBase.squareCoordList[i];
            onMoveBlock.squareList[i].transform.localPosition = AreaPos2Local(squareCoord);
            onMoveBlock.squareList[i].SetActive(squareCoord.y >= 0);
        }
        nowBlockPos = targetPos;
    }
    public Vector2 AreaPos2Local(Vector2 areaPos)
    {
        return new Vector2((areaPos.x + 0.5f) * blockBuilder.squareSize.x, - (0.5f + areaPos.y) * blockBuilder.squareSize.y);
    }
}

目录

(一) 定义方块

(二) 搭建方块UI和生成方块.

(三) 搭建场地UI和游戏流程控制

(四) 方块下落和落地判定

(五) 方块平移和旋转

(六) 方块消除



猜你喜欢

转载自blog.csdn.net/neverwind/article/details/75023899