분류 javascript

테트리스 턴 35 (3)

컨텐츠 정보

  • 조회 267 (작성일 )

본문

function erase() {    let index = 0;    if (position.x >= 0 && position.x <= width - 1) {
if (position.y >= -3 && position.y <= height - 1) {
for (let y = position.y; y < position.y + 3; y++) {
for (let x = position.x; x < position.x + 3;
x++, index++) {
if (current[index] == 1) {
let id = "square_x" + x + "y" + y;
let square = document.getElementById(id);
if (square) {
if (true) { // well[x] && well[y]
well[x][y] = 0;
if (x == 0 || x == width - 1 ) { }
else {
square.style.backgroundColor
= color.background;
}
}
}
}
}
}
}
}
}


타락한 블록을 우물에 붙여 넣기 


블록이 "타락"한 것으로 간주되면 블록이 물리적으로 웰 어레이에 붙여집니다.


이 솔리드 블록은 well 배열에서 1이 됩니다. 이것은 다음 번에 다음 테트로미노에서 충돌을 검사 할 때 (위에서 이미 작성한 충돌 감지 알고리즘을 사용하여)이 영역은 솔리드로 간주되며  블록은 다른 블록과 충돌합니다.


1*bpJKZos2FyqboQ89YbnbPw.gif 

벽돌이 벽이나 다른 벽돌과 충돌하면 우물에“붙여 넣기”되어 고체로 표시됩니다.


행 분리 알고리즘 


이것은 테트리스와 관련하여 가장 복잡한 코드입니다. 이 알고리즘은 

1) 제거 할 행이 있는지 확인합니다. 

2) 전체 행을 제거하지 않고 웰을 다시 빌드하여 취소하고 블록 축소 환상을 만듭니다.


내 버전에서는 블록이 지워진 것을 시각적으로 명확하게 하기 위해 강조 애니메이션을 추가했습니다. 이 데모의 최종 버전에서 볼 수 있습니다.


단 몇 줄의 코드 로이 기능을 최적화 된 미친 버전으로 만들 수 있습니다. 그러나 그렇게 하면 논리가 추상화 되어 따르고 배우기가 어려워 질 것입니다.


배열 및 for 루프와 같은 간단한 JavaScript 구문을 사용하여 논리를 살펴 보는 것이 좋습니다. 나중에 코드를 더 짧게 만들도록 최적화 할 수 있습니다.


// Check if a row needs to be cleared
function clear_row() {

// Placeholder for new rows
let placeholder = [];

// How many rows cleared?
let rows_cleared = 0;

// Scan the well one row at a time and capture any
// non-filled rows in placeholder
// (except the last row)

for (let y = 0; y < height - 1; y++) {
let start = y * width;
let scanned = scan_row(y);
let total = scanned[0];
let row_data = scanned[1];
// Skip all horizontal rows that are completely filled
if (total != width) {
// Memorize only uncleared rows
let len = placeholder.length;
placeholder[len] = row_data;
} else {
start_highlight(y);
rows_cleared++;
}
}

// If at least one row was cleared, update the well
if (rows_cleared > 0) {
// Clear the well, except last row (well's bottom)
for (let y = 0; y < height - 1; y++) {
// Clear all except walls ([0] and [width - 1])
for (let x = 1; x < width - 1; x++) {
well[x][y] = 0;
// Paint empty square
let square =
document.getElementById("square_x" + x + "y" + y);
if (square)
square.style.backgroundColor = color.background;
}
}

// Paste captured placeholder rows onto the well
// but from bottom up

let r = height - 2;
for (let i = placeholder.length - 1; i > 0; i--) {
let row = placeholder[i];
for (let x = 0; x < width; x++) {
if (row[x] != 0) {
well[x][r] = 3;
if (x != 0 && x != width - 1) {
let square =
document.getElementById("square_x"+x+"y"+r);
if (square)
square.style.backgroundColor = color.solid;
}
}
}
r--;
}
}
}


테트리스 인 더 다크 (소스 코드에 포함되어 있습니다!)


전략 비디오 게임에는 전쟁이 필요합니다. 탐험 되지 않은 지형 영역을 검게 표시합니다.


빛 추가 


밝은 점을 만들기 위해 먼저 우물과 동일한 치수를 공유하는 보조 그리드를 만들어 오버레이로 사용했습니다. 기본적으로 해당 그리드의 모든 DIV 사각형은 검은 색과 불투명도 1로 설정되었습니다.


보조 그리드의 각 사각형에는 fog_x1y3의 ID가 할당되었습니다 (해당 그리드의 x = 1 및 y = 3에서 사각형에 액세스하려는 경우).


그런 다음 라이트 스팟 데이터를 별도의 배열에 저장했습니다.


// light position
let light = { x: 0, y: 0 };
// lightspot data
let light_mask = [
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,4,4,0,0,0,0,0,0,
0,0,0,2,3,4,5,5,4,3,2,0,0,0,
0,0,2,3,4,5,6,6,5,4,3,2,0,0,
0,2,3,4,5,6,7,7,6,5,4,3,2,0,
0,3,4,5,6,7,8,8,7,6,5,4,3,0,
0,4,5,6,7,8,9,9,8,7,6,5,4,0,
0,4,5,6,7,8,9,9,8,7,6,5,4,0,
0,3,4,5,6,7,8,8,7,6,5,4,3,0,
0,2,3,4,5,6,7,7,6,5,4,3,2,0,
0,0,2,3,4,5,6,6,5,4,3,2,0,0,
0,0,0,2,3,4,5,5,4,3,2,0,0,0,
0,0,0,0,0,0,4,4,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
];


여기서 0에서 9 사이의 값은 0.0-0.9 CSS 불투명도를 나타냅니다.


이번에는 draw_light() 함수를 사용하여 간단한 for-loop를 사용하여 이 데이터를 어두운 격자에 붙여 넣었습니다.


function draw_light() {
let index = 0;
for (let y = 0; y < 14; y++) {
for (let x = 0; x < 14; x++, index++) {
let posx = x + position.x;
let posy = y + position.y;
let id = "fog_x" + (posx - 6) + "y" + (posy - 6);
let square = document.getElementById(id);
if (square) {
let type = light_mask[index];
if (type == 9) square.style.opacity = '0';
if (type == 8) square.style.opacity = '0.1';
if (type == 7) square.style.opacity = '0.2';
if (type == 6) square.style.opacity = '0.3';
if (type == 5) square.style.opacity = '0.4';
if (type == 4) square.style.opacity = '0.5';
if (type == 3) square.style.opacity = '0.7';
if (type == 2) square.style.opacity = '0.8';
if (type == 1) square.style.opacity = '0.9';
if (type == 0) square.style.opacity = '1.0';
}
}
}
} 


이로 인해 빛이 어둠으로 사라지는 환상이 생겼습니다.


주요 행 애니메이션 


행 구분 애니메이션은 다른 모든 것과 별도로 수행됩니다. 우물의 모든 높이에서 긴 수평 DIV 요소의 목록 일 뿐입니다.


행을 끊어야 할 경우 clear_row () 함수 (앞에 표시)는 지워야 하는 각 행의 Y 좌표를 추적합니다.


그런 다음 setInterval 함수는 해당 DIV의 상태가 1인지 판별합니다. 그렇다면 DIV를 흰색 배경색으로 설정하고 시간에 따른 불투명도를 줄여 애니메이션을 재생합니다.


1*XIqveUj5SsZ1Ko01HfRQQQ.gif 


최종 결과 


같은 주제를 오랫동안 사용하면 약간 지루 해져 깨어나는 혁신을 하게 됩니다.


결론 : 게임 개발자로서 나는 약간의 전쟁의 안개를 추가하여 이 재미있는 버전의 테트리스를 만들기로 결정했습니다. 모든 실험이 좋은 것은 아닙니다. 그러나 결과에 매우 만족합니다.


소스 코드? Tetris GitHub 리포지토리에서 가져올 수 있습니다.