# 2020q3 Homework5 (render)
contributed by < `blueskyson` >
###### tags: `linux2020`
## 目錄
[TOC]
## Trace Code
在 `main.cpp` 的 `main` 中,首先使用 `SDL_Init(SDL_INIT_VIDEO)` 初始化視訊媒體
```cpp=1
int main(int argc, char *args[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
} else {
```
接下來初始化遊戲視窗 `SDL_Window` ,以下是 `SDL_CreateWindow` 的參數說明:
- **title** The title of the window, in UTF-8 encoding.
- **x** The x position of the window, `::SDL_WINDOWPOS_CENTERED`, or `::SDL_WINDOWPOS_UNDEFINED`.
- **y** The y position of the window, `::SDL_WINDOWPOS_CENTERED`, or `::SDL_WINDOWPOS_UNDEFINED`.
- **w** The width of the window, in screen coordinates.
- **h** The height of the window, in screen coordinates.
- **flags** The flags for the window, a mask of any of the following:
`::SDL_WINDOW_FULLSCREEN`, `::SDL_WINDOW_OPENGL`, `::SDL_WINDOW_HIDDEN`, `::SDL_WINDOW_BORDERLESS`, `::SDL_WINDOW_RESIZABLE`, `::SDL_WINDOW_MAXIMIZED`, `::SDL_WINDOW_MINIMIZED`,`::SDL_WINDOW_INPUT_GRABBED`, `::SDL_WINDOW_ALLOW_HIGHDPI`,
`::SDL_WINDOW_VULKAN`
```cpp=6
/* 在 raycaster.h 中有宣告要傳入 SDL_CreateWindow 的參數
* #define SCREEN_WIDTH (uint16_t) 320
* #define SCREEN_HEIGHT (uint16_t) 256
* #define SCREEN_SCALE 2
*/
SDL_Window *sdlWindow =
SDL_CreateWindow("RayCaster [fixed-point vs. floating-point]",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCREEN_SCALE * (SCREEN_WIDTH * 2 + 1),
SCREEN_SCALE * SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
```
確認 `SDL_Window` 是否成功初始化
```cpp=16
if (sdlWindow == NULL) {
printf("Window could not be created! SDL_Error: %s\n",
SDL_GetError());
} else {
```
接下來初始化遊戲中會用到的物件,首先初始化 `Game` 物件, `Game` 物件中包含
- `float playerX, playerY, playerA;` 代表玩家的位置和視角
- `void Move(int m, int r, float seconds);` 用來控制玩家移動
```cpp=20
Game game;
```
初始化 `RayCasterFloat` , `RayCasterFloat` 物件有計算光線投射的方法
初始化 `RayCasterFloat` 物件,搭配 `RayCasterFloat` 可以完成浮點數算繪
目前還不知道 `floatBuffer` 的用途
```cpp=21
RayCasterFloat floatCaster;
Renderer floatRenderer(&floatCaster);
uint32_t floatBuffer[SCREEN_WIDTH * SCREEN_HEIGHT];
```
跟 21 到 23 行類似,初始化定點數的算繪
```cpp=24
RayCasterFixed fixedCaster;
Renderer fixedRenderer(&fixedCaster);
uint32_t fixedBuffer[SCREEN_WIDTH * SCREEN_HEIGHT];
```
初始化以下變數
```cpp=27
int moveDirection = 0; // 玩家的移動方向
int rotateDirection = 0; // 玩家的轉動方向
bool isExiting = false; // 是否已離開遊戲
/* 根據 SDL 解析度所得到的刷新頻率 */
const static auto tickFrequency = SDL_GetPerformanceFrequency();
/* 獲得目前 SDL Counter 的值 */
auto tickCounter = SDL_GetPerformanceCounter();
SDL_Event event; // 儲存目前的 key code
/* 用來接收 fixedTexture 和 floatTexture 的值
* 並且暫存下一個 frame 要繪製的資訊 */
SDL_Renderer *sdlRenderer =
SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED);
/* 用來接收 fixedBuffer 的值,以 SDL_Texture 型態表示 */
SDL_Texture *fixedTexture = SDL_CreateTexture(
sdlRenderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT);
/* 用來接收 floatBuffer 的值,以 SDL_Texture 型態表示 */
SDL_Texture *floatTexture = SDL_CreateTexture(
sdlRenderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT);
```
接下來進入 while 迴圈,玩家按下 Esc 或關閉遊戲視窗才會跳出迴圈
```cpp=50
while (!isExiting) {
floatRenderer.TraceFrame(&game, floatBuffer);
fixedRenderer.TraceFrame(&game, fixedBuffer);
DrawBuffer(sdlRenderer, fixedTexture, fixedBuffer, 0);
DrawBuffer(sdlRenderer, floatTexture, floatBuffer,
SCREEN_WIDTH + 1);
SDL_RenderPresent(sdlRenderer);
if (SDL_PollEvent(&event)) {
isExiting =
ProcessEvent(event, &moveDirection, &rotateDirection);
}
const auto nextCounter = SDL_GetPerformanceCounter();
const auto seconds = (nextCounter - tickCounter) /
static_cast<float>(tickFrequency);
tickCounter = nextCounter;
game.Move(moveDirection, rotateDirection, seconds);
}
SDL_DestroyTexture(floatTexture);
SDL_DestroyTexture(fixedTexture);
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow(sdlWindow);
}
}
SDL_Quit();
return 0;
}
```
## 待續