経緯
子供にUnity教える時に、テトリス作ってってよく言われるし作っとくかー
ブロックの回転は数学的知識が必要なのでわかりにくいかも...
URL
コード
できるだけObjectを少なくするように制作。ステージ、ミノは全て、一つのPrefabを使って制作した。
backGroundgenerator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.UI;
public class backGroundgenerator : MonoBehaviour
{
private GameObject backGroundBlock;
private GameObject block;
private GameObject none;
public GameObject backGround;
public GameObject Block;
private List<List<GameObject>> backGroundList = new List<List<GameObject>>();
private int[,] onOff = new int[10,10];
private List<GameObject> movingBlock = new List<GameObject>();
private int rotationKey;
private Color[] colorList = new Color [7]{new Color(0,1,1,1),new Color(1,0.92f,0.016f,1),new Color(0,1,0,1),new Color(1,0,0,1),new Color(0,0,1,1),new Color(1,0.6471f,0,1),new Color(1,0,1,1)};
//水色、黄色、緑、赤、青、オレンジ、マゼンダ
private int random;
private int score=0;
public Text scoreText;
// Start is called before the first frame update
void Start()
{
scoreText.text="Score: "+score.ToString();
for(int j = 0;j<10;j++){//盤面生成
for(int i = 0;i<10;i++){
if(j==0 || i==0 || i==9){
if(i==0){
backGroundList.Add(new List<GameObject>());
}
onOff[i,j]=1;
backGroundBlock = (GameObject)Instantiate(backGround) as GameObject;
backGroundBlock.gameObject.transform.position = new Vector2(-4.5f+i,-4.5f+j);
backGroundList[j].Add(backGroundBlock);
}else{
onOff[i,j]=0;
backGroundList[j].Add(none);
}
}
}
StartCoroutine (main());
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.RightArrow)){
if(check("Right")){//右に進めるかチェック
move("Right");//右に進める
}
}
if(Input.GetKeyDown(KeyCode.LeftArrow)){
if(check("Left")){
move("Left");
}
}
if(Input.GetKeyDown("d")){
if(checkRotation("Right")){//右に回せるかチェック
rotate("Right");//右に回す
}
}
if(Input.GetKeyDown("a")){
if(checkRotation("Left")){
rotate("Left");
}
}
}
private IEnumerator main(){
while(true){
generate();//新しいブロック生成
while(true){
yield return new WaitForSeconds(1f);//一秒待つ
if(check("Down")){//下に行けるかチェック
move("Down");//下に動かす
}
else{
changeToBackGround();//ブロックを動かせなくする
checkLine();//消せるラインがないか確認
break;
}
}
}
}
private void generate(){
random = Random.Range(0,6);
if(random==0){//Iミノ
for(int i=0;i<4;i++){
block = (GameObject)Instantiate(Block) as GameObject;
block.gameObject.transform.position = new Vector2(-0.5f+i,4.5f);
block.GetComponent<Renderer> ().material.color = colorList[random];
movingBlock.Add(block);
}
rotationKey=1;
}else if (random==1){//Oミノ
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
block = (GameObject)Instantiate(Block) as GameObject;
block.gameObject.transform.position = new Vector2(-0.5f+i,4.5f-j);
block.GetComponent<Renderer> ().material.color = colorList[random];
movingBlock.Add(block);
}
}
rotationKey=3;
}else if (random==2){//Sミノ
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
block = (GameObject)Instantiate(Block) as GameObject;
block.gameObject.transform.position = new Vector2(-0.5f+i-j,4.5f-j);
block.GetComponent<Renderer> ().material.color = colorList[random];
movingBlock.Add(block);
}
}
rotationKey=3;
}else if(random==3){//Zミノ
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
block = (GameObject)Instantiate(Block) as GameObject;
block.gameObject.transform.position = new Vector2(-0.5f+i+j,4.5f-j);
block.GetComponent<Renderer> ().material.color = colorList[random];
movingBlock.Add(block);
}
}
rotationKey=1;
}else{//J,L,Tミノ
//random4,5,6
block = (GameObject)Instantiate(Block) as GameObject;
block.gameObject.transform.position = new Vector2(-0.5f+random-4,4.5f);
block.GetComponent<Renderer> ().material.color = colorList[random];
movingBlock.Add(block);
for(int i=0;i<3;i++){
block = (GameObject)Instantiate(Block) as GameObject;
block.gameObject.transform.position = new Vector2(-0.5f+i,3.5f);
block.GetComponent<Renderer> ().material.color = colorList[random];
movingBlock.Add(block);
}
rotationKey=2;
}
}
private bool check(string str){
foreach(GameObject stock in movingBlock){
int i=(int)(stock.gameObject.transform.position.x+4.5);
int j=(int)(stock.gameObject.transform.position.y+4.5);
if(str=="Right"){
if(onOff[i+1,j]==1){
return false;
}
}
else if(str=="Left"){
if(onOff[i-1,j]==1){
return false;
}
}
else if (str=="Down"){
if(onOff[i,j-1]==1){
return false;
}
}
}
return true;
}
private bool checkRotation(string str){
GameObject center = movingBlock[rotationKey];
int centerX=(int)(center.gameObject.transform.position.x+4.5);
int centerY=(int)(center.gameObject.transform.position.y+4.5);
foreach(GameObject stock in movingBlock){
int i=(int)(stock.gameObject.transform.position.x+4.5);
int j=(int)(stock.gameObject.transform.position.y+4.5);
if(str=="Right"){
if(centerX-centerY+j<0|centerX-centerY+j>9|centerX+centerY-i<0|centerX+centerY-i>9){
return false;
}
if(onOff[centerX-centerY+j,centerX+centerY-i]==1){
return false;
}
}
else if(str=="Left"){
if(centerX+centerY-j<0|centerX+centerY-j>9|-centerX+centerY+i<0|-centerX+centerY+i>9){
return false;
}
if(onOff[centerX+centerY-j,-centerX+centerY+i]==1){
return false;
}
}
}
return true;
}
private void move(string str){
foreach(GameObject stock in movingBlock){
if(str=="Right"){
stock.gameObject.transform.Translate(new Vector2(1,0));
}
else if(str=="Left"){
stock.gameObject.transform.Translate(new Vector2(-1,0));
}
else if (str=="Down"){
stock.gameObject.transform.Translate(new Vector2(0,-1));
}
}
}
private void rotate(string str){
GameObject center = movingBlock[rotationKey];
int centerX=(int)(center.gameObject.transform.position.x+4.5);
int centerY=(int)(center.gameObject.transform.position.y+4.5);
foreach(GameObject stock in movingBlock){
int i=(int)(stock.gameObject.transform.position.x+4.5);
int j=(int)(stock.gameObject.transform.position.y+4.5);
if(str=="Right"){
stock.gameObject.transform.position = new Vector2(-4.5f+centerX-centerY+j,-4.5f+centerX+centerY-i);
}
else if(str=="Left"){
stock.gameObject.transform.position = new Vector2(-4.5f+centerX+centerY-j,-4.5f+-centerX+centerY+i);
}
}
}
private void changeToBackGround(){
foreach(GameObject stock in movingBlock){
int i=(int)(stock.gameObject.transform.position.x+4.5);
int j=(int)(stock.gameObject.transform.position.y+4.5);
onOff[i,j]=1;
backGroundBlock = (GameObject)Instantiate(backGround) as GameObject;
backGroundBlock.gameObject.transform.position = new Vector2(-4.5f+i,-4.5f+j);
backGroundBlock.GetComponent<Renderer> ().material.color = colorList[random];
backGroundList[j][i]=backGroundBlock;
Destroy(stock);
}
movingBlock.Clear();
}
private void checkLine(){
int[] goodLine = new int[10]{1,0,0,0,0,0,0,0,0,0};
for(int j=1;j<10;j++){
int sum = 0;
for(int i=1;i<9;i++){
sum+=onOff[i,j];
}
if(sum==8){
goodLine[j]=1;
}
}
if(goodLine.Sum()>1){
destroyLine(goodLine);
}
}
private void destroyLine(int[] x){
GameObject stock;
int value = 1000;
for(int j=1;j<10;j++){
for(int i=1;i<9;i++){
stock = backGroundList[j][i];
backGroundList[j][i] = none;
onOff[i,j]=0;
if(x[j]==1){
Destroy(stock);
if(i==1){
score+=value;
value+=1000;
scoreText.text="Score: "+score.ToString();
}
}else if (stock != none){
int downValue=-1;
for(int k=0;k<j;k++){
downValue+=x[k];
}
stock.gameObject.transform.Translate(new Vector2(0,-downValue));
backGroundList[j-downValue][i] = stock;
onOff[i,j-downValue]=1;
}
}
}
}
}
今後の課題
- 下ボタンを押せるようにするとバグるので追加しなかった。
=>そもそもの仕組みを変える必要があるかも?