[테트리스2] 블럭 그리기, 블럭 내리기
안녕하세요. 컴퓨터못하는 컴퓨터공학생입니다.
이번 시간에는 배경에 블록을 그리고 블록이 내려오는 기능에 대해 살펴보려 합니다.
블록은 총 7가지 종류가 있습니다.
위의 그림처럼 블럭 모양 및 색을 사용하겠습니다.
위의 블록을 배열에 미리 저장하여 사용합니다. 저는 TPoint 형 3차원 배열을 선언해서 사용하였습니다.
TPoint는 다음과 같이
1 2 3 4 5 6 | type TPoint = record _iX : integer; _iY : integer; end; | cs |
정의 하였습니다.
_iX와 _iY는 각각 x,y좌표를 나타냅니다.
각각의 블록은 미리 배열에 저장해 두겠습니다.
1 2 3 4 5 6 7 8 9 10 11 | shape : array[0..6, 0..3, 0..3] of TPoint = ( ( ( (_iX : 0; _iY : 0), (_iX : 0; _iY : 1), (_iX : 0; _iY : 2), (_iX : 1; _iY : 2) ), // L ( (_iX : 2; _iY : 0), (_iX : 2; _iY : 1), (_iX : 1; _iY : 1), (_iX : 0; _iY : 1) ), ( (_iX : 0; _iY : 0), (_iX : 1; _iY : 0), (_iX : 1; _iY : 1), (_iX : 1; _iY : 2) ), ( (_iX : 0; _iY : 0), (_iX : 0; _iY : 1), (_iX : 1; _iY : 0), (_iX : 2; _iY : 0) ) ), //생략 ); | cs |
위는 L자 모양의 블록을 정의한 내용입니다.
변경했을 때의 블록 모양도 정의하여 총 4개로 정의하였습니다.
블록을 그리기 위해 블록 색깔을 정해둡니다.
1 2 | BlockColor : array [0..8] of TColor = ($00A5FF, $E96AE9, $09D9D9, $D9D909, $FF5900, $09D909, $4949EE, clBlack, clSilver ); | cs |
델파이는 RGB가 아닌 BGR로 하기 때문에 $00A5FF는 L자 블록 모양의 색인 주황색 입니다.
블록을 그릴때는 다음과 같이 함수를 사용합니다.
1 2 3 4 5 6 7 8 9 10 11 | for i := 0 to 3 do begin MCanvas.brush.Color := BlockColor[iBrickIndex]; MCanvas.Pen.Style := psClear; MCanvas.Rectangle( (shape[iBrickIndex][iBrickRotation][i]._iX * 15) + iXY + ( 15 * 5 ), (shape[iBrickIndex][iBrickRotation][i]._iY * 15) + iDown + 15, (shape[iBrickIndex][iBrickRotation][i]._iX * 15) + 15 + iXY + ( 15 * 5 ), (shape[iBrickIndex][iBrickRotation][i]._iY * 15) + iDown + 15 + 15 ); end; | cs |
iBrickIndex 값은 이 함수 실행전 어떤 블록을 선택할건지의 인덱스 값입니다.
iBrickRotation 변수는 초기에 어떤모양의 블록을 내릴건지의 인덱스 값입니다.
15는 블록한칸의 가로, 세로 길이입니다.
iXY 변수는 현재 블록의 가로 좌표 위치를 나타냅니다. 초기값은 0입니다.
(15*5)는 15는 블록의 한변의 길이이고, 5는 총 가로길이의 중간을 나타냅니다.
초기 시작시에 블록이 중간에서 내려오기 위해서입니다.
iDown 변수는 세로 좌표 위치를 나타냅니다. 초기값은 0입니다.
정리하자면 중간에 블록 4개 그리는 함수입니다.
글이 많아서 설명이 어려울 수 있는데 댓글로 남겨주세요.
블록을 한칸 내리기 위해서는 블록 바로 아래에 벽이 있는지, 다른 블록이 쌓여있는지 확인을 해봐야 합니다.
확인하는 함수는 다음과 같이 사용합니다.
CheckBrick(iXY, iDown+15)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | function TFrmMain.CheckBrick(x,y : integer) : Boolean; var i, j : integer; begin j := 0; for i := 0 to 3 do begin j := max( j, board[ 5 + (x div 15) + shape[iBrickIndex][iBrickRotation][i]._iX ] [ 1 + (y div 15) + shape[iBrickIndex][iBrickRotation][i]._iY ] [ 1 ] ); end; // 벽돌이나 가장자리이면 if (j = 1) or (j = 2) then result := False else result := True; end; | cs |
여기서 x의 값은 가로에서 어느 위치인지를 나타냅니다.
y는 세로에서 어느 위치인지를 나타냅니다.
board배열 첫 번째에 5를 더하는 이유는 블록의 시작이 왼쪽 위가 아닌 중간에서 시작하기 때문입니다.
중간의 위치는 총 10의 길이에서 반인 5입니다.
board배열 첫 번째에 1을 더하는 이유는 제일 위에 블록이 벽이기 때문에 한칸 밑부터 시작하려고 1을 더합니다.
나누기 15를 하는 이유는 x의 값은 블록의 가로/세로 길이이기 때문에 15로 나누어서 상대적인 위치를 가져옵니다.
CheckBrick(iXY, iDown+15) 다음과 같이 함수를 실행합니다. iXY, iDown는 현재 가로세로의 위치를 나타냅니다.
이제 블럭을 한칸씩 내려보겠습니다.
블럭을 내리기 위해서는 기존의 블럭을 지우고, 바로 한칸 아래에 블럭을 그려야 합니다.
1 2 3 4 5 6 7 8 9 10 | for i := 0 to 3 do begin MCanvas.brush.Color := clSilver; MCanvas.Pen.Style := psClear; MCanvas.Rectangle( (shape[iBrickIndex][iBrickRotation][i]._iX * 15) + iXY + ( 15* 5 ), (shape[iBrickIndex][iBrickRotation][i]._iY * 15) + iDown + 15, (shape[iBrickIndex][iBrickRotation][i]._iX * 15) + 15+ iXY + ( 5* 5), (shape[iBrickIndex][iBrickRotation][i]._iY * 15) + iDown + 5+ 15 ); end; | cs |
지우는 방식은 현재 블럭의 위치를 벽색깔인 회색으로 덮어 씌웁니다. Color만 다르고 위의 함수와 동일하기 때문에 설명은 생략하겠습니다.
그리고 iDown의 변수를 +15(블록 크기) 한 뒤 다시 위의 함수를 호출하면 한칸 아래로 내려온것 처럼 보입니다.
간단하게 정리하자면 초기에는 블록을 그리기 전에 바로 밑에 블록인지 체크 한 뒤 블록을 그립니다.
그릴수 있다면 블록을 그리고 그릴수 없다면 블록이 초기상태까지 쌓였기 때문에 게임 종료입니다.
초기가 아니라면 블록을 그리고 블록을 한칸 내리기 위해 다시한번더 밑에 블록이 있는지 체크를 합니다.
없다면 블록을 내리고 있다면 블록을 쌓습니다.
정리하거나 표현하는게 서툴러 이해가 되지 않을 수도 있지만, 일단 저는 알고 보니 이해가 되서..
다음에는 블록 변경하는거에 대해서 살펴보겠습니다.
감사합니다.
'IT > 프로젝트' 카테고리의 다른 글
[테트리스5] 테트리스 소스 (0) | 2016.11.02 |
---|---|
[테트리스4] 블럭 쌓기. 한줄 지우기 (0) | 2016.11.01 |
[테트리스3] 블럭 변경하기 (0) | 2016.11.01 |
[테트리스1] 개요, 설계, 화면구성 (0) | 2016.10.28 |