又到了一年一度的鐵人賽啦~?!今年決定嘗試用C與OpenGL寫出一個2D平台卷軸遊戲,希望至少一可以完成一個小關卡。已經可以預想到會碰到很多問題了,百分之百碰一個問題不會在一天就解決,所以如果要完成的話應該會不只30天,就看我可以撐到甚麼時候了。
我會盡量不漏地,一步一步敘述我的作法,有興趣的讀者可以跟著試試看。廢話不多說,進入正題~
雖然我是用C與OpenGL製作,Windows、MacOS、Linux都可以進行跨平台建置,但目前只會專注在Windows平台
編輯器(Editor): Visual Studio Code
編譯器(Compiler): GCC 10.3.0
CMake: 3.21.0-rc3
|
+---- external/ // 放第三方的libs
|
+---- src/ // 遊戲sourece code
|
+---- CMakeLists.txt // CMake的建置腳本,名字不可變
這裡選用GLFW管理專案的視窗生成與輸入控制等功能,先把GLFW的專案整的下載下來後,把整包放到external資料夾底下,很快就會用到。
|
+--- external/
|
+---- glfw/
提問: 為什麼不使用SDL或是更土炮的呼叫WinMain呢?
主要原因是我OpenGL的相關知識都來自這個網站 - LearnOpenGL(https://learnopengl.com/),去年也有看到很多鐵人賽賽友利用這個優良的學習網站撰寫學習筆記,裡面Create a Window這一章節就是用GLFW。
GLFW這個開源專案有須多貢獻者,以及完善的文件,這裡是他的官網,右上方Documentaion點下去,就會看到關鍵的Example Code:
#include <GLFW/glfw3.h>
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
為什麼特地要說這個呢?原因我在初學的時候,找到一個看起來可以用的lib,直接二話不說Google或上Stackoverflow找相關範例,以及一些使用中遇到的錯誤,其實這些東西,往往都已經寫在官方的wiki或官網上了,甚至有完整的流程與解說,有些甚至就直接所在原始碼的註解裡面了。完全不用繞這麼多路
上面這段範例,我會放在以下地方
|
+--- src/
|
+---- iron.h
|
+---- iron_main.c
然後這裡是內容
// iron.h --> 這裡之後會集中放相關的header
#ifndef _IRON_H_
#define _IRON_H_
#include "GLFW/glfw3.h"
#endif // _IRON_H_
// iron_main.c --> 2d platfomer的main.c
#include "iron.h"
// #include <stdio.h>
int main() {
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
// glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
return 0;
}
常常會看到一些開源的C或C++的專案有一個或多個CMakeList.txt
的檔案,這些都是CMake的建置腳本。
這麼做的原因在於C與C++有相當多的實作平台,建置方法也不一,CMake幫我們做的事情,並不是建置,而是生成相對應平台的建置文件,例如: GCC或Clang的話就是Makefile。
但是CMake最麻煩的還是需要額外去學習CMake專用的語言,個人認為門檻挺高的,且只能在CMake使用。
介紹完畢,下面直接貼上我的2D Platformer的CMake腳本,註解會寫上我知道但可能不適那麼準確的解釋:
# cmake的註解是從'#'開始的
cmake_minimum_required(VERSION 3.1) # --- 最低版本 ---
project(LittleIron) # --- 專案名稱 ---
#變數所有src資料夾中的source files
file(GLOB sources src/*.c)
# 不需要建置docs, examples, tests
# from - https://www.glfw.org/docs/latest/compile_guide.html#compile_options_shared
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
add_executable( # 標記執行黨和原始碼
LittleIron
${sources}
)
add_subdirectory(external/glfw) # 引用由glfw建置的lib
include_directories(external/glfw/include)
target_link_libraries( # 與glfw lib進行連接
LittleIron
glfw
)
接下來可以直接依靠VS Code插件提供的方便。
下圖是我的VS Code,左牌工具列最下面的就是插件提供的建置按鈕,如果沒有看到的話,可以按下Ctrl + Shift + P
,輸入CMake Quick Start,選擇要使用的編譯器後,就會開始設定專案的設定了,這時會發現多了一個build
的資料夾。
設定完之後紅色框框的按鈕按下去,就會開始建置了(如果正常的話... :)),最後會看到build
資料夾有LittleIron
(小鐵)的執行檔了。