Skip to content

Commit

Permalink
resolved #18.블록 이동, 바닥에 도달했을 때 로직 개선
Browse files Browse the repository at this point in the history
  • Loading branch information
fpdjsns committed Feb 28, 2022
1 parent bbe340b commit c51c2cd
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 126 deletions.
237 changes: 141 additions & 96 deletions Tetris/js/block.js
@@ -1,72 +1,56 @@
function Point(x, y) {
this.x = x;
this.y = y;
}

Point.prototype.isEquals = function (x, y) {
return this.x == x && this.y == y;
}

Point.prototype.isLower = function (x, y) {
return this.y < y;
};

class Block {

constructor(blockTypeIndex, x, y) {
this.typeIndex = blockTypeIndex;
this.type = blockType[this.typeIndex];
this.shape = [...this.type.shape];
this.blockNum = this.shape.length
this.x = x;
this.y = y;

this.position = new Point(x, y)
this.bottomPosition = new Point(x, y)
this.isLoaded = false;

this.setPreviewCoordinate()
}

// === private ===
drawPreview() {
for (let k = 0; ; k++) {
if (this.isBottom(this.x, this.y + k + 1)) {
this.justDrawBlock(this.x, this.y + k, 'gray');
return;
}
}
this.justDrawBlock(this.bottomPosition.x, this.bottomPosition.y, 'gray');
}

erasePreview() {
for (let k = 0; ; k++) {
if (this.isBottom(this.x, this.y + k + 1)) {
this.eraseBlock(this.x, this.y + k);
return;
}
}
this.eraseBlock(this.bottomPosition.x, this.bottomPosition.y);
}

drawLeftOrRight(nx, ny) {
const isDuplicated = this.isDuplicatedBlockOrOutOfGameScreen(nx, ny);
if (isDuplicated != NONE_DUPLICATED) {
console.log("duplicated!");
} else {
this.eraseBeforeBlock();
this.drawBlock(nx, ny);
}
moveLeftOrRight(nx, ny) {
this.move(nx, ny)
timer.refreshBottomTemp();
}

checkRowsAndErase() {
checkRowsAndErase(
this.y,
Math.min(
GAME_SCREEN_HEIGHT_NUM - 1,
this.y + this.blockNum - 1
)
);
}

drawDown(nx = this.x, ny = this.y + 1) {
if (this.isBottom(nx, ny)) {
timer.startBottom();
timer.startBottomTemp();
} else {
this.eraseBeforeBlock();
this.drawBlock(nx, ny);
timer.stopBottom();
timer.stopBottomTemp();
setPreviewCoordinate() {
for (let k = 0; ; k++) {
if (this.isBottom(this.position.x, this.position.y + k + 1)) {
this.bottomPosition.x = this.position.x
this.bottomPosition.y = this.position.y + k
return;
}
}
}

eraseBeforeBlock() {
this.erasePreview();
this.eraseBlock();
}

eraseBlock(x = this.x, y = this.y) {
eraseBlock(x = this.position.x, y = this.position.y) {
for (let i = 0; i < this.blockNum; i++) {
for (let j = 0; j < this.blockNum; j++) {
if (this.shape[i][j] == 1) {
Expand All @@ -76,7 +60,7 @@ class Block {
}
}

justDrawBlock(x = this.x, y = this.y, colorName = undefined) {
justDrawBlock(x = this.position.x, y = this.position.y, colorName = undefined) {
for (let i = 0; i < this.blockNum; i++) {
for (let j = 0; j < this.blockNum; j++) {
if (this.shape[i][j] == 1) {
Expand All @@ -90,26 +74,14 @@ class Block {
}
}

drawBlock(x, y) {
this.x = x;
this.y = y;

// this.erasePreview(this.x, this.y);
this.drawPreview();

// Change colors just before drawing to avoid affecting the previous or next block color.
this.justDrawBlock();
isDuplicatedBlockOrOutOfGameScreen(x, y, shape = this.shape) {
let checkShape = shape;

}

isDuplicatedBlockOrOutOfGameScreen(x, y, block) {
var checkShape = this.shape;
if (block != undefined) checkShape = block;
for (let i = 0; i < this.blockNum; i++) {
for (let j = 0; j < this.blockNum; j++) {
const nx = x + i;
const ny = y + j;

for (var i = 0; i < this.blockNum; i++) {
for (var j = 0; j < this.blockNum; j++) {
var nx = x + i;
var ny = y + j;
if (checkShape[j][i] == 0) continue;

// out of game screen
Expand All @@ -119,6 +91,9 @@ class Block {
if (GAME_SCREEN_WIDTH_NUM < nx) {
return RIGHT_DUPLICATED;
}
if (GAME_SCREEN_HEIGHT_NUM <= ny) {
return BOTTOM_DUPLICATED;
}
// duplicated another block
if (gameScreenArray[ny] != undefined && gameScreenArray[ny][nx] != -1) {
return EITHER_DUPLICATED;
Expand All @@ -128,7 +103,78 @@ class Block {
return NONE_DUPLICATED;
}

isBottom(x, y) {
// 블럭을 nx, ny로 움직일 때 실행
// 블럭이 성공적으로 (nx, ny)로 움직였는지 boolean 값 반환
move(nx, ny, shape = this.shape) {
let moved = false

// 움직일 수 있는 곳인지 체크 가능하지 않다면
if (this.isDuplicatedBlockOrOutOfGameScreen(nx, ny) != NONE_DUPLICATED) {
console.log("duplicated!");
} else {
// bottom 좌표 갱신
this.eraseBeforeBlock();

// bottom 좌표와 동일한지 체크( = 바닥인지 체크)
if (this.bottomPosition.isLower(nx, ny)) {
ny = this.bottomPosition.y
} else {
// move
this.shape = shape;
moved = true
}

this.drawBlock(nx, ny)
}

return moved;
}

// position의 갱신은 해당 함수에서만 이루어진다.
drawBlock(x, y) {
this.position.x = x
this.position.y = y

this.setPreviewCoordinate()
this.drawPreview();
this.justDrawBlock();
}

// public
moveLeft() {
this.moveLeftOrRight(this.position.x - 1, this.position.y)
}

moveRight() {
this.moveLeftOrRight(this.position.x + 1, this.position.y)
}

checkRowsAndErase() {
checkRowsAndErase(
this.position.y,
Math.min(
GAME_SCREEN_HEIGHT_NUM - 1,
this.position.y + this.blockNum - 1
)
);
}

drawDown(nx = this.position.x, ny = this.position.y + 1) {
if (!this.move(nx, ny)) {
timer.startBottom();
timer.startBottomTemp();
} else {
timer.stopBottom();
timer.stopBottomTemp();
}
}

eraseBeforeBlock() {
this.erasePreview();
this.eraseBlock();
}

isBottom(x = this.position.x, y = this.position.y) {
for (let i = 0; i < this.blockNum; i++) {
for (let j = 0; j < this.blockNum; j++) {
const nx = x + i;
Expand All @@ -142,38 +188,36 @@ class Block {
return false;
}

// shape 갱신
rotation() {
this.eraseBeforeBlock();
const length = this.shape.length;
const nextShape = [];
for (let i = 0; i < length; i++) nextShape[i] = [];

for (let i = 0; i < length; i++)
for (let j = 0; j < length; j++)
nextShape[length - 1 - j][i] = this.shape[i][j];

var checkDuplicated = this.isDuplicatedBlockOrOutOfGameScreen(
this.x,
this.y,
nextShape
);
const nextShape = getRotateShape(this.shape);

const originPosition = this.position
let nx = this.position.x
let ny = this.position.y

let checkDuplicated = this.isDuplicatedBlockOrOutOfGameScreen(nx, ny, nextShape);

let rotatable = true;

// 충돌한 곳이 있다면
if (checkDuplicated != NONE_DUPLICATED) {
var moveIndex = 0;
rotatable = false;
// 왼쪽 면이 중복이거나 다른 블록가 중복이라면
if (
checkDuplicated == LEFT_DUPLICATED ||
checkDuplicated == EITHER_DUPLICATED
) {
for (i = 1; i < this.blockNum; i++) {
for (let i = 1; i < this.blockNum; i++) {
if (
this.isDuplicatedBlockOrOutOfGameScreen(
this.x + i,
this.y,
originPosition.x + i,
originPosition.y,
nextShape
) == NONE_DUPLICATED
) {
moveIndex = i;
rotatable = true;
nx = originPosition.x + i;
break;
}
}
Expand All @@ -185,27 +229,28 @@ class Block {
for (let i = 1; i < this.blockNum; i++) {
if (
this.isDuplicatedBlockOrOutOfGameScreen(
this.x - i,
this.y,
originPosition.x - i,
originPosition.y,
nextShape
) == NONE_DUPLICATED
) {
moveIndex = -i;
rotatable = true;
nx = originPosition.x - i;
break;
}
}
}

if (moveIndex == 0) { // x축을 움직여도 안되는경우 회전하지 않음
rotatable = false;
} else { // x축을 움직인다.
this.x += moveIndex;
}
// x축을 움직여도 안되는경우 회전하지 않음
}

if (rotatable) {
this.shape = nextShape.slice();
this.move(nx, ny, nextShape.slice());
}
this.drawBlock(this.x, this.y);
}

moveBottom() {
this.move(this.bottomPosition.x, this.bottomPosition.y)
}

}
14 changes: 12 additions & 2 deletions Tetris/js/blockType.js
Expand Up @@ -41,6 +41,16 @@ const blockTypeMap = blockType.reduce((map, type, index, array) => {
return map;
}, new Map());

var getBlockTypeIndex = function(blockType) {
function getRotateShape(shape) {
const length = shape.length
const nextShape = [];
for (let i = 0; i < length; i++) nextShape[i] = [];
for (let i = 0; i < length; i++)
for (let j = 0; j < length; j++)
nextShape[length - 1 - j][i] = shape[i][j];
return nextShape;
}

var getBlockTypeIndex = function (blockType) {
return blockTypeMap[blockType.name];
}
}
3 changes: 2 additions & 1 deletion Tetris/js/constants.js
Expand Up @@ -32,6 +32,7 @@ const NONE_DUPLICATED = 0;
const LEFT_DUPLICATED = 1;
const RIGHT_DUPLICATED = 2;
const EITHER_DUPLICATED = 3;
const BOTTOM_DUPLICATED = 4;

const LINE_COLOR = "gray";

Expand All @@ -41,4 +42,4 @@ const BLOCK_BOTTOM_TEMP_TIMEOUT = 500; // 0.5sec
const SPEED_UP_INTERVAL = 10000; // 10sec
const SPEED_UNIT_PERCENT = 0.9; // 90%

const CANVAS_BORDER_LINE_WIDTH = 2;
const CANVAS_BORDER_LINE_WIDTH = 2;

0 comments on commit c51c2cd

Please sign in to comment.