제 7강 Map and Player Movement 맵과 플레이어 움직임
2.1. Drawing the Map with SDL. SDL로 맵 그리기
2.2. Player Movement and SDL Events. 플레이어 움직임과 SDL 이벤트
2.E. Excerise: Wall Collision in C. C언어로 벽 충돌 구현하기
2.3. Implementing Wall Collision in C. C언어로 벽 충돌 구현하기
2.1. Drawing the Map with SDL. SDL로 맵 그리기
2.2. Player Movement and SDL Events. 플레이어 움직임과 SDL 이벤트
2.E. Excerise: Wall Collision in C. C언어로 벽 충돌 구현하기
2.3. Implementing Wall Collision in C. C언어로 벽 충돌 구현하기
#include "constants.h"
#include <stdio.h>
const int map[MAP_NUM_ROWS][MAP_NUM_COLS] =
{
{ 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 1},
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{ 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1},
{ 1, 0, 0, 0, 0, 0, 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, 0, 0, 1, 0, 0, 1},
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1},
{ 1, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 1},
{ 1, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1}
};
struct Player
{
float x;
float y;
float width;
float height;
int turnDirection; // -1 for left, +1 for right
int walkDirection; // -1 for back, +1 for front
float rotationAngle;
float walkSpeed;
float turnSpeed;
} player;
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
int isGameRunning = FALSE;
int ticksLastFrame;
int initializeWindow(void)
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{ fprintf(stderr, "Error: initializing SDL\n"); return (FALSE);}
window = SDL_CreateWindow(
NULL,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
WINDOW_WIDTH, WINDOW_HEIGHT,
SDL_WINDOW_BORDERLESS
);
if (!window)
{ fprintf(stderr, "Error: creating SDL window\n"); return (FALSE); }
renderer = SDL_CreateRenderer(window, -1, 0);
if (!renderer)
{ fprintf(stderr, "Error: creating SDL renderer\n"); return (FALSE); }
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
return (TRUE);
}
void setup(void)
{
player.x = WINDOW_WIDTH / 2;
player.y = WINDOW_HEIGHT / 2;
player.width = 1;
player.height = 1;
player.turnDirection = 0;
player.walkDirection = 0;
player.rotationAngle = PI / 2;
player.walkSpeed = 100;
player.turnSpeed = 45 * (PI / 180);
}
void processInput(void)
{
SDL_Event event;
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_QUIT:
{
isGameRunning = FALSE;
break;
}
case SDL_KEYDOWN:
{
if (event.key.keysym.sym == SDLK_ESCAPE)
isGameRunning = FALSE;
if (event.key.keysym.sym == SDLK_UP)
player.walkDirection = +1;
if (event.key.keysym.sym == SDLK_DOWN)
player.walkDirection = -1;
if (event.key.keysym.sym == SDLK_RIGHT)
player.turnDirection = +1;
if (event.key.keysym.sym == SDLK_LEFT)
player.turnDirection = -1;
break;
}
case SDL_KEYUP: {
if (event.key.keysym.sym == SDLK_UP)
player.walkDirection = 0;
if (event.key.keysym.sym == SDLK_DOWN)
player.walkDirection = 0;
if (event.key.keysym.sym == SDLK_RIGHT)
player.turnDirection = 0;
if (event.key.keysym.sym == SDLK_LEFT)
player.turnDirection = 0;
break;
}
}
}
int hasWallAt(float posX, float posY)
{
int mapIdxX;
int mapIdxY;
if (posX < 0 || posX > WINDOW_WIDTH || posY < 0 || posY > WINDOW_HEIGHT)
return (TRUE);
mapIdxX = floor((double)posX / TILE_SIZE);
mapIdxY = floor((double)posY / TILE_SIZE);
if (map[mapIdxY][mapIdxX] != 0)
return (TRUE);
return (FALSE);
}
// TODO: move my player
void movePlayer(float deltaTime)
{
player.rotationAngle += player.turnDirection * player.turnSpeed * deltaTime;
float moveStep = player.walkDirection * player.walkSpeed * deltaTime;
float newPlayerX = player.x + cos(player.rotationAngle) * moveStep;
float newPlayerY = player.y + sin(player.rotationAngle) * moveStep;
// TODO: perform wall collision
// printf("hasWallAt[%d, %d]? -> ", (int)newPlayerX, (int)newPlayerY);
if (hasWallAt(newPlayerX, newPlayerY) == FALSE)
{
player.x = newPlayerX;
player.y = newPlayerY;
}
}
void update(void)
{
// waste some time until we reach the target frame time length
// int timeToWait = FRAME_TIME_LENGTH - (SDL_GetTicks() - ticksLastFrame);
// if (timeToWait > 0 && timeToWait <= FRAME_TIME_LENGTH)
// SDL_Delay(timeToWait);
while (!SDL_TICKS_PASSED(SDL_GetTicks(), ticksLastFrame + FRAME_TIME_LENGTH));
float deltaTime = (SDL_GetTicks() - ticksLastFrame) / 1000.0f;
ticksLastFrame = SDL_GetTicks();
// TODO: remember to update game objects as a function of deltaTime
movePlayer(deltaTime);
}
void renderMap(void)
{
int tileX;
int tileY;
int tileColor;
for (int i=0; i<MAP_NUM_ROWS; i++)
{
for (int j=0; j<MAP_NUM_COLS; j++)
{
tileX = j * TILE_SIZE;
tileY = i * TILE_SIZE;
tileColor = map[i][j] != 0 ? 255 : 0;
SDL_SetRenderDrawColor(renderer, tileColor, tileColor, tileColor, 255);
SDL_Rect mapTileRect = {
tileX * MINIMAP_SCALE_FACTOR,
tileY * MINIMAP_SCALE_FACTOR,
TILE_SIZE * MINIMAP_SCALE_FACTOR,
TILE_SIZE * MINIMAP_SCALE_FACTOR,
};
SDL_RenderFillRect(renderer, &mapTileRect);
}
}
}
void renderPlayer(void)
{
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_Rect playerRect = {
player.x * MINIMAP_SCALE_FACTOR,
player.y * MINIMAP_SCALE_FACTOR,
player.width * MINIMAP_SCALE_FACTOR,
player.height * MINIMAP_SCALE_FACTOR
};
SDL_RenderFillRect(renderer, &playerRect);
SDL_RenderDrawLine(
renderer,
MINIMAP_SCALE_FACTOR * player.x,
MINIMAP_SCALE_FACTOR * player.y,
MINIMAP_SCALE_FACTOR * player.x + cos(player.rotationAngle) * 40,
MINIMAP_SCALE_FACTOR * player.y + sin(player.rotationAngle) * 40
);
}
void render(void)
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
renderMap();
renderPlayer();
SDL_RenderPresent(renderer);
}
void destroyWindow(void)
{
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
int main(void)
{
isGameRunning = initializeWindow();
setup();
while (isGameRunning)
{
processInput();
update();
render();
}
destroyWindow();
return (0);
}
#ifndef CONSTANTS_H
#define CONSTANTS_H
# include <unistd.h>
# include <SDL2/SDL.h>
# define FALSE 0
# define TRUE 1
# define PI 3.14159265
# define TWO_PI (2 * PI)
# define TILE_SIZE 64
# define MAP_NUM_ROWS 13
# define MAP_NUM_COLS 20
# define MINIMAP_SCALE_FACTOR 1.0
# define WINDOW_WIDTH (MAP_NUM_COLS * TILE_SIZE)
# define WINDOW_HEIGHT (MAP_NUM_ROWS * TILE_SIZE)
# define FOV_ANGLE (60 * (PI / 180))
# define NUM_RAYS WINDOW_WIDTH
# define FPS 30
# define FRAME_TIME_LENGTH (1000 / FPS)
#endif
'42Seoul > cub3d' 카테고리의 다른 글
Cub3d 학습일지 - 9 - 칼라 버퍼 (0) | 2021.01.06 |
---|---|
Cub3d 학습일지 - 8 - C에서의 레이캐스팅 (0) | 2021.01.05 |
Cub3d 학습일지 - 6 - 게임 루프 만들기 (0) | 2021.01.02 |
Cub3d 학습일지 - 5 - C로 시작하기 (0) | 2021.01.02 |
Cub3d 학습일지 - 4 - 벽 영상 렌더링하기 (0) | 2021.01.01 |
Comment