CRPG 進度筆記

#RPG #C++

最近弄了很多東西進去,寫一寫當作備忘好了。之後大概要調整架構+新增功能+弄一些小的測試用遊戲。

大致有幾個重要的更新:

跨 Windows 和 Mac OX

這就是刻crpg主要原因之一,終於處理好了!

OpenGL, OpenAL, Python API

主要問題大概是:

在Mac OX底下,編譯和引用這三個就跟喝一杯開水一樣簡單,可是在Windows底下光是安裝Glut就超麻煩,還好,有人寫了一個類似Linux的終端機的:MSYS2pacman指令就可以把需要的Package安裝好。需要注意的是,MSYS2底下分兩種g++編譯器,一個是usr\bin\g++,這是給MSYS2自己用的,可以用

1
2
3
4
5
6
7
#include<cstdio>
int main(){
#ifdef _WIN32
    printf("win32\n");
#endif
    return 0;
}

測試,會發現並沒有出現win32。另外一個需要用pacman安裝mingw-w64-g++(可能更長),這編譯出來才會是給Windows用的。

安裝的對應關鍵字:

可以這樣找

1
$ pacman -Sl | grep keyword

然後安裝

1
$ pacman -S package_name

讀取目錄下的檔案

當初沒有寫這個,本來是要使用者自己把清單寫在一個目錄底下的檔案,仔細想想不太合理,就決定要把這部分處理好。原本是想直接用Boost:File System,但想到只是要實做羅列檔案,就用一個大Library,cost好像有點高。所以決定自己弄一個:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// For GetFileUnderDir header
#ifdef __APPLE__
#include <sys/types.h>
#include <dirent.h>
#elif __WIN32
#include <windows.h>
#endif
// ------
std::vector<std::string> GetFileUnderDir(const char* dir_name){
    std::vector<std::string> ret;

#ifdef __APPLE__
    DIR* dp = opendir(dir_name);
    struct dirent* ep; 
    if(dp != NULL){
        while((ep = readdir(dp))){
            if(strcmp(ep->d_name, ".") == 0 or
               strcmp(ep->d_name, "..") == 0) continue;
            ret.push_back(std::string(ep->d_name));
        }
        closedir(dp);
    }else{
        fprintf(stderr, "Couldn't open the directory\n");
        exit(1);
    }
#elif __WIN32
    
    WIN32_FIND_DATA data;
    HANDLE hFind;
    char d_dir_name[100];
    sprintf(d_dir_name, "%s/*", dir_name);
    hFind = FindFirstFile(d_dir_name, &data);
    if (hFind == INVALID_HANDLE_VALUE) {
        fprintf(stderr, "Couldn't open the directory\n");
        exit(1);
    } 
    else{
        do{
            if(strcmp(data.cFileName, ".") == 0 or 
               strcmp(data.cFileName, "..") == 0) continue;
            ret.push_back(std::string(data.cFileName));
        }while(FindNextFile(hFind, &data));
        FindClose(hFind);
    }
#endif
    return ret;
}

紅線問題

在圖片邊緣會有模糊的紅線,發現是在讀取Image時,設定Texture處裡部分不好。 class Image 在讀取Tile時要把GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAX_FILTER 設成 GL_NEAREST即可。

Env過於神通廣大

這是初期在處理公共變數的餘毒,有這種東西,有點不科學:

1
2
3
4
5
6
struct StrCompare{
    bool operator() (const char* str1, const char* str2) const{
        return std::strcmp(str1, str2) < 0;
    }
};
typedef std::map<const char*, void* , StrCompare> Env;

一個 map: string -> void*裏面包有太多髒東西。

大致把一部份instance放在class裏的static就清理好了,整理好後,code變乾淨許多,不再有一堆奇奇怪怪的pointer存取。

Component

參考自Component - Decoupling Pattern

在準備寫Hero的腳本控制時發現和Event腳本控制重複太多地方,於是用Component的方法把共同的地方接出來,很快就處理好了。像是MoverComponent:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class MoverComponent{
public:
    MoverComponent(Object* _obj);
    void TickEvent(int delta_time);
    void Update();
//...
private:
//...    
    Object* obj;
};

在Event裏,會呼叫new MoverComponent(this),借由操縱MoverComponent間接操作Event裏的status。當然Event是繼承自Object。這時也順便發現Hero也需要相同的Component,讓腳本可以操作他。

尚未處理的重要Issue

目前還有一些重要Issue,有必要處理掉

BSD講完第一次話就Crash

這毫無頭緒._. Issue:#14

讀取ogg或mp3

目前的引擎只可以讀取wav,這有點傷,因為wav檔沒經過壓縮,通常有點大,一個遊戲少說二三十的音效和音樂下來就差很多。

資源控管

目前有很多new出來的東西都沒delete掉,考慮用shared_ptr解決。