using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BlockController : MonoBehaviour
{
// 落下タイマー
float fallTimerMax = 0.5f;
float fallTimer;
// シーンディレクター
[SerializeField] TetrisPuzzleSceneDirector gameSceneDirector;
// 初期化
public void Init(TetrisPuzzleSceneDirector director, float timerMax)
{
gameSceneDirector = director;
fallTimerMax = timerMax;
}
// Start is called before the first frame update
void Start()
{
fallTimer = fallTimerMax;
}
// Update is called once per frame
void Update()
{
// 落下タイマー消化
fallTimer -= Time.deltaTime;
// 移動する方向
Vector3 movePosition = Vector3.zero;
// 左移動
if(Input.GetKeyUp(KeyCode.LeftArrow))
{
movePosition = Vector3.left;
}
// 右移動
else if (Input.GetKeyUp(KeyCode.RightArrow))
{
movePosition = Vector3.right;
}
// 下移動
else if (Input.GetKeyUp(KeyCode.DownArrow))
{
movePosition = Vector3.down;
}
// 回転
else if (Input.GetKeyUp(KeyCode.UpArrow))
{
transform.Rotate(new Vector3(0, 0, 1), 90);
if(!gameSceneDirector.IsMovable(transform))
{
transform.Rotate(new Vector3(0, 0, 1), -90);
}
}
// 時間経過で下移動
if(fallTimer < 0)
{
movePosition = Vector3.down;
fallTimer = fallTimerMax;
}
// 移動
transform.position += movePosition;
// 移動できなかった場合
if(!gameSceneDirector.IsMovable(transform))
{
// 元に戻す
transform.position -= movePosition;
// 下に移動できなかった場合は終了
if(movePosition == Vector3.down)
{
enabled = false;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TetrisPuzzleSceneDirector : MonoBehaviour
{
// フィールドサイズ
const int FieldWidth = 10;
const int FieldHeight = 20;
// ブロックのプレハブ
[SerializeField] List<BlockController> prefabBlocks;
// 次のブロック
BlockController nextBlock;
// 現在のブロック
BlockController currentBlock;
// フィールド全体のデータ
Transform[,] fieldTiles;
// Start is called before the first frame update
void Start()
{
// 2次元配列を初期化
fieldTiles = new Transform[FieldWidth, FieldHeight];
// 初回のブロックを作成
SetupNextBlock();
// フィールドへ
SpawnBlock();
}
// Update is called once per frame
void Update()
{
// 動いている時はなにもしない
if (currentBlock.enabled) return;
// 動きが止まったらデータセット
foreach (Transform item in currentBlock.transform)
{
Vector2Int index = GetIndexPosition(item.position);
fieldTiles[index.x, index.y] = item;
}
// 次のブロックをフィールドへ
SpawnBlock();
}
// ワールド座標をインデックス座標に変換
Vector2Int GetIndexPosition(Vector3 position)
{
Vector2Int index = new Vector2Int();
index.x = Mathf.RoundToInt(position.x - 0.5f) + FieldWidth / 2;
index.y = Mathf.RoundToInt(position.y - 0.5f) + FieldHeight / 2;
return index;
}
// 移動可能か
public bool IsMovable(Transform blockTransform)
{
foreach (Transform item in blockTransform)
{
Vector2Int index = GetIndexPosition(item.position);
// 左右と下
if(index.x < 0 || FieldWidth-1 < index.x || index.y < 0)
{
return false;
}
// ブロックがある
if(GetFieldTile(index))
{
return false;
}
}
return true;
}
// 次のブロックを作成
void SetupNextBlock()
{
// prefabBlocksからランダムで作成
int rnd = Random.Range(0, prefabBlocks.Count);
// 表示位置
Vector3 setupPosition = new Vector3(2.5f, 11f, 0);
// ブロック生成
BlockController prefab = prefabBlocks[rnd];
nextBlock = Instantiate(prefab, setupPosition, Quaternion.identity);
// 初期化
nextBlock.Init(this, 1);
// 動かないようにしておく
nextBlock.enabled = false;
}
// ブロックをフィールドへ
void SpawnBlock()
{
// 出現位置
Vector3 spawnPosition = new Vector3(0.5f, 8.5f, 0);
// ブロックをセット
currentBlock = nextBlock;
currentBlock.transform.position = spawnPosition;
// 動かす
currentBlock.enabled = true;
// 次のブロックをセット
SetupNextBlock();
}
// フィールドのブロックを返す
Transform GetFieldTile(Vector2Int index)
{
if(index.x < 0 || FieldWidth -1 < index.x ||
index.y < 0 || FieldHeight - 1 < index.y )
{
return null;
}
return fieldTiles[index.x, index.y];
}
}