반응형

웹 개발을 해보겠다고 예전에 학원을 다니면서 강사님과 같이 만들어봤던, 테트리스 예제가 있어서 약간의 소스 정리 후 포스팅을 하면 좋을 것 같아 테트리스 만들기 예제를 시작합니다.

 

테트리스 만들기 예제들을 찾아보면 캔버스값으로 처리하는 예제들이 많던데, 아직 캔버스 사용이 쉽지는 않은터라 게임치고는 UI가 엄청 화려하게 변화는 없는 테트리스정도는 html의 간단한 요소들로 충분히 표현이 가능하고 jquery나 다른 화려한 플러그인 없이 순수 javascript만으로 로직을 구성해서 표현할 수 있는 테트리스를 선택하게 되었습니다.

크게 구분하자면 배열데이터를 조작하고 매번 배열의 데이터를 검사하여 table요소를 통해 UI를 표현하는 형태로 진행할 예정입니다.

 

 

 


1. 작성을 위해 페이지 구성 & 배열 데이터 만들기 맵 그리기

 

페이지별 구성도

이러한 형태로 페이지들을 구성할 예정입니다.

메인이될 index.html 페이지

css를 꾸며줄 index.css

동작처리를 위한 index.js

전체 맵데이터, 테트리스 모양데이터를 담아놓을 tetris_data.js 로 구성하여 소스를 작성하겠습니다.

 

각각 소스들을 보도록 하겠습니다.

 

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="./css/index.css">
    <title>Tetris</title>
    <script src="./js/tetris_data.js"></script>
    <script src="./js/index.js"></script>
</head>
<body>
    <div id="container"></div>
</body>
</html>

사용할 index.html은 1개입니다.

tetris_data.js라는곳에는 전역으로 처리할 맵 배열과 테트리스 모양배열을 담아두고 실질적으로 돌아가는 코드 동작은 index.js에서 처리할 예정입니다.

 

tetris_data.js

//맵
var MAP=[
    [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4],       
    [4,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,2,2,2,2,2,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,2,2,2,2,2,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,2,2,2,2,2,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,2,2,2,2,2,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,2,2,2,2,2,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,0,0,0,0,0,0,0,0,0,0,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4],
    [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4]];

//테트리스 조각
var TETRIS=[
    [
        [//막대기
            [0,0,0,0],
            [1,1,1,1],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,0,0],
            [0,1,0,0],
            [0,1,0,0],
            [0,1,0,0]
        ],
        [
            [0,0,0,0],
            [1,1,1,1],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,0,0],
            [0,1,0,0],
            [0,1,0,0],
            [0,1,0,0]
        ]
    ],
    [
        [//ㄹ1
            [0,1,0,0],
            [0,1,1,0],
            [0,0,1,0],
            [0,0,0,0]
        ],
        [
            [0,0,1,1],
            [0,1,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,0,0],
            [0,1,1,0],
            [0,0,1,0],
            [0,0,0,0]
        ],
        [
            [0,0,1,1],
            [0,1,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ]
    ],
    [
        [//ㄹ2
            [0,0,1,0],
            [0,1,1,0],
            [0,1,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,1,0],
            [0,0,1,1],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,0,1,0],
            [0,1,1,0],
            [0,1,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,1,0],
            [0,0,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]
        ],
        [
            [0,0,0,1],
            [0,1,1,1],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,0,0],
            [0,1,0,0],
            [0,1,1,0],
            [0,0,0,0]
        ],
        [
            [0,1,1,1],
            [0,1,0,0],
            [0,0,0,0],
            [0,0,0,0]
        ]
    ],
    [
        [//ㄴ
            [0,1,1,0],
            [0,1,0,0],
            [0,1,0,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]
        ],
        [
            [0,1,1,1],
            [0,0,0,1],
            [0,0,0,0],
            [0,0,0,0]
        ]
    ],
    [
        [//ㅁ
            [0,1,1,0],
            [0,1,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,1,0],
            [0,1,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,1,0],
            [0,1,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,1,0],
            [0,1,1,0],
            [0,0,0,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,0,1,1],
            [0,0,1,0],
            [0,0,0,0]
        ],
        [
            [0,0,0,0],
            [0,1,1,1],
            [0,0,1,0],
            [0,0,0,0]
        ],
        [
            [0,0,1,0],
            [0,1,1,0],
            [0,0,1,0],
            [0,0,0,0]
        ]
    ]
];

- 전역변수 MAP 배열에 테트리스 맵 데이터를 담아놓고 그릴 배열입니다.

  > 2차원 배열

  > 4의 값은 게임의 보드를 표현할 값입니다.

  > 3은 테트리스 가이드 라인으로 처리할 값입니다.

  > 2번은 다음 테트리스 블럭을 표현할 테트리스맵으로 검은 배경을 처리할 값입니다.

  > 0번은 테트리스 블럭이 돌아다니는 테트리스맵으로 검은 배경을 처리할 값입니다.

 

- 전역변수 TETRIS는 테트리스 게임의 블럭들을 담아놓는 배열입니다. ㅡ, ㄱ, ㄴ, ㄹ, ㅁ, ㅗ 형태의 블럭을 회전 4회의 모양별로 담아두었습니다.

  > 3차원 배열[첫번째][두번째][세번째]

  > 첫번째 인덱스의 값은 테트리스의 모양을 구분합니다.

  > 두번째 인덱스의 값은 테트리스의 회전을 구분합니다.

  > 세번째 인덱스의 값은 맵의값인지 블럭의값인지 구분합니다.

 

index.js

맵과 테트리스의 블럭들을 그려봐야겠죠?

실질적으로 동작을 정의할 자바스크립트입니다.

var GX = 0; //블럭을 생성할 초기 위치 X
var GY = 3; //블럭을 생서할 초기 위치 Y
var NGY = 17;
var TURN = 0;
var TYPE = Math.round(Math.random()*6);
var NTYPE = Math.round(Math.random()*6);
var BLOCKTYPE=6, BLOCKROTATE=3;
var GAME_SPEED = 2000;
 
window.onload = function(){
    drawMap();
    drawNextTetris(NTYPE);
    myFunction();
}

function drawMap(){
    var rowLen = MAP.length;
    var tag = "<table>";
    var x = 0;
    var y = 0;
    for(var i=0; i<rowLen; i++){
        tag += "<tr>"
        var colLen = MAP[i].length;
        for(var j=0; j<colLen; j++){
            var className = "";
            var idValue = "";
            if(MAP[i][j] == 0){
                className = "map";
                idValue = "x"+(i-2)+"y"+(j-2);
            }else if(MAP[i][j] == 2){
                className = "map";
                idValue = "xn"+(i-1)+"yn"+(j-16);
            }else if(MAP[i][j] == 3){
                className = "guard";
            }else if(MAP[i][j] == 4){
                className = "board";
            }

            if(idValue != ""){
                tag += "<td id="+idValue+" class="+className+"></td>"
            }else{
                tag += "<td class="+className+"></td>"
            }
            
        }
        tag += "</tr>"
    }
    document.getElementById("container").innerHTML = tag + "</table>";
};

function ChangeColor(x, y, cN){
    document.getElementById("x"+x+"y"+y).className = cN;
}

//다음에 그려질 방향의 테트리스 그리기
function drawNextTetris(NTYPE){
    for(var x=0; x<4; x++){
        for(var y=0; y<4; y++){
            if(TETRIS[NTYPE][0][x][y] == 1){
                ChangeColor("n"+(x+1), "n"+y, "block"+NTYPE);                
            }
        }
    }
}

//테트리스 그리기
function drawTetris(GX, TYPE, TURN){
    for(var x=0; x<TETRIS[BLOCKTYPE][BLOCKROTATE].length; x++){
        for(var y=0; y<TETRIS[BLOCKTYPE][BLOCKROTATE][x].length; y++){
            if(TETRIS[TYPE][TURN][x][y] == 1){
                ChangeColor(x+GX, y+GY, "block"+TYPE);
            }
        }
    }
}

//동작을 초기화하고 입력값에 따라 그려줄 함수
function myFunction(input){
    //테트리스 블럭 그리기
    drawTetris(GX, TYPE, TURN);
}

drawMap이라는 함수는 페이지가 로드되면 실행되면서 MAP배열의 값을 불러와서 table을 그리고 각각 td값에 알맞는 클래스값을 지정하여 테트리스 게임의 맵처럼 표출시키는 함수 입니다.

ChangeColor함수는 전달받은 x,y같에 따라 클래스명을 처리해줍니다.

drawNextTetris는 다음으로 그려질 블럭을 그리는 함수입니다.

drawTetris함수는 테트리스 블럭을 특정 위치에 그리는 함수 입니다.

myFunction은 현재 기능적으로 정의된게 없지만 추후에 동작 정의나 초기값 설정등을 처리할 함수입니다.

 

index.css

마지막으로 디자인을 입혀야 게임다운 느낌이 들겠죠? index.css입니다.

table{
    margin: auto;
    border-collapse: collapse;
}

td{
    width: 18px;
    height: 18px;
    text-align:center;
    vertical-align:middle;
    outline: 0.5px solid #EAEAEA;
}

.board{
    background-color: #5f3dc4;
}
.guard{
    background-color: #91a7ff;
}
.map{
    background-color: #495057;
}
.ghost{
    background-color: #495057;
}

.block0{
    background-color: #f5f100;
}
.block1{
    background-color: #e64980;
}
.block2{
    background-color: #ae3ec9;
}
.block3{
    background-color: #7048e8;
}
.block4{
    background-color: #4263eb;
}
.block5{
    background-color: #1098ad;
}
.block6{
    background-color: #37b24d;
}
.block7{
    background-color: #f59f00;
}

 

css까지 작성하시고 페이지를 열어보시면 이러한 기본 준비가 완성되어 있을겁니다.

 

 

다음장부터는 index.js에서 정의 동작을 수정하고 추가하면서 진행하다보면 어느새 완성된 테트리스를 만나볼 수 있을겁니다. 계속해서 진행해보겠습니다.

반응형