오전까지는 과제 제출 시간 ~
그래서 디자인 패턴 예습 겸 다음 영상을 보고 정리
https://www.youtube.com/watch?v=J6F8plGUqv8
Solid 원칙에 대해 공부함.
정리는 다른 포스트에 !
그리고 Git과 한참을 싸움,
분명 나는 gitignore에 다음 사이트에서 받아온 Unity 관련 무시할 것들을 집어넣었다.
https://www.toptal.com/developers/gitignore
gitignore.io
Create useful .gitignore files for your project
www.toptal.com
근데 Push를 하려 하면 할수록 너무 용량이 크다고 안되길래 계속해서 다시 하고, 또 기록을 지우고 다시 하는 과정을 거쳤다.
git rm -r --cached .
git add .
git commit -m "Fix .gitignore issues"
git push -u origin main
다음과 같은 방식으로 스테이징된걸 풀고 다시하고,,, 라이더 이그노어도 넣어보고 다시하고 했으나 되지 않아서
script폴더에 새로운 깃을 만들고 올렸다.
이후 용량의 문제를 확실히 알아보기 위해서 어떤 파일을 무시하는지 다시 확인했다.
테트리스 만들기
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public enum TetrominoType : byte
{
None,
I,
O,
Z,
S,
L,
T,
Max
}
public class TetrominoData : MonoBehaviour
{
[Header("Tetromino Data")]
[SerializeField] private TetrominoType tetrominoType = TetrominoType.None;
[SerializeField] private float dropTime = 1.0f;
[SerializeField] private float leftLimtPosition = -4.0f;
[SerializeField] private float rightLimtPosition = 4.0f;
[SerializeField] private float bottomLimtPosition = -9.0f;
private bool cnaDrop = true;
private List<Transform> blocks = new List<Transform>();
private float currentDropTime = 0.0f;
void Start()
{
currentDropTime =dropTime;
blocks = GetComponentsInChildren<Transform>().ToList();
}
// Update is called once per frame
void Update()
{
if (!cnaDrop)
return;
if (Input.GetKeyDown(KeyCode.A))
{
transform.position += Vector3.left;
if (checkBlockCollision())
{
transform.position -= Vector3.left;
}
}
if (Input.GetKeyDown(KeyCode.D))
{
transform.position += Vector3.right;
if (checkBlockCollision())
{
transform.position -= Vector3.right;
}
}
currentDropTime -= Time.deltaTime;
if (currentDropTime <= 0.0f)
{
transform.position += Vector3.down;
if (checkBlockFinishMove())
{
transform.position -= Vector3.down;
cnaDrop = false;
GameObject Tetromino_Prefab = null;
TetrominoType nextBlockIndex =(TetrominoType)Random.Range(0, 6) + 1;
switch (nextBlockIndex)
{
case TetrominoType.I:
Tetromino_Prefab = Resources.Load<GameObject>("Prefabs/Tetrismino_I");
break;
case TetrominoType.O:
Tetromino_Prefab = Resources.Load<GameObject>("Prefabs/Tetrismino_O");
break;
case TetrominoType.Z:
Tetromino_Prefab = Resources.Load<GameObject>("Prefabs/Tetrismino_Z");
break;
case TetrominoType.S:
Tetromino_Prefab = Resources.Load<GameObject>("Prefabs/Tetrismino_S");
break;
case TetrominoType.L:
Tetromino_Prefab = Resources.Load<GameObject>("Prefabs/Tetrismino_L");
break;
case TetrominoType.T:
Tetromino_Prefab = Resources.Load<GameObject>("Prefabs/Tetrismino_T");
break;
}
Debug.Assert(Tetromino_Prefab);
//GameObject Tetromino_Prefabs = Resources.Load<GameObject>("Prefabs/Tetromiono_I");
Instantiate(Tetromino_Prefab, new Vector3(0,9,0), Quaternion.identity);
}
currentDropTime = dropTime;
}
}
bool checkBlockCollision()
{
foreach (var block in blocks)
{
if (block.position.x < leftLimtPosition)
{
return true;
}
if (block.position.x > rightLimtPosition)
{
return true;
}
if (block.position.y < bottomLimtPosition)
{
return true;
}
}
return false;
}
bool checkBlockFinishMove()
{
foreach (var block in blocks)
{
if (block.position.y < bottomLimtPosition)
{
return true;
}
}
return false;
}
}
하드코딩 방식이다. 기본 구조를 짜고 있음
아직 블록끼리 충돌이나 회전은 없음
싱글톤 패턴으로 게임매니저 만들고, 테트리스 구현
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour, ISingleton
이렇게 쓰면 안된다, MonoBehaviour이 모노비헤이비어지아 싱글톤이 되어버린다.
인터페이스는 패스하고 !
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class TetrominoData : MonoBehaviour
{
private List<Transform> blocks = new List<Transform>();
public List<Transform> Blocks { get => blocks; }
// Start is called before the first frame update
void Start()
{
blocks = GetComponentsInChildren<Transform>().ToList();
}
}
테트리스 블럭들을 배열에 저장한다. (위치)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T Instance
{
get
{
// 저는 이거 생략해요
if (instance == null)
{
instance = FindObjectOfType(typeof(T)) as T;
}
if (instance == null)
{
GameObject obj = new GameObject();
obj.name = typeof(T).Name;
obj.AddComponent<T>();
}
return instance;
}
}
// 게임이 시작되면 그냥 처음으로 불리우는 함수이다.
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
public static void OnBeforeSceneLoadRuntimeMethod()
{
}
private void Awake()
{
if (instance == null)
{
instance = this as T;
}
OnAwake();
}
public virtual void OnAwake()
{
}
}
싱글톤 패턴을 구현한다.
이에 관한 자세한 내용은 따로 포스팅할 예정이다.
using System;
using System.Collections;
using System.Collections.Generic;
using AYellowpaper.SerializedCollections;
using Unity.VisualScripting;
using UnityEngine;
using Random = UnityEngine.Random;
public enum TetrominoType : byte
{
None,
I,
O,
Z,
S,
J,
L,
T,
Max
}
public class TetrisManager : Singleton<TetrisManager>
{
[SerializeField] private Transform spawnPoint;
[SerializeField] private SerializedDictionary<TetrominoType, string> tetrominoDatas;
[SerializeField] private float dropTime = 1.0f;
[SerializeField] private float leftLimitPosition = -5.0f;
[SerializeField] private float rightLimitPosition = 5.0f;
[SerializeField] private float bottomLimitPosition = -8.5f;
private TetrominoData _currentTetrominoData;
private float currentDropTime = 0.0f;
private int[][] grid = null;
public override void OnAwake()
{
base.OnAwake();
grid = new int[25][];
for (int i = 0; i < grid.Length; i++)
{
grid[i] = new int[10];
}
}
void Start()
{
currentDropTime = dropTime;
SpawnTetromino();
}
void Update()
{
if (_currentTetrominoData.IsUnityNull())
return;
if (Input.GetKeyDown(KeyCode.A))
{
_currentTetrominoData.transform.position += Vector3.left;
if (checkBlockCollision())
{
_currentTetrominoData.transform.position -= Vector3.left;
}
}
if (Input.GetKeyDown(KeyCode.D))
{
_currentTetrominoData.transform.position += Vector3.right;
if (checkBlockCollision())
{
_currentTetrominoData.transform.position -= Vector3.right;
}
}
if (Input.GetKeyDown(KeyCode.W))
{
_currentTetrominoData.transform.Rotate(new Vector3(0, 0, -90));
if (checkBlockCollision())
{
_currentTetrominoData.transform.Rotate(new Vector3(0, 0, 90));
}
}
currentDropTime -= Time.deltaTime;
if (currentDropTime <= 0.0f)
{
_currentTetrominoData.transform.position += Vector3.down;
var (minX, minY, maxX, maxY) = GetGridState();
Debug.Log(minX + " - " + minY);
if (minY == -1)
{
_currentTetrominoData.transform.position -= Vector3.down;
string printS = "\n";
for (int y = grid.Length - 1; y >= 0; y--)
{
for (int x = 0; x < grid[y].Length; x++)
{
printS += grid[y][x] == 1 ? "1" : "0";
}
printS += "\n";
}
Debug.Log(printS);
SpawnTetromino();
}
currentDropTime = dropTime;
}
}
private (int, int, int, int) GetGridState()
{
int minX = Int32.MaxValue;
int minY = Int32.MaxValue;
int maxX = Int32.MinValue;
int maxY = Int32.MinValue;
foreach (var block in _currentTetrominoData.Blocks)
{
int y = (int)(block.transform.position.y + 8.5f);
int x = (int)(block.transform.position.x + 5.0f);
minX = Mathf.Min(minX, x);
minY = Mathf.Min(minY, y);
maxX = Mathf.Max(maxX, x);
maxY = Mathf.Max(maxY, y);
}
return (minX, minY, maxX, maxX);
}
private void SpawnTetromino()
{
GameObject Tetromino_Prefab = null;
TetrominoType nextBlockIndex = (TetrominoType)Random.Range(0, 7) + 1;
Tetromino_Prefab = Resources.Load<GameObject>($"Prefab/{tetrominoDatas[nextBlockIndex]}");
Debug.Assert(Tetromino_Prefab);
GameObject spawndTetromino = Instantiate(Tetromino_Prefab, spawnPoint.position, Quaternion.identity);
spawndTetromino.TryGetComponent(out _currentTetrominoData);
}
bool checkBlockCollision()
{
foreach (var block in _currentTetrominoData.Blocks)
{
if (block.position.x < leftLimitPosition)
{
return true;
}
if (block.position.x > rightLimitPosition)
{
return true;
}
}
return false;
}
bool checkBlockFinishMove()
{
foreach (var block in _currentTetrominoData.Blocks)
{
if (block.position.y < bottomLimitPosition)
{
return true;
}
}
return false;
}
}
간단한 이동, 좌우와 한계선까지 가면 이동을 못하게 한다( 정확하게는 이동시켰다 되돌린다)
그리고 맵 전체를 하나의 배열로 보고 (25,10) 블럭이 있으면 1, 없으면 0으로 만든다.
생성은 랜덤이다.
*Resources : 유니티에서 자체적으로 쓸 수 있는 파일명이자 코드에서 불러올 수 있음
오늘은 싱글톤에 관해 GPT와 토론하느라 시간이 너무 늦었고, 자세한 설명을 해 주시지 않아서 내일 다시 오겠다.
'TIL' 카테고리의 다른 글
[멋쟁이사자처럼 부트캠프TIL회고] 42일차 : 테트리스 기능 추가 (0) | 2025.01.01 |
---|---|
[멋쟁이사자처럼 부트캠프 TIL회고] 41일차 : 테트리스 (1) | 2025.01.01 |
[멋쟁이사자처럼 부트캠프 TIL회고] 39일차 : 폭발물 추가 (1) | 2024.12.29 |
[멋쟁이사자처럼 부트캠프 TIL회고] 38일차 : 폭발통 만들기 (3) | 2024.12.29 |
[멋쟁이사자처럼 부트캠프 TIL회고] Unity 게임개발 3기 37일차 (0) | 2024.12.27 |