|
From: Tim B. <tim...@gm...> - 2006-02-22 18:16:16
|
Jonathan,
Thanks for your comments. My example was extracted from a more
complex game project that I've been using to investigate RubyCocoa.
I like using the document-based architecture because it lets me log
game events and easily save and restore them for game replays, which
are great for demos, debugging, and performance analysis.
My "advanced" version of the game supports two players and subdivides
rocks (large rocks break into two medium-sized rocks, medium-sized
rocks break into two small rocks, which then can be destroyed). The
result is that there are a lot more objects flying around, which
starts to slow down the game (even when I disable collision
detection, which is an obvious potential bottleneck).
One possible optimization is to replace the Sprite class with a
version written in Objective-C. Ideally, we could just swap in a
new parent class with no changes to its subclasses. But in practice,
I had several problems:
* The Ruby versions of Sprite and its subclasses must already be
using Objective-C alloc/init construction instead of new.
* Methods in Ruby subclasses that will be replaced by Objective-C
classes must map to Objective-C message names.
* Something needs to be done to resolve the different calling
conventions used by Ruby attribute setters ("object =") and Cocoa KVC
setters ("setObject").
* When a Ruby subclass overrides an Objective-C class method, an
"ns_overrides" declaration seems to be necessary. But if the parent
class is switched back to Ruby (for debugging or testing), that
"ns_overrides" is a fatal error.
Surprisingly, I found that replacing the Ruby Sprite class with an
Objective-C version didn't speed up my game; in fact it seemed to
slow it down a bit. The reason for this was that the new version was
making more calls across the bridge, and calls across the bridge are
much more expensive than code implemented in Ruby or calls to
standard Ruby C extensions. I made some crude measurements and
estimated that the best I could hope for was a few thousand bridge
crossings per second. That's plenty for a typical Cocoa app, but not
enough for an arcade game that uses RubyCocoa to draw and manage
objects. So I switched back to my Ruby Sprite class and rewrote my
object drawing functions as standard Ruby C extensions. After that I
had only 2-3 bridge crossings per frame and the game was snappy
again, even with the brute-force Ruby collision detection that I had
worried about initially.
So to conclude, I found RubyCocoa to be great for prototyping,
designing, and testing. I used code that I had written in Ruby to
guide C and Objective-C rewrites. If I take this project further, I
expect that I will rewrite more of the game objects and their
management in Objective-C and use Ruby for testing, top-level game
control, and user input handling.
Tim
p.s. You suggested the following procedure for setting the Document
class:
> Rather than editing the pbxproj file manually:
> Targets inspector -> rubyrocks -> Info.plist Entries -> Document
Types -> Document Class
Have you verified this? If you can do this for the rubyrocks project,
would you please send me a screenshot? I may be missing something
obvious; it's not working for me. I know that it's possible for
Cocoa Document-based apps, but the RubyCocoa project template seems
to be different. When I look at the rubyrocks target with the
inspector, I only see two tabs: "General" and "Comments". I don't
see how I could use either to modify the Info.plist file. I'm using
Xcode 2.2.1. Thanks!
On Feb 22, 2006, at 2:36 AM, Jonathan Paisley wrote:
>
> On 22 Feb 2006, at 7:23, Tim Burks wrote:
>
>> This evening I spoke to the San Francisco Ruby Meetup group about
>> RubyCocoa. I thought it would be fun to describe RubyCocoa with
>> an example, so I presented a simple arcade-style game written in
>> Ruby that uses RubyCocoa to draw and handle user events. I also
>> wrote it up as a tutorial and put it online here: http://
>> www.rubycocoa.com/ruby-rocks.
>
> Great stuff!
>
> A few comments on the tutorial:
>
> Probably worth mentioning up front that a game wouldn't normally be
> a document-based application (and say at the end what would be
> different to use a non-document application template).
>
> Rather than editing the pbxproj file manually:
> Targets inspector -> rubyrocks -> Info.plist Entries -> Document
> Types -> Document Class
>
> I couldn't see any instructions for binding GameView.game to the
> Game instance (File's Owner) in Interface Builder.
>
> The instructions for adding the 'game' outlet aren't as detailed as
> the result of the instructions in Interface Builder.
>
> You can just use [a,b,c,d] instead of OSX::NSRect.new(a,b,c,d)
> (similarly for NSPoint), unless you want to hang on to the object
> and use .x, .y etc.
>
> The moveWithBounds_ and initWithPosition_ methods etc don't need a
> trailing underscore.
>
> The model objects (Sprite and descendents) can be plain Ruby
> objects rather than NSObject descendents. This means you can use a
> normal ruby initialize method (instead of .alloc.initWith...).
>
> Cheers,
> Jonathan
>
>
>
|