public

Rpg Maker Developers Group

Simple enough for a child, powerful enough for a developer

2 Followers

Combine RGSS with ruby-c dll and speed up the game like a boss

BMM Archive · July 15, 2026

Preserved forum archive. This topic stores the original first post and locally mirrored RPG Maker Web attachments when available. It is posted by the BMMPlay archive account, not by the original creator.

Original Source

  • Original title: Combine RGSS with ruby-c dll and speed up the game like a boss
  • Original author: ken1882
  • Original date: March 19, 2019
  • Source thread: https://forums.rpgmakerweb.com/threads/combine-rgss-with-ruby-c-dll-and-speed-up-the-game-like-a-boss.107006/
  • Source forum path: Game Development Engines > RPG Maker Tutorials > RMVXAce Tutorials

Summary

WARNING: This post is not suitable for newbies, perhaps also not applied to the game that doesn't have a performance issue. It's suggested to know the following knowledge to fully understand how it works: RMVA Scripting experience(most important one, required)

Archived First Post

WARNING:
This post is not suitable for newbies, perhaps also not applied to the game that doesn't have a performance issue.

It's suggested to know the following knowledge to fully understand how it works:
  • RMVA Scripting experience(most important one, required)
  • Basic C/C++ knowledge
  • Familiar with Ruby and C/C++
  • PE(portable executable) and DLL(Dynamic Link Library)
Don't panic if you're not familiar with C/C++, I'll try my best to explain anyway.
A very basic thing that you should know is the datatype of all ruby object in C level is 'VALUE', a pointer to the object except some very basic object, like Fixnum, and you can see this part in ruby.c:
Code:
#define INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<1 | FIXNUM_FLAG))
in this line, SIGNED_VALUE generally is LONG(aka int) and FIXNUM_FLAG is 1, so you can think Fixnum is encoded by (n * 2 + 1) instead of the pointer. However, the VALUE of String and Float are both pointers. And you can get the object's address by:
Code:
obj.object_id << 1
(as known as multiply the object_id by 2)
we'll need that to pass the object from Game.exe to our dll later
------------------------I'm a random split line------------------------
Currently, I'm making a unique engine for my game, and as larger as it gets, the performance issue comes up...(duh)

Just like Python, one of the popular way to resolve this problem in interpreter language is mixing it with C-level code to speed up and improve the calculation significantly.


Before getting started, you will need:
- Ruby 1.9.2-p0 source code (download here), this is the ruby version that rgss using
- A C/C++ IDE, Visual Studio is a common option, but I also using Code::Blocks, VS is using for debugging DLL
- (optional) A debugger (I use VS), because the game will crash silently if something wrong with the dll

Once got the software running and prepared the DLL project, the next step is telling the compiler to know what's Ruby object, notice that we don't have to compile the ruby source code itself. Since RubyVM is running inside RGSS301.dll so we only need to declare necessary functions and datatypes and call RGSS301.dll while building up the dynamic link library. But if you're as silly as I am...managed to include the whole ruby to the dll and using the ruby function... Congratulations! You'll get ruby_vm_current_ptr is nullptr and the game crashes! (I f*cking even compile the whole ruby natively and it took me ages to build successfully...)

If you don't want to copy, edit and post the ruby source code, you can go download header files here and put them in the project folder, then include "ruby.h", this way you should have no trouble using VALUE in your C/CPP file. So the .hpp or .h file should like:
Code:
#include <windows.h>
#include "ruby.h"

Next, we're heading to the example, and what I gonna show here is how to improve the projectile collide detection, here're also some extra tips you should know while writing c code:
- Access VALUE as less as possible, the dll is slower than getting VALUE in RGSS
- Don't wrap the functions that frequently calling other methods into dll, the reason is above
- From 2 above, things needed to write into C-level are calculation-heavy functions
- Since Float are pointers, so using Fixnum if you can, and convert them to int and store in your C code
- avoid using std::vector, using new int [] if need to deal with fixed-length array

since the time complexity of simplest collide detection is O(n^2), only need O(n) time to access VALUE data, also not affect gameplay much if the projectile colliding effect is delayed by 1 frame so it's good to put that into C.

Before jump into the demo and explain the code, here's the result of my little experiment, I also used Theo's Anti-Lag to make the result better due to the fact that tons of projectiles also means tons of active sprites(unfortunately RMVA is not good at graphics processing), and the measurement is making a constantly updated event run from A point to B point 10 times, since the lag will slow the entire game down, so the one take less time is the better result.

Experiment Info:
> Using collision box as collide detection
> Distance of A to B: 10 tiles
> Measurement Event: x4 Faster Speed, Highest Frequency, through
> 5 projectiles are generated per frame update
> Maximum visible sprites number is 100/1000000000 (over will become invisible projectile lol)
> Total events: 277
> Total battler event: 65
※The result will vary on different hardware, tested using I5-6200U/4GB laptop


No projectile:
Average 1.0149 seconds in 10 runs

100 sprite limit, no dll nor anti-lag script:
Average 5.4282 seconds in 10 runs; lim -> 5.98 seconds with around 620 projectiles

100 sprite limit, with dll only:
Average 3.1801 seconds in 10 runs; lim -> 3.38 seconds with around 620 projectiles


100 sprite limit, with ATL only:
Average 3.3929 seconds in 10 runs; lim -> 3.92 seconds with around 676 projectiles


100 sprite limit, with both dll and ATL:
Average 1.3161 seconds in 10 runs; lim -> 1.39 seconds with around 676 projectiles


1,000,000,000 sprite limit, with dll only:
Average 4.3676 seconds in 10 runs; lim -> 5.11 seconds with around 650 projectiles

1,000,000,000 sprite limit, with ATL only:
Average 4.0854 seconds in 10 runs; lim -> 4.92 seconds with around 693 projectiles


1,000,000,000 sprite limit, with both dll and ATL:]

Average 2.3111 seconds in 10 runs; lim -> 3.09 seconds with around 693 projectiles


No projectile:
Ma7gokA.png


No anti-lag, native ruby collision detection, 100 sprite limit
wujLFQQ.png


with anti-lag, native ruby code, 100 sprite limit
lQWb4uc.png

1000000000 limit:
qQQWcA1.png


no anti-lag, C-level collide detection code, 100 sprite limit
kgDH5hh.png

1000000000 limit:
gpfg1yz.png


with anti-lag and C-level code, 100 sprite limit
VYj9HVl.png

1000000000 limit:
gOujwkb.png

Download the source code of DLL project: https://github.com/ken1882/RGSS-Ext
Download the Demo: https://mega.nz/#!AlZiAK6A!cCybazZERTQmkT0TELzZpAu6I2AnUZTf1nCRAnDsPPA (Google Drive tends to think executable is infected virus for some reason)

<next: building dll>

Downloads / Referenced Files

Log in to download

Log in, then follow the RPG Maker Developers Group to see these download links.

Log in to download
Creator Claims / Removal

If you are the original creator and want this listing reassigned, edited, or removed, join BMMPlay and contact the moderators with proof that matches the original RPG Maker Web profile, linked GitHub, itch.io page, or another public creator identity.

#039#define#include#rpg-maker-archive#vxace-tutorials

Replies (0)

No replies yet.

0 replies 1 view

Log in to reply.

User Avatar