Project1

标题: How to写一个全新的rpg maker [打印本页]

作者: guoxiaomi    时间: 2021-7-29 16:56
标题: How to写一个全新的rpg maker
看到大家贡献了这么多的runtime,就想了解一下写这个需要多少知识,然后我发现了这个课程:

Create a 2D Game Engine with C++ & Lua
https://courses.pikuma.com/courses/2dgameengine

共有如下几大章,每章里还有若干小节,果然很难啊……

1 Introduction
2 Libraries & Dependencies
3 Displaying the Game Window
4 Rendering SDL Objects
5 Fixing the Game Time Step
6 Logger
7 Files & Folder Structure
8 Organizing Game Objects
9 ECS Design
10 ECS Implementation
11 Creating Entities & Components
12 Creating Systems
13 Managing Assets
14 Animation System
15 Collision System
16 Killing Entities
17 Event System
18 Other Useful Components & Systems
19 Tagging & Grouping Entities
20 Data-Oriented Design
21 Displaying True-Type Fonts
22 Dear ImGui
23 Culling & Map Control
24 Lua Scripting
25 Next Steps
26 Bonus: The Map Editor
27 Moving Forward

众筹$29.99学费

作者: 黑白界    时间: 2021-7-29 21:28
一看就是个大工程,可能需要一个经验丰富的团队开发很长时间。
作者: 真·可乐    时间: 2021-7-30 02:02
我记得B站有个叫红色激情的Up,用GMS仿制了一个RMMV https://b23.tv/GHqjZ4
作者: tuxyin    时间: 2021-7-30 08:24
这个课程之前的名字叫《Fundamentals of 2D Game Engines with C++ SDL and Lua》,曾在udemy上卖9.9$(该课程在udemy上貌似下架了)。现在换个名字卖的这么贵。。。当然,也许作者把课程内容优化的更好了。
作者: guoxiaomi    时间: 2021-8-1 03:32
本帖最后由 guoxiaomi 于 2021-8-1 03:44 编辑

成功写好了0.1个rpgmaker:
  1. #include <rice/rice.hpp>
  2. #include <iostream>

  3. using namespace Rice;

  4. extern "C" void Init_test()
  5. {
  6.     Class rb_cTest = define_class("Test");
  7. }

  8. int main()
  9. {
  10.     std::cout << "Hello, rice" << std::endl;
  11.     ruby_init();
  12.     Init_test();
  13.     rb_eval_string("p Test");
  14.     std::cout << "-- end --" << std::endl;
  15.     return ruby_cleanup(0);
  16. }
复制代码
一顿编译后得到test.exe,执行结果:
  1. Hello, rice
  2. Test
  3. -- end --
复制代码
,范例: test.zip (2.45 MB, 下载次数: 4)
现在只要把SDL加进去
参考资料:
1. rice:https://jasonroelofs.com/rice/4.x/tutorial.html
2. embed ruby:https://silverhammermba.github.io/emberb/embed

编译方法是用rice在mingw64里编译出test.o文件,然后把最终g++编译.so文件的那部分内容改为输出exe就OK了:
  1. g++ -o test.exe test.o -L. -LC:/Ruby30-x64/lib -L. -pipe -s -fstack-protector-strong -pipe -s -fstack-protector-strong -Wl,--enable-auto-image-base,--enable-auto-import test-x64-mingw32.def -m64 -static -Wl,-Bdynamic -lx64-msvcrt-ruby300 -Wl,-Bstatic -lstdc++ -lshell32 -lws2_32 -liphlpapi -limagehlp -lshlwapi
复制代码

作者: enghao_lim    时间: 2021-8-1 14:31
guoxiaomi 发表于 2021-8-1 03:32
成功写好了0.1个rpgmaker:
一顿编译后得到test.exe,执行结果:,范例:。
现在只要把SDL加进去

真是怀念的代码……
话说为了ruby用了rice么?
作者: guoxiaomi    时间: 2021-8-1 22:07
本帖最后由 guoxiaomi 于 2021-8-1 22:28 编辑

SDL也加进去了!
  1. #include <rice/rice.hpp>
  2. #include <SDL2/SDL.h>
  3. #include <iostream>
  4. #include <windows.h>

  5. using namespace Rice;

  6. void Init_test()
  7. {
  8.     Class rb_cTest = define_class("Test");
  9. }

  10. int main(int argc, char *argv[])
  11. {
  12.     ::ShowWindow(::GetConsoleWindow(), SW_HIDE);

  13.     std::cout << "Hello, rice" << std::endl;
  14.     SDL_Window *window = SDL_CreateWindow("demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
  15.     SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

  16.     ruby_init();
  17.     Init_test();
  18.     rb_eval_string("sleep 10");
  19.     SDL_DestroyRenderer(renderer);
  20.     SDL_DestroyWindow(window);
  21.     std::cout << "-- end --" << std::endl;
  22.     return ruby_cleanup(0);
  23. }
复制代码
一顿编译后得到: test2.zip (2.86 MB, 下载次数: 10)
make

接下来写个事件循环就完事了

作者: guoxiaomi    时间: 2021-8-2 17:53
本帖最后由 guoxiaomi 于 2021-8-2 17:56 编辑

v0.0.1版发布成功!话说为什么要带这么多的dll…… lib.zip (4.54 MB, 下载次数: 4)
https://gitee.com/rmxp/sdlrgss/releases/v0.0.1

作者: 哇哇哇啊叭叭    时间: 2021-8-2 19:46

  这个水贴好硬核。突然有种想买的冲动...如果这是一贴广告的话,就更硬了

  什么是runtime?百度上的翻译感觉完全翻成了另一种外语



作者: guoxiaomi    时间: 2021-8-3 23:26
本帖最后由 guoxiaomi 于 2021-8-4 00:22 编辑

写了个draw_text:[attach]381031[/attach]
跟右值引用干了一晚上,目前使用了全局变量,情绪非常稳定
20210731-rice-v0.0.2.zip (4.15 MB, 下载次数: 8)

Screenshot 2021-08-03 232359.png (52.71 KB, 下载次数: 39)

Screenshot 2021-08-03 232359.png

作者: guoxiaomi    时间: 2021-8-7 01:17
本帖最后由 guoxiaomi 于 2021-8-7 01:34 编辑

写了个渲染的循环: release.zip (3.94 MB, 下载次数: 6)
我准备了2个std::vector,分别在不同的线程(ruby线程和渲染线程)里添加和执行指令。
设计中ruby里的所有绘制相关的函数调用都不实际执行,而是向commands_in里push命令。
  1. void renderer_loop(cen::renderer &renderer, void(function(Command &&, cen::renderer &)))
  2.     {
  3.         while (!program_terminate)
  4.         {
  5.             if (commands_out.empty())
  6.             {
  7.                 if (!commands_in.empty())
  8.                 {
  9.                     swap_queues();
  10.                 }
  11.                 continue;
  12.             }

  13.             for (auto cmd : commands_out)
  14.             {
  15.                 if (cmd.id == Command_Code::Frame_End)
  16.                 {
  17.                     num_frame_out--;
  18.                     if (num_frame_out > 0)
  19.                     {
  20.                         continue;
  21.                     }
  22.                 }
  23.                 function(std::move(cmd), renderer);
  24.             }
  25.             commands_out.clear();
  26.         }
  27.     }
复制代码
然后增加了一个跳帧的设定,当负责渲染的线程检查到有多个Frame_End的指令时,只有最后一帧才会尝试渲染所有的画面,前面的Frame_End指令跳过。
作者: pporder    时间: 2021-8-7 02:04
硬核……(码了就是跑了系列
作者: guoxiaomi    时间: 2021-8-13 01:47
成功绘制了图片!https://gitee.com/rmxp/sdlrgss/releases/v0.0.6

ruby代码为:
RUBY 代码复制
  1. class Bitmap
  2.   attr_reader :x, :y
  3.  
  4.   def initialize(path)
  5.     @x = @y = 0
  6.     Core._bitmap_new_path(self, path)
  7.   end
  8.  
  9.   def x=(x)
  10.     @x = x
  11.     Core._bitmap_set_xy(self, @x, @y)
  12.   end
  13.  
  14.   def y=(y)
  15.     @y = y
  16.     Core._bitmap_set_xy(self, @x, @y)
  17.   end
  18.  
  19.   def dispose
  20.     Core._bitmap_dispose(self)
  21.   end
  22. end
  23.  
  24. b1 = Bitmap.new("resource/001-Fighter01.png")
  25. b2 = Bitmap.new("resource/001-Fighter01.png")
  26. t = Time.now
  27. 1000.times do
  28.   b1.y = (b1.y + 1) % 320
  29.   b2.x = (b2.x + 1) % 320
  30.  
  31.   Core.frame_end
  32.   Core.wait_renderer
  33. end
  34. p "FPS: #{1000 / (Time.now - t)}"
  35. b1.dispose
  36. b2.dispose
  37. b1 = b2 = nil
可以看到Bitmap(其实更像是RGSS的Sprite)其实是个没啥东西的类,而Core.XXX函数只是传输指令,并没有实际执行任何东西。图片的加载和渲染在另一个线程里异步完成。
作者: hyrious    时间: 2021-8-13 09:14
歪楼:其实 rpg maker 包含运行时编辑器两个部分,运行时全在 rgss.dll 里,你可以直接拿来调(注意这里只能用 RGSS300,因为 301 有壳不让 gcc 链接):
  1. #include <windows.h>
  2. int CALLBACK WinMain(HINSTANCE hInstance,
  3.                      HINSTANCE hPrevInstance,
  4.                      LPSTR lpCmdLine,
  5.                      int nCmdShow) {
  6.     wchar_t *rgssad = NULL;
  7.     RGSSInitialize3();
  8.     RGSSSetupFonts();
  9.     RGSSGameMain(
  10.         CreateWindowEx(0, "#32770", "RGSSGameMain", 0x90cf0000,
  11.             CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
  12.             0, 0, 0, 0),
  13.         L"Scripts.rvdata2",
  14.         &rgssad);
  15.     return 0;
  16. }
复制代码
  1. gcc -O3 -static -s -o player player.c RGSS300.dll -m32 -w && player
复制代码
而坛友的编辑器据我所知目前只有 UCCU 可以一战(逃
作者: hyrious    时间: 2021-8-13 09:26
继续歪:从编辑器角度来说,你也可以从 rgss.dll 里偷一个 RGSSEval(或者 RGSSGetInt 等更容易使用的)来方便处理 Ruby Marshal 等数据。
一个我滥用 RGSSEval 的例子:https://github.com/hyrious/RgssS ... hEvent/RGSS.cs#L368
作者: guoxiaomi    时间: 2021-8-13 09:55
hyrious 发表于 2021-8-13 09:14
歪楼:其实 rpg maker 包含运行时和编辑器两个部分,运行时全在 rgss.dll 里,你可以直接拿来调(注意这里 ...

终于钓出大佬来讨论了!

借用dll里的RGSSEval我在论坛的帖子上看过。但貌似那样就只能用win32api来交互了,而且换不掉ruby的版本?感觉作为2D游戏引擎,“不太正规”。
我的工程里内置了完整的ruby,可以require .so库。除了不能-mwindows编译消掉初始的控制台窗口以外,其他的看上去都挺好的(情绪稳定)。然后,包装好RGSS的几个内部类就OK了。整体思路其实更接近zh99998的OpenRGSS:https://rpg.blue/thread-248776-1-1.html
不过相比OpenRGSS,我还有一个额外的设计是让ruby只负责处理逻辑,另一个线程负责绘制。
作者: patchouli4869    时间: 2021-8-13 18:07
本帖最后由 patchouli4869 于 2021-8-13 18:16 编辑

想起大二時弄的 crpg
https://github.com/mudream4869/crpg
那時候主要是用
1. python 當作每個事件的腳本語言
2. tiled 當作地圖編輯器

不過現在沒在維護了。還是需要先做幾個遊戲再設計架構,那時還是太年輕。

作者: guoxiaomi    时间: 2021-8-16 01:54
实现了Viewport/Sprite/Bitmap的基础功能:https://gitee.com/rmxp/sdlrgss/releases/v0.1.0
1. Bitmap可以读取文件
2. Sprite需要绑定Viewport,在Viewport外不进行绘制
3. Sprite和Viewport都拥有Z值,Z值靠前的显示在前面

接下来可能要先做一下Bitmap#draw_text和Bitmap#blt,然后是图层透明度的混合
作者: guoxiaomi    时间: 2021-9-1 14:02
仔细看了看发现openrgss很多函数都是空着的,其中Bitmap#change_hue可能比较难实现。根据参考文献里的说法,有多种对色调(Hue)的定义。如果使用第2种定义,把RGB值当成空间中的矢量,单纯的对色调进行修改其实是沿着(111)方向的旋转。这样就只需要简单的矩阵乘法即可完成变换。为了提升计算速度,这里甚至打了个表:
C 代码复制
  1. void bitmap_change_hue(uint8_t *data, int size, int hue)
  2. {
  3.     // make table
  4.     array<double, 256 * 3> table;
  5.     // thanks dongjx for generating the rotation matrix
  6. #define PI 3.14159265359
  7.     double k1 = (1 - cos(hue * PI / 180) - sqrt(3) * sin(hue * PI / 180)) / 3;
  8.     double k2 = (1 - cos(hue * PI / 180) + sqrt(3) * sin(hue * PI / 180)) / 3;
  9. #undef PI
  10.     double k0 = 1 - k1 - k2;
  11.     double temp;
  12.     temp = 0.0;
  13.     for (int i = 0; i < 256; i++)
  14.     {
  15.         table[i] = temp;
  16.         temp += k0;
  17.     }
  18.     temp = 0.0;
  19.     for (int i = 256; i < 256 * 2; i++)
  20.     {
  21.         table[i] = temp;
  22.         temp += k1;
  23.     }
  24.     temp = 0.0;
  25.     for (int i = 256 * 2; i < 256 * 3; i++)
  26.     {
  27.         table[i] = temp;
  28.         temp += k2;
  29.     }
  30.     // do convertion
  31.     double x, y, z;
  32.     for (int i = 0; i < size / 4; i++)
  33.     {
  34.         x = *(data);
  35.         y = *(data + 1);
  36.         z = *(data + 2);
  37. #define convert(x, y, z) (uint8_t)(min(255.0, max(0.0, table[x] + table[256 + y] + table[512 + z])))
  38.         *(data) = convert(x, y, z);
  39.         *(data + 1) = convert(y, z, x);
  40.         *(data + 2) = convert(z, x, y);
  41. #undef convert
  42.         data += 4;
  43.     }
  44. }


参考文献: A200804-1390.pdf (320.87 KB, 下载次数: 2)
作者: yayapipifly    时间: 2021-9-1 14:16
比起重写一个,我还蛮想在Unity里面重现Rpg Maker的,
继承RPG Maker的各种直观可用性功能,又可以方便拓展更多的功能。
作者: xiaohuangdi    时间: 2021-9-1 18:02
大佬不如用Unity做一個開源 RPGmaker的功能啊   
11區的幾個黃油大社團現在都用同一個Unity模板  
作者: guoxiaomi    时间: 2021-9-23 00:40
本帖最后由 guoxiaomi 于 2021-9-23 00:43 编辑

把Sprite、Plane、Window和Tilemap都写好了:

其实Tilemap没有想象中难写……反而是window最麻烦。
1920x1080的Tilemap轻松120帧
作者: phunmung5173    时间: 2021-9-23 09:53
渲染怎麽解決的... 感覺這方面是最難的坎 但是看樓主好像跳過了。
作者: 搞事    时间: 2021-9-23 10:39
牛逼啊,改天发我的看看有啥问题
作者: 搞事    时间: 2021-9-23 10:42
搞事 发表于 2021-9-23 10:39
牛逼啊,改天发我的看看有啥问题

我的只是一个引擎,没有用来写rm,只是自己写游戏用的
作者: 搞事    时间: 2021-9-23 21:56
/*
* 游戏引擎
*/
#ifndef _GAMENGINE_H_
#define _GAMENGINE_H_

// 包含库
#include "Configure_Engine.h"                // 引擎配置参数
#include "Engine_Graphics.h"                // 渲染部分
#include "Engine_DataBase.h"                // 数据部分
#include "Manager_UI.h"                                // UI部分
#include "Manager_View.h"                        // 场景部分

// 声明类
class GameEngine;

// 外部定义
extern GameEngine* g_eng;                        // 全局 - 游戏引擎


// 游戏引擎 实现类
class GameEngine {
private:
        // 基础属性
        bool eng_iskeep;                                // 可持续
        unsigned int eng_errorvalue;        // 错误值
        unsigned int eng_state;                        // 引擎状态

        // 错误类型

private:
        // win32程序属性 -- 句柄
        HWND m_hwnd;                                        // 句柄
        HINSTANCE m_hinstance;                        // 线程进程
        HMENU m_hemnu;                                        // 菜单
        HCURSOR m_hcursor;                                // 光标
        HICON m_hicon;                                        // 图标
        HBRUSH m_hbrush;                                // 画刷

        // win32程序属性 -- 基础属性
        int m_x, m_y, m_width, m_height;
        bool m_fullscreen;

private:       
        vector<Data_San9Event*> eng_eventlist;        // 事件列表


public:
        // 构造
        GameEngine();

        // 析构
        ~GameEngine();

        // 释放引擎
        void ReleaseEngine();

        // 初始化句柄
        void InithInst(HINSTANCE hinstance);

        // 初始化引擎
        void InitEngine();

        // 初始化引擎
        // x,y,width,height == 程序窗口大小
        // Fullscreen == 全屏(默认全屏)
        void InitEngine(int x,int y,int width,int height,bool full = true);

        // 运行引擎
        void RunEngine();

public:        // 相关 win32程序
        // 接收win32消息
        void CheckWin32Msg(UINT msg, WPARAM wp, LPARAM lp);

public:
        // 判定引擎是否结束更新
        bool IsActivity();


private:
        // 发送结束引擎消息
        void SelfKill();

private:
        // 初始化win32程序
        void InitWin32Process();

        // 初始化渲染部分
        void InitGraphicsProcess();

        // 初始化数据库部分
        void InitDataBaseProcess();

        // 初始化场景控制部分
        void InitViewControlProcess();

        // 处理事件
        void Engine_CheckEvent();

        // 处理更新
        void Engine_Update();

        // 处理渲染
        void Engine_Draw();

};


#endif // !_GAMENGINE_H_





作者: 搞事    时间: 2021-9-23 21:57
#include "GameEngine.h"

// 游戏引擎生成  
GameEngine* g_eng = new GameEngine();

// 游戏引擎 - win32回调函数
// 唯一性
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {

        switch (msg) {
        case WM_KEYDOWN:
        case WM_KEYUP:
        case WM_MOUSEMOVE:
        case WM_LBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_RBUTTONDOWN:
        case WM_RBUTTONUP:
        case WM_MBUTTONDOWN:
        case WM_MBUTTONUP:
        case WM_CHAR:
        case WM_ACTIVATE:
        {
                if (g_eng != nullptr) {
                        g_eng->CheckWin32Msg(msg, wp, lp);
                }
        }
                break;
        case WM_DESTROY:
        {
                bool result = false;
                if (g_eng != nullptr) {
                        result = g_eng->IsActivity();
                }

                if (result) {
                        PostQuitMessage(0);
                }
        }
                break;
        default:
                break;
        }
        return DefWindowProc(hwnd, msg, wp, lp);
}

// 构造
GameEngine::GameEngine() {
        // 基础属性
        eng_iskeep = true;                                // 可持续
        eng_errorvalue = 0x00;                        // 错误值 - 0
        eng_state = SYS_STATE_BEGIN;        // 引擎状态 - 刚开始

        // win32程序属性 -- 句柄


        // win32程序属性 -- 基础属性
        m_x = 0, m_y = 0, m_width = 1024, m_height = 769;        // 固定像素大小
        m_fullscreen = true;                                                                // 默认全屏


}

// 析构
GameEngine::~GameEngine() {

}

// 释放引擎
void GameEngine::ReleaseEngine() {

}

// 初始化句柄
void GameEngine::InithInst(HINSTANCE hinstance) {
        m_hinstance = hinstance;
}

// 初始化引擎
void GameEngine::InitEngine() {
        // 初始化 win32程序  
        InitWin32Process();

        // 初始化 渲染部分
        InitGraphicsProcess();

        // 初始化 数据库部分
        InitDataBaseProcess();

        // 初始化场景控制部分
        InitViewControlProcess();
}

// 初始化引擎
// x,y,width,height == 程序窗口大小
// Fullscreen == 全屏(默认全屏)
void GameEngine::InitEngine(int x, int y, int width, int height, bool full) {
        // 设置属性
        m_fullscreen = full;
        if (!m_fullscreen) {
                m_x = x;
                m_y = y;
                m_width = width;
                m_height = height;
        }
        else {
                m_x = 0;
                m_y = 0;
                m_width = GetSystemMetrics(SM_CXSCREEN) - 1;
                m_height = GetSystemMetrics(SM_CYSCREEN) - 1;
        }

        // 初始化引擎
        InitEngine();
}

// 初始化win32程序
void GameEngine::InitWin32Process() {
        // 属性配置
        // 背景画刷
        if (m_hbrush == nullptr) {
                m_hbrush = CreateSolidBrush(RGB(0, 0, 0));
        }
        // 默认光标
        if (m_hcursor == nullptr) {
                m_hcursor = LoadCursor(NULL, IDC_ARROW);
        }
        // 默认图标  
        if (m_hicon == nullptr) {
                m_hicon = LoadIcon(NULL, IDI_APPLICATION);
        }

        // 窗口创建
        // 信息结构体
        WNDCLASSEX wc = { 0 };
        wc.cbSize = sizeof(WNDCLASSEX);
        wc.style = 0;
        wc.cbWndExtra = 0;
        wc.hbrBackground = m_hbrush;
        wc.hCursor = m_hcursor;
        wc.hIcon = m_hicon;
        wc.lpfnWndProc = WindowProc;
        wc.hInstance = m_hinstance;
        wc.lpszClassName = "youguess";
        wc.lpszMenuName = "sometitle";

        // 注册
        if (!RegisterClassEx(&wc)) {
                return;
        }
        else {
                // 创建窗口
                DWORD tmp_style = m_fullscreen ? (WS_MAXIMIZE | WS_POPUP) : WS_POPUP;
                m_hwnd = CreateWindow(
                        wc.lpszClassName, "san9pk",
                        tmp_style,
                        m_x, m_y, m_width, m_height,
                        NULL, NULL, m_hinstance, NULL
                );

                // 创建失败
                if (m_hwnd == NULL) {
                       
                }
        }
}

// 初始化渲染部分
void GameEngine::InitGraphicsProcess() {
        bool result = true;

        // 非全屏
        if (!m_fullscreen) {
                result = Engine_Graphics::InitGraphics(m_hwnd, RECT{ (LONG)m_x, (LONG)m_y, (LONG)m_width, (LONG)m_height });
        }

}

// 初始化数据库部分
void GameEngine::InitDataBaseProcess() {
        if (g_data != nullptr) {
                return;
        }

        g_data = new DataBase();
        g_data->InitDataBase();

}

// 初始化场景控制部分
void GameEngine::InitViewControlProcess() {
        if (g_view != nullptr) {
                return;
        }

        g_view = new Manager_View();
        g_view->Init();
}

// 处理事件
void GameEngine::Engine_CheckEvent() {
        // 处理事件
        unsigned int index = 0;
        while (1) {
                // 索引
                if (index >= eng_eventlist.size()) {
                        break;
                }

                index++;
        }

        // 清空事件列表
        eng_eventlist.clear();
}

// 处理更新
void GameEngine::Engine_Update() {
        //
        if (eng_state == SYS_STATE_EXIT) {
               
                return;
        }
        else {
                if (eng_state == SYS_STATE_BEGIN) {
                        eng_state = SYS_STATE_KEEP;
                }
                else {
                        // 场景更新
                        if (g_view != nullptr) {
                                g_view->Update();
                        }
                }
        }

        // 渲染系统更新
        Manager_UI::Update();
}

// 处理渲染
void GameEngine::Engine_Draw() {
        // 开始 + 清屏
        Engine_Graphics::Begin();

        //
        if (eng_state == SYS_STATE_EXIT) {
                return;
        }
        else {
                // 场景渲染
                if (g_view != nullptr) {
                        g_view->Draw();
                }
        }

        // UI系统绘制
        Manager_UI::Draw();

        // 结束
        Engine_Graphics::End();
}

// 运行引擎
void GameEngine::RunEngine() {

        // 窗体已创建
        if (m_hwnd != NULL) {
                // 显示和更新窗口
                if (m_fullscreen) {
                        ShowWindow(m_hwnd, SW_MAXIMIZE);
                }
                else {
                        ShowWindow(m_hwnd, SW_SHOW);
                }
                UpdateWindow(m_hwnd);


                // 消息循环
                MSG msg = { 0 };
                while (1) {

                        // 窗口消息
                        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
                                // 系统处理机制
                                TranslateMessage(&msg);
                                DispatchMessage(&msg);

                                if (msg.message == WM_QUIT) {
                                        break;
                                }
                        }
                        else {
                                // 计时器
                                Engine_CheckEvent();
                                Engine_Update();
                                Engine_Draw();
                        }
                }
        }
}

// 接收win32消息
void GameEngine::CheckWin32Msg(UINT msg, WPARAM wp, LPARAM lp) {
        // 渲染部分
        Manager_UI::CheckUpdate(msg, wp, lp);

        // 场景部分
        if (g_view != nullptr) {
                g_view->CheckUpdate(msg, wp, lp);
        }
}

// 判定引擎是否结束更新
bool GameEngine::IsActivity() {
        return (eng_state == SYS_STATE_EXIT);
}

// 发送结束引擎消息
void GameEngine::SelfKill() {
        if (m_hwnd != nullptr) {
                // 状态值更新
                eng_state = SYS_STATE_EXIT;

                // 立即发送摧毁窗口消息
                PostMessage(m_hwnd, WM_DESTROY, 0, 0);
        }
}
作者: 搞事    时间: 2021-9-23 21:58
感觉直接发代码好像不太好
作者: guoxiaomi    时间: 2021-9-24 01:37
搞事 发表于 2021-9-23 21:57
#include "GameEngine.h"

// 游戏引擎生成  

没有用SDL嘛,那画面上的内容是用什么画的?
作者: 搞事    时间: 2021-9-24 10:10
guoxiaomi 发表于 2021-9-24 01:37
没有用SDL嘛,那画面上的内容是用什么画的?

用的direct2d渲染的
作者: guoxiaomi    时间: 2021-9-26 01:09
渐变也做好了!现在绘图相关的应该都完成了。

作者: 小凡哥    时间: 2021-9-27 12:20
太强了,大佬
如果能顺利重写引擎的话,感觉可以直接超出“RPG maker”这个限制了
作者: b565185756    时间: 2021-10-1 13:31
先捕捉了宇宙最强的郭兄大人再说。。
作者: guoxiaomi    时间: 2021-10-3 15:46
本帖最后由 guoxiaomi 于 2021-10-3 16:09 编辑

做了个勉强能发布的版本v0.7.4:https://7niu.gxmatmars.com/p1/asxp/release_v0.7.4.zip

1. 已经在windows10沙盒里测试完毕。沙盒里安装RMXP后,工程可以正常打开
2. 工程里使用了默认素材。如果RTP没有安装在默认路径(C:\Program Files (x86)\RPG Maker XP\RGSS\Standard)下,就必须把RTP的Audio和Graphics拷贝到工程目录下,否则会找不到素材。
3. 这个版本没有声音。双击exe到窗口出现,以及标题画面出现各有一点点延迟
4. 可以修改Core/main.rb里的帧率

接下来的计划是测试完所有RGSS默认的事件确保兼容性,然后添加Audio模块,就差不多可以发布了吧?

自问:道理我都懂,但那个xxx.dll为什么那么大
自答:那是enigma virtual box打包的package,里面有完整的ruby3.0.0和SDL2全家桶的DLL。后缀名改为.dll是迷惑使用者。

打开后你应该能看到这个:

作者: siry冷月    时间: 2021-10-3 22:13
过于硬核的水贴,插眼。
作者: 哇哇哇啊叭叭    时间: 2021-10-4 09:10
本帖最后由 哇哇哇啊叭叭 于 2021-10-4 15:13 编辑


  突然觉得做游戏不香了想要转头学习脚本

[line]6[/line]
这个runtime是干什么用的呢?
  试着下载了一下,感觉跟正常的xp没太有区别呢(但其实肯定是有区别 啦)。看题目和之前的楼,是不是:
1. 楼主把RM重写了一遍
2. 可以在脚本中使用Ruby3.0和SDL。因此可以使用一些Ruby中比较新的语法、可以实现跨平台

  这个引擎是不是就是做这些用的呢?

作者: RPGzh500223    时间: 2021-10-4 10:14
哈哈,不明觉厉。
可惜是我不能用的样子,电脑太烂了,配置什么的不懂,举个例子,玩英雄联盟都卡的那种。
我打开资源管理器,与RMXP做了下对比。内存不知道干什么了(地图和菜单场景都差不多??),是RMXP的4倍的样子,
地图场景时,CPU占用高,与菜单场景和RMXP的地图场景比较的话,我大胆的猜测tilemap写得不算好……
切换场景好像GPU(不知道是干什么用的)也用了。
然后就是事件开天气之后,非常卡,慢镜头的感觉,关闭天气时,报错
小问题:场景切换有点“生硬”

error.png (181.5 KB, 下载次数: 36)

error.png

作者: guoxiaomi    时间: 2021-10-4 17:44
本帖最后由 guoxiaomi 于 2021-10-4 17:47 编辑
RPGzh500223 发表于 2021-10-4 10:14
哈哈,不明觉厉。
可惜是我不能用的样子,电脑太烂了,配置什么的不懂,举个例子,玩英雄联盟都卡的那种。
...


感谢测试!

我其实只测完了动画就放出来了,天气还没测试。内存占用目前也没有仔细测试,感觉好像就40M左右的样子,但应该没有内存泄漏(指内存占用会随着运行时间不停的增长)?如果你是集显,会使用内存当显存,可能会占的比较多?

场景切换的生硬具体是指啥?以及你的cpu型号和占用比例大概是多少?我这个是异步的需要2核才能正常运行。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1