제 2강 Map and Player Movement 맵과 플레이어 움직임
2.1 Defining the 2D Map Grid 2D 맵 그리드 정의하기
2.2 Coding the Map Class 맵 클래스 코딩하기!
2.3 Player Movement 플레이어 움직임
2.4 Coding the Player Movement 플레이어 움직임 코딩하기!
2.E Exercise: Map Collision 맵 충돌 기능
2.5 Implementing Map Collision 맵 충돌 기능 구현하기!
2.1 Defining the 2D Map Grid 2D 맵 그리드 정의하기
맵 정의하기
지금 저희는 맵과 ROW, COL 등을 정의해놓았으나
cub3d 과제를 진행할 때는 .cub 파일에 넣고 row와 col도 동적으로 계산해야합니다.
const TILE_SIZ = 32;
const MAP_ROWS = 11;
const MAP_COLS = 15;
class Map {
walls = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
];
}
Javascript로 코딩 시작!
폴더 구조입니다.
지금은 화면으로 쉽게 확인하기 위해서 html방식으로 간단하게 프로토타입만 제작할 것이며,
이제부터 작성한 모든 코드는 github에 업로드 하겠습니다!
p5.js는 그림을 쉽게 그리기 위한 js 라이브러리이며 p5js.org/에서 다운받았습니다.
2.2 Coding the Map Class 맵 클래스 코딩하기!
github룰 참고하세요! 직접 실행시켜보시고 디버깅하시는 걸 추천드립니다.
const TILE_SIZE = 32;
const MAP_NUM_ROWS = 11;
const MAP_NUM_COLS = 15;
const WINDOW_WIDTH = MAP_NUM_COLS * TILE_SIZE; // how many columns
const WINDOW_HEIGHT = MAP_NUM_ROWS * TILE_SIZE; // how many rows
class Map {
constructor()
{
this.grid = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
}
render()
{
for (var i=0; i<MAP_NUM_ROWS; i++)
{
for (var j=0; j<MAP_NUM_COLS; j++)
{
var tileX = j * TILE_SIZE;
var tileY = i * TILE_SIZE;
var tileColor = this.grid[i][j] == 1 ? "#222" : "#fff";
stroke("#222");
fill(tileColor);
rect(tileX, tileY, TILE_SIZE, TILE_SIZE);
}
}
}
}
var grid = new Map();
// TODO: initialize all objects 모든 오브젝트 초기화하기
function setup()
{
createCanvas(WINDOW_WIDTH, WINDOW_HEIGHT);
}
// TODO: update all game objects before we render the next frame 다음 프레임을 렌더링 하기 전에 모든 게임 오브젝트를 업데이트
function update()
{
}
// TODO: render all objects frame by frame 모든 개체를 프레임 별로 렌더링
function draw()
{
// 언제나 업데이트 후 시작
update();
grid.render();
}
2.3 Player Movement 플레이어 움직임
// Player의 클래스 정의
class Player
{
x;
y;
// radius
rad;
// turnDirection : -1(left), 1(right), 0(nothing to update) : 실제 각도가 아니라 왼쪽인지 오른쪽인지만.
dir_turn = 0;
// walkDirection : -1(back), 1(front), 0(nothing to update) : 실제 각도가 아니라 앞인지 뒤인지만.
dir_walk = 0;
// rotationAngle : PI = 180도, PI/2 = 90도
ang_rota = Math.PI / 2;
// moveSpeed 움직이는 속도
spd_move = 3.0;
// rotationSpeed : 3도씩 회전
spd_rota = 3 * (MATH.PI / 180);
}
2.E Exercise: Map Collision 맵 충돌 기능
2.5 Implementing Map Collision 맵 충돌 기능 구현하기!
github.com/KKWANH/cub3d_kkim/tree/main/P2_Collision
const TILE_SIZ = 32;
const MAP_ROWS = 11;
const MAP_COLS = 15;
const WIND_WID = MAP_COLS * TILE_SIZ; // how many columns
const WIND_HEI = MAP_ROWS * TILE_SIZ; // how many rows
var x_now = 5;
var y_now = 8;
class Map {
constructor()
{
this.grid = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
}
hasWallAt(posX, posY)
{
var mapIdxX = Math.floor(posX / TILE_SIZ);
var mapIdxY = Math.floor(posY / TILE_SIZ);
return (this.grid[mapIdxY][mapIdxX] != 0);
}
render()
{
for (var i=0; i<MAP_ROWS; i++)
{
for (var j=0; j<MAP_COLS; j++)
{
var tileX = j * TILE_SIZ;
var tileY = i * TILE_SIZ;
var tileColor = this.grid[i][j] == 1 ? "#222" : "#fff";
stroke("#222");
fill(tileColor);
rect(tileX, tileY, TILE_SIZ, TILE_SIZ);
}
}
}
}
class Player
{
constructor()
{
this.x = WIND_WID / 2;
this.y = WIND_HEI / 2;
this.rad = 3;
this.dir_turn = 0; // turnDirection : -1(left), 1(right), 0(nothing to update) : 실제 각도가 아니라 왼쪽인지 오른쪽인지만.
this.dir_walk = 0; // walkDirection : -1(back), 1(front), 0(nothing to update) : 실제 각도가 아니라 앞인지 뒤인지만.
this.ang_rota = Math.PI / 2; // rotationAngle : PI = 180도, PI/2 = 90도s
this.spd_move = 3.0; // moveSpeed 움직이는 속도
this.spd_rota = 3 * (Math.PI / 100); // rotationSpeed : 3도씩 회전
}
// TODO: update player position based on turnDirection and walkDirection
update()
{
this.ang_rota += this.dir_turn * this.spd_rota;
var moveStep = this.dir_walk * this.spd_move;
var newPosiX = this.x + Math.cos(this.ang_rota) * moveStep;
var newPosiY = this.y + Math.sin(this.ang_rota) * moveStep;
// 벽이 아닐 경우 (충돌하지 않을 경우) 에만 플레이어 놓기
if (!grid.hasWallAt(newPosiX, newPosiY))
{
this.x = newPosiX;
this.y = newPosiY;
}
}
render()
{
noStroke();
// 위치
fill("red");
circle(this.x, this.y, this.rad);
// 라인
stroke("red");
line(
this.x,
this.y,
this.x + Math.cos(this.ang_rota) * 30,
this.y + Math.sin(this.ang_rota) * 30
);
}
}
var grid = new Map();
var player = new Player();
// TODO :
function keyPressed()
{
if (keyCode == UP_ARROW) {
player.dir_walk = +1;
} else if (keyCode == DOWN_ARROW) {
player.dir_walk = -1;
} else if (keyCode == RIGHT_ARROW) {
player.dir_turn = +1;
} else if (keyCode == LEFT_ARROW) {
player.dir_turn = -1;
}
}
function keyReleased()
{
if (keyCode == UP_ARROW) {
player.dir_walk = 0;
} else if (keyCode == DOWN_ARROW) {
player.dir_walk = 0;
} else if (keyCode == RIGHT_ARROW) {
player.dir_turn = 0;
} else if (keyCode == LEFT_ARROW) {
player.dir_turn = 0;
}
}
// TODO: initialize all objects 모든 오브젝트 초기화하기
function setup()
{
createCanvas(WIND_WID, WIND_HEI);
}
// TODO: update all game objects before we render the next frame 다음 프레임을 렌더링 하기 전에 모든 게임 오브젝트를 업데이트
function update()
{
player.update();
}
// TODO: render all objects frame by frame 모든 개체를 프레임 별로 렌더링
function draw()
{
// 언제나 업데이트 후 시작
update();
grid.render();
player.render();
}
여기까진 P2_Collision에 최종 구현되었습니다.
'42Seoul > cub3d' 카테고리의 다른 글
Cub3d 학습일지 - 4 - 벽 영상 렌더링하기 (0) | 2021.01.01 |
---|---|
Cub3d 학습일지 - 3 - 레이캐스팅 (0) | 2020.12.30 |
Cub3d 학습일지 - 1 - 삼각법 리뷰하기 (1) | 2020.12.28 |
Cub3d 학습일지 - 0 - Introduction (0) | 2020.12.27 |
Cub3d - 서브젝트 분석하기 (0) | 2020.12.27 |
Comment