320x100
2018. 7. 30.
# 블럭 회전
var blockType = [
{
name: "O",
color: "skyblue",
shape: [[[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]]]
},
{
name: "S",
color: "gray",
shape: [
[[0, 0, 0, 0], [0, 0, 1, 1], [0, 1, 1, 0], [0, 0, 0, 0]],
[[0, 0, 1, 0], [0, 0, 1, 1], [0, 0, 0, 1], [0, 0, 0, 0]]
]
},
{
name: "Z",
color: "purple",
shape: [
[[0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 1, 1], [0, 0, 0, 0]],
[[0, 0, 0, 1], [0, 0, 1, 1], [0, 0, 1, 0], [0, 0, 0, 0]]
]
},
{
name: "I",
color: "red",
shape: [
[[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]],
[[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0]]
]
},
{
name: "T",
color: "yellow",
shape: [
[[0, 0, 0, 0], [0, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 0]],
[[0, 0, 1, 0], [0, 0, 1, 1], [0, 0, 1, 0], [0, 0, 0, 0]],
[[0, 0, 1, 0], [0, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]],
[[0, 0, 1, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0]]
]
},
{
name: "L",
color: "green",
shape: [
[[0, 0, 0, 0], [0, 1, 1, 1], [0, 1, 0, 0], [0, 0, 0, 0]],
[[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 1], [0, 0, 0, 0]],
[[0, 0, 0, 1], [0, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]],
[[0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0]]
]
},
{
name: "J",
color: "blue",
shape: [
[[0, 0, 0, 0], [0, 1, 1, 1], [0, 0, 0, 1], [0, 0, 0, 0]],
[[0, 0, 1, 1], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0]],
[[0, 1, 0, 0], [0, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]],
[[0, 0, 1, 0], [0, 0, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]]
]
}
];
this.rotation = function() {
this.eraseBeforeBlock(); // 모양 변경되기 전에꺼 지움
this.shapeIndex = (this.shapeIndex + 1) % this.type.shape.length;
this.shape = this.type.shape[this.shapeIndex];
this.drawBlock(this.x, this.y); // 모양 변경된거 그림
}
처음에는 블럭의 중심을 두고 그 회전 알고리즘을 짜서 블럭 모양을 변경하려고 했다. 그런데 블럭 배열이 홀수가 아니라서(끄응..;;) 생각보다 어려웠다. 그래서 그냥 4가지 방향의 블럭 모양을 하드코딩해서 배열에 때려박았다.
# 회전 시 블럭 충돌 체크
const NONE_DUPLICATED = 0; // 충돌 없음
const LEFT_DUPLICATED = 1; // 왼쪽 충돌
const RIGHT_DUPLICATED = 2; // 오른쪽 충돌
const EITHER_DUPLICATED = 3; // 왼쪽이나 오른쪽 충돌
this.isDuplicatedBlockOrOutOfGameScreen = function(x, y) {
for (var i = 0; i < SMALL_BLOCK_NUM; i++) {
for (var j = 0; j < SMALL_BLOCK_NUM; j++) {
var nx = x + i;
var ny = y + j;
if (this.shape[j][i] == 0) continue;
// out of game screen
if (nx < 0) {
console.log("LEFT DUPL");
return LEFT_DUPLICATED;
}
if (GAME_SCREEN_WIDTH_NUM < nx) {
console.log("RIGHT DUPL");
return RIGHT_DUPLICATED;
}
// duplicated another block
if (gameScreenArray[ny][nx] != -1) {
console.log("EITHER DUPL");
return EITHER_DUPLICATED;
}
}
}
return NONE_DUPLICATED;
};
this.rotation = function() {
this.eraseBeforeBlock();
this.shapeIndex = (this.shapeIndex + 1) % this.type.shape.length;
this.shape = this.type.shape[this.shapeIndex];
var checkDuplicated = this.isDuplicatedBlockOrOutOfGameScreen(
this.x,
this.y
);
// 모양 변경시 충돌이라면
if (checkDuplicated != NONE_DUPLICATED) {
var moveIndex = 0;
// 왼쪽으로 한 칸씩 움직이면서 충돌 확인
if (
checkDuplicated == LEFT_DUPLICATED ||
checkDuplicated == EITHER_DUPLICATED
) {
for (var i = 1; i < SMALL_BLOCK_NUM; i++) {
if (
this.isDuplicatedBlockOrOutOfGameScreen(
this.x + i,
this.y
) == NONE_DUPLICATED
) {
moveIndex = i;
break;
}
}
}
// 오른쪽으로 한 칸씩 움직이면서 충돌 확인
if (
checkDuplicated == RIGHT_DUPLICATED ||
checkDuplicated == EITHER_DUPLICATED
) {
for (var i = 1; i < SMALL_BLOCK_NUM; i++) {
if (
this.isDuplicatedBlockOrOutOfGameScreen(
this.x - i,
this.y
) == NONE_DUPLICATED
) {
moveIndex = -i;
console.log(-moveIndex);
break;
}
}
}
// 움직여도 다 충돌인 경우
if (moveIndex == 0) {
// 이전 모양으로 되돌리기
this.shapeIndex =
(this.shapeIndex + this.type.shape.length - 1) %
this.type.shape.length;
this.shape = this.type.shape[this.shapeIndex];
} else {
this.x += moveIndex;
}
}
this.drawBlock(this.x, this.y);
};
중요하게 생각했던게 다른 블럭도 마찬가지이지만 블럭의 방향을 변경했을 때 다른 블럭과의 충돌이 발생했을 때였다. (특히 I 블럭)
몇 개의 테트리스 게임을 탐색해본 결과 좌우 둘 중 하나 충돌인 경우 충돌되지 않게 안쪽으로 옮겨준다.
좌우 둘 다 충돌인 경우 변경되지 않는다.
변경한 경우 바닥충돌인 경우, 이 경우 경우의 수가 좀 더 다양했는데 어떤 곳은 변경될 수 있는 위치로 이동해서 블럭 모양을 변경한다. 어떤 경우는 변경되지 않는다. 나는 일단 변경할 수 없게 개발하기로 했다.
코드 리팩토링하고 디자인 고치고 점수 추가하는 등 추가할거는 아직 많지만 테트리스 기본기능은 거의 끝난 듯.
그리고 포매터 설정도 손 좀 봐야겠다..
깃허브
develop rotation block shape
Resolve conflict when block rotation
320x100
'Project > 테트리스' 카테고리의 다른 글
[테트리스] 8. 키보드 버튼 구현 (0) | 2019.08.27 |
---|---|
[테트리스] 7. 블럭 한 칸 구별, 스페이스 구현 (0) | 2019.08.27 |
[테트리스] 5. 다음블럭출력, 한 줄 삭제 (0) | 2019.08.27 |
[테트리스] 4. 블럭 간 경계 설정 (0) | 2019.08.27 |
[테트리스] 3. 테트리스 블럭 모양 만들기 (0) | 2019.08.27 |
댓글