I have figured out how to properly expose C++ classes to Ruby so you don't have to.
There are three things that you always have to keep in mind.
1. Every function/method returns the a variable of type VALUE. If the function/method doesn't actually return anything (void in C/C++), then because of Ruby, it has to return Qnil.
2. Every function/method has its containing class as first parameter. I have named that parameter self. The parameter is of type VALUE.
3. When exposing functions to Ruby, you disregard the fact that the first parameter is actually self and use argc as if the self parameter wasn't there.
You can take a look at my first implementation of Graphics::getFrameCount (Graphics.frame_count), Graphics::setFrameCount (Graphics.frame_count=) and Graphics::update (Graphics.update). I implemented them in Graphics::createRubyInterface. All RGSS classes should have createRubyInterface defined for the exposure to Ruby.
The whole C API is listed here: http://www.ruby-doc.org/docs/ProgrammingRuby/html/ext_ruby.html#S8
You will most probably need only rb_define_class, rb_define_method, rb_define_module and rb_define_module_function.
It's nice seeing a few nice examples. I was reading into this a few days ago in preparation, and wasn't exactly sure how easy/hard it would be in practice.
So was I. I had some time yesterday so I decided to try it out. It's the next logical step to bind C++ and Ruby before we can continue working on it.
Once I have put together a proper rendering method (Graphics.update), I will make a task for interfaces similar to the one I have made for Graphics so far. Of course I will interface one or two more classes fully so you have many examples which you can work with. :)
The more examples the better. :)
If you haven't noticed already, my C++ skill is sketchy, at best. I'm trying to learn it as we go.
I have implemented module Input and added some temporary test stuff in Graphics.
You can now compile and run ARC. Press the B button to quit and press the C button to reset the frame count. I will post a task now for the implementation of the interfaces.
This is getting exciting now. :naughty:
I was pumped when we first starting, but now that things are starting to really come together and we are getting some actual results, this is AWESOME!
I have implemented a sprite rendering queue and interfaced a few methods myself. For now the sprite actually just renders a randomly colored 80x80 rectangle, but once I have implemented properly the Bitmap class, we will have our first sprites ready to go. :D
But for that the Bitmap class has to be interfaced first. :P
I should be able to do some work after school today, dad won't be around :3
There's just one important thing. I have defined an allocation function. Basically when you call ClassName.new first the allocation method is called, then the initialize method is called. The allocation method can be literally exactly the same in all classes for now. So simply copy paste my implementation of rb_new when you use it.
Also, don't forget the new naming convention of Ruby exposed methods with rb_ as prefix.
*double posts*
Before we can continue working, I want you guys to check out what's been done so far. To be able to continue, you have to understand what has been done. Go through the code, read the headers, read the source files. Try to understand how everything is structured. If you have questions, ask. We won't really be able to continue until you understand the code so far.
*triple posts*
If you guys haven't done what I suggested in my previous post, now is a good time. :P
I have additionally implemented some more features of the Sprite class today.
EDIT: I was able to split off a class with some common features. The Renderable class is a superclass of Sprite (and it will be for Window, Viewport and Plane and maybe Tilemap as well). But Renderable is not exposed to Ruby. One problem is that because Ruby creates our instances of Sprite, etc., no virtual function pointer table is created and we can't use any kind of polymorphism. That's why I have added an additional variable called type which is set to one of four (or five if we include Tilemap) possible values. This value determines which class it actually is and calls the proper draw method.
This may seem like a dirty trick (and I assure you, it is, it's very dirty), but at least we don't have to duplicate so much code (e.g. setting a bitmap, setting the Z coordinate, setting the offset X and offset Y coordinates, etc.). Also, we can put all objects into one single rendering queue instead of having to keep track of multiple queues (each one for windows, sprites, planes and viewports). I'll change the unsigned int variable to an enum later.