본문 바로가기

Game Programming in C++ Chapter1 - paddle 조작

반응형

산자이 마드하브 저 / 박주항 역 ❘ 에이콘

 

책의 소스 코드를 직접 작성해보면서 정리한 글입니다. (실습환경: windows)

책 소스 코드: GitHub - gameprogcpp/code: Game Programming in C++ Code


1. 움직임

게임에서 움직임이란, 매 순간 정적인 그림들을 빠르게 출력하는 것이다.

 

2. Frame

프레임이란 한 장면에 해당하는 시간 간격을 의미한다.

 

3. Delta Time

앞 프레임과 시간차이를 delta time이라고 한다.

 

4. 퐁 게임 시간

퐁 게임의 시간 단위는 1ms(0.001초) 이다.

또한 16 delta time을 가질 것이다. 즉, 16ms(0.016초)마다 게임 세계를 갱신할 것이다.

이는 1초(1000ms)를 16ms로 나눈 것(\( 1000 \div 16 = 62.5 \))과 같으며,

결과적으로 62.5 FPS(Frame Per Second)가 된다.

 

6. paddle 이동

물체 이동에 사용되는 공식: \( 이동거리 = 시간 \times 속력 \)

퐁 게임의 시간은 delta time이므로, 공식에 delta time을 사용할 것이다.

그럼 속력은 어떻게 해야할까? 단순하게 하드코딩 하기로 한다. -_-

// 패들위치 = 패들방향 * 이동속력(초속) * 시간
_paddle_pos.y += _paddle_dir * 300.0f * delta_time;

 

퐁 게임은 0.016초 마다 게임을 갱신(delta time)하므로, 초당 4.8씩 움직일 것이다. \( (300 \times 0.016 = 4.8) \) 

 

5. Game.hpp

게임 세계를 업데이트할 함수(updateGame)를 추가한다.

사용자 입력에 따라 paddle 방향을 나타내는 변수(_paddle_dir)를 추가한다.

게임 내 시간을 저장하는 변수(_ticks_cnt)를 추가한다.

#include "SDL3/SDL.h"

class Game
{
public:
	...(생략)...

private:
	...(생략)...
	void updateGame() // 게임 갱신
	int _paddle_dir; // paddle 방향(위/아래)
	Uint64 _ticks_cnt; // 게임 시간
};

 

6. Game.cpp

Game() 수정

Game::Game() : _sdl_window(nullptr), _w(1024), _h(768), _running(true), _sdl_renderer(nullptr),
	_thickness(15.0f), _paddle_h(100.0f), _paddle_dir(0), _ticks_cnt(0) // 초기화 리스트 추가
{
}

 

● processInput() 수정

void Game::processInput()
{
	SDL_Event event;
	while (SDL_PollEvent(&event)) //if event is occurred in queue, it will return TRUE
	{
		switch (event.type)
		{
		case SDL_EVENT_QUIT: //windows x icon is pressed
			_running = false;
			break;
		}
	}

	const bool* state = SDL_GetKeyboardState(NULL);
	if (state[SDL_SCANCODE_ESCAPE]) //Esc is pressed
	{
		_running = false;
	}

	// user input controls paddle direction
	_paddle_dir = 0;
	if (state[SDL_SCANCODE_W])
	{
		_paddle_dir -= 1;
	}

	if (state[SDL_SCANCODE_S])
	{
		_paddle_dir += 1;
	}
}

 

● updateGame() 구현

시간이 16ms만큼 흐르지 않았다면, 아무것도 하지 않고 대기한다.

반대로 시간이 너무 많이(0.05초 초과) 흘렀다면, 게임 세상이 0.05초만 흐른걸로 보정한다. (예외처리)

void Game::updateGame()
{
	Uint64 current_time = SDL_GetTicks();
	while (current_time < _ticks_cnt + 16) //16ms
	{
		current_time = SDL_GetTicks();
	}

	//delta time = last frame - current frame
	//converting to per second
	float delta_time = (SDL_GetTicks() - _ticks_cnt) / 1000.0f;

	//delta time validation
	//maximum delta time is 0.05 second
	if (delta_time > 0.05f)
	{
		delta_time = 0.05f;
	}

	_ticks_cnt = SDL_GetTicks(); // update tick count for next frame

	if (_paddle_dir != 0)
	{
		//moving speed is 300.0f/sec
		_paddle_pos.y += _paddle_dir * 300.0f * delta_time;

		//if out of wall
		if (_paddle_pos.y < (_paddle_h / 2.0f + _thickness))
		{
			_paddle_pos.y = _paddle_h / 2.0f + _thickness;
		}
		else if (_paddle_pos.y > (static_cast<float>(_h) - _paddle_h / 2.0f - _thickness))
		{
			_paddle_pos.y = static_cast<float>(_h) - _paddle_h / 2.0f - _thickness;
		}
	}
}

 

runLoop() 수정

void Game::runLoop()
{
	while (_running)
	{
		processInput();
		updateGame();
		generateOutput();
	}
}

 

7. 결과

excution result

반응형