Let’s Build a Simple Video Game with JRuby: A Tutorial »

Created at: 15.12.2011 02:34, source: Ruby Inside, tagged: Cool jruby Tutorials

Ruby isn't known for its game development chops despite having a handful of interesting libraries suited to it. Java, on the other hand, has a thriving and popular game development scene flooded with powerful libraries, tutorials and forums. Can we drag some of Java's thunder kicking and screaming over to the world of Ruby? Yep! - thanks to JRuby. Let's run through the steps to build a simple 'bat and ball' game now.

The Technologies We'll Be Using

JRuby

If you're part of the "meh, JRuby" brigade, suspend your disbelief for a minute. JRuby is easy to install, easy to use, and isn't going to trample all over your system or suck up all your memory. It will be OK!

One of JRuby's killer features is its ability to use Java libraries and generally dwell as a first class citizen on the JVM. JRuby lets us use performant Java powered game development libraries in a Rubyesque way, lean on Java-based tutorials, and basically have our cake and eat it too.

To install JRuby, I recommend RVM (Ruby Version Manager). I think the JRuby core team prefer you to use their own installer but rvm install jruby has always proven quick and effective for me. Once you get it installed, rvm use jruby and you're done.

Slick and LWJGL

The Slick library is a thin layer of structural classes over the top of LWJGL (Lightweight Java Game Library), a mature and popular library that abstracts away most of the boring system level work.

Out of the box LWJGL gives us OpenGL for graphics, OpenAL for audio, controller inputs, and even OpenCL if we wanted to do heavy parallelism or throw work out to the GPU. Slick gives us constructs like game states, geometry, particle effects, and SVG integration, while allowing us to drop down to using LWJGL for anything we like.

Getting Started: Installing Slick and LWJGL

Rather than waste precious time on theory, let's get down to the nitty gritty of getting a basic window and some graphics on screen:

  • First, create a folder in which to store your game and its associated files. From here I'll assume it's /mygame
  • Go to the Slick homepage and choose "Download Full Distribution" (direct link to .zip here).
  • Unzip the download and copy the lib folder into your /mygame as /mygame/lib - this folder includes both LWGWL and Slick.
  • In /mygame/lib, we need to unpack the natives-[your os].jar file and move its contents directly into /mygame.

    Mac OS X: Right click on the natives-mac.jar file and select to unarchive it (if you have a problem, grab the awesome free The Unarchiver from the App Store) then drag the files in /mygame/lib/native-mac/* directly into /mygame.

    Linux and Windows: Running jar -xf natives-linux.jar or jar -xf natives-win32.jar and copying the extracted files back to /mygame should do the trick.

  • Now your project folder should look a little like this:

    If so, we're ready to code.

A Bare Bones Example

Leaping in with a bare bones example, create /mygame/verybasic.rb and include this code:

$:.push File.expand_path('../lib', __FILE__)

require 'java'
require 'lwjgl.jar'
require 'slick.jar'

java_import org.newdawn.slick.BasicGame
java_import org.newdawn.slick.GameContainer
java_import org.newdawn.slick.Graphics
java_import org.newdawn.slick.Input
java_import org.newdawn.slick.SlickException
java_import org.newdawn.slick.AppGameContainer

class Demo < BasicGame
  def render(container, graphics)
    graphics.draw_string('JRuby Demo (ESC to exit)', 8, container.height - 30)
  end

  # Due to how Java decides which method to call based on its
  # method prototype, it's good practice to fill out all necessary
  # methods even with empty definitions.
  def init(container)
  end

  def update(container, delta)
    # Grab input and exit if escape is pressed
    input = container.get_input
    container.exit if input.is_key_down(Input::KEY_ESCAPE)
  end
end

app = AppGameContainer.new(Demo.new('SlickDemo'))
app.set_display_mode(640, 480, false)
app.start

Ensure that ruby actually runs JRuby (using ruby -v) and then run it from the command line with ruby verybasic.rb. Assuming all goes well, you'll see this:

If you don't see something like the above, feel free to comment here, but your problems most likely orient around not having the right 'native' libraries in the current directory or from not running the game in its own directory in the first place (if you get probable missing dependency: no lwjgl in java.library.path - bingo).

Explanation of the demo code

  • $:.push File.expand_path('../lib', __FILE__) pushes the 'lib' folder onto the load path. (I've used push because my preferred << approach breaks WordPress ;-))
  • require 'java' enables a lot of JRuby's Java integration functionality.
  • Note that we can use require to load the .jar files from the lib directory.
  • The java_import lines bring the named classes into play. It's a little like include, but not quite.
  • We lean on Slick's BasicGame class by subclassing it and adding our own functionality.
  • render is called frequently by the underlying game engine. All activities relevant to rendering the game window go here.
  • init is called when a game is started.
  • update is called frequently by the underlying game engine. Activities related to updating game data or processing input can go here.
  • The code at the end of the file creates a new AppGameContainer which in turn is given an instance of our game. We set the resolution to 640x480, ensure it's not in full screen mode, and start the game.

Fleshing Out a Bat and Ball Game

The demo above is something but there are no graphics or a game mechanic, so it's far from being a 'video game.' Let's flesh it out to include some images and a simple pong-style bat and ball mechanic.

Note: I'm going to ignore most structural and object oriented concerns to flesh out this basic prototype. The aim is to get a game running and to understand how to use some of Slick and LWJGL's features. We can do it again properly later :-)

All of the assets and code files demonstrated here are also available in an archive if you get stuck. Doing it all by hand to start with will definitely help though.

A New Code File

Start a new game file called pong.rb and start off with this new bootstrap code (very much like the demo above but with some key tweaks):

$:.push File.expand_path('../lib', __FILE__)

require 'java'
require 'lwjgl.jar'
require 'slick.jar'

java_import org.newdawn.slick.BasicGame
java_import org.newdawn.slick.GameContainer
java_import org.newdawn.slick.Graphics
java_import org.newdawn.slick.Image
java_import org.newdawn.slick.Input
java_import org.newdawn.slick.SlickException
java_import org.newdawn.slick.AppGameContainer

class PongGame < BasicGame
  def render(container, graphics)
    graphics.draw_string('RubyPong (ESC to exit)', 8, container.height - 30)
  end

  def init(container)
  end

  def update(container, delta)
    input = container.get_input
    container.exit if input.is_key_down(Input::KEY_ESCAPE)
  end
end

app = AppGameContainer.new(PongGame.new('RubyPong'))
app.set_display_mode(640, 480, false)
app.start

Make sure it runs, then move on to fleshing it out.

A Background Image

It'd be nice for our game to have an elegant background. I've created one called bg.png which you can drag or copy and paste from here (so it becomes /mygame/bg.png):

Now we want to load the background image when the game starts and render it constantly.

To load the game at game start, update the init and render methods like so:

def render(container, graphics)
  @bg.draw(0, 0)
  graphics.draw_string('RubyPong (ESC to exit)', 8, container.height - 30)
end

def init(container)
  @bg = Image.new('bg.png')
end

The @bg instance variable picks up an image and then we issue its draw method to draw it on to the window every time the game engine demands that the game render itself. Run pong.rb and check it out.

Adding A Ball and Paddle

Adding a ball and paddle is similar to doing the background. So let's give it a go:

def render(container, graphics)
  @bg.draw(0, 0)
  @ball.draw(@ball_x, @ball_y)
  @paddle.draw(@paddle_x, 400)
  graphics.draw_string('RubyPong (ESC to exit)', 8, container.height - 30)
end

def init(container)
  @bg = Image.new('bg.png')
  @ball = Image.new('ball.png')
  @paddle = Image.new('paddle.png')
  @paddle_x = 200
  @ball_x = 200
  @ball_y = 200
  @ball_angle = 45
end

The graphics for ball.png and paddle.png are here. Place them directly in /mygame.

We now have this:

Note: As I said previously, we're ignoring good OO practices and structural concerns here but in the long run having separate classes for paddles and balls would be useful since we could encapsulate the position information and sprites all together. For now, we'll 'rough it' for speed.

Making the Paddle Move

Making the paddle move is pretty easy. We already have an input handler in update dealing with the Escape key. Let's extend it to allowing use of the arrow keys to update @paddle_x too:

def update(container, delta)
  input = container.get_input
  container.exit if input.is_key_down(Input::KEY_ESCAPE)

  if input.is_key_down(Input::KEY_LEFT) and @paddle_x > 0
    @paddle_x -= 0.3 * delta
  end

  if input.is_key_down(Input::KEY_RIGHT) and @paddle_x < container.width - @paddle.width
    @paddle_x += 0.3 * delta
  end
end

It's crude but it works! (P.S. I'd normally use && instead of and but WordPress is being a bastard - I swear I'm switching one day.)

If the left arrow key is detected and the paddle isn't off the left hand side of the screen, @paddle_x is reduced by 0.3 * delta and vice versa for the right arrow.

The reason for using delta is because we don't know how often update is being called. delta contains the number of milliseconds since update was last called so we can use it to 'weight' the changes we make. In this case I want to limit the paddle to moving at 300 pixels per second and 0.3 * 1000 (1000ms = 1s) == 300.

Making the Ball Move

Making the ball move is similar to the paddle but we'll be basing the @ball_x and @ball_y changes on @ball_angle using a little basic trigonometry.

If you stretch your mind back to high school, you might recall that we can use sines and cosines to work out the offset of a point at a certain angle within a unit circle. For example, our ball is currently moving at an angle of 45, so:

Math.sin(45 * Math::PI / 180)   # => 0.707106781186547
Math.cos(45 * Math::PI / 180)   # => 0.707106781186548

Note: The * Math::PI / 180 is to convert degrees into radians.

We can use these figures as deltas by which to move our ball based upon a chosen ball speed and the delta time variable that Slick gives us.

Add this code to the end of update:

@ball_x += 0.3 * delta * Math.cos(@ball_angle * Math::PI / 180)
@ball_y -= 0.3 * delta * Math.sin(@ball_angle * Math::PI / 180)

If you run the game now, the ball will move up and right at an angle of 45 degrees, though it will continue past the game edge and never return. We have more logic to do!

Note: We use -= with @ball_y because sines and cosines use regular cartesian coordinates where the y axis goes from bottom to top, not top to bottom as screen coordinates do.

Add some more code to update to deal with ball reflections:

if (@ball_x > container.width - @ball.width) || (@ball_y < 0) || (@ball_x < 0)
  @ball_angle = (@ball_angle + 90) % 360
end

This code is butt ugly and pretty naive (get ready for a nice OO design assignment later) but it'll do the trick for now. Run the game again and you'll notice the ball hop through a couple of bounces off of the walls and then off of the bottom of the screen.

Resetting the Game on Failure

When the ball flies off of the bottom of the screen, we want the game to restart. Let's add this to update:

if @ball_y > container.height
  @paddle_x = 200
  @ball_x = 200
  @ball_y = 200
  @ball_angle = 45
end

It's pretty naive again, but does the trick. Ideally, we would have a method specifically designed to reset the game environment, but our game is so simple that we'll stick to the basics.

Paddle and Ball Action

We want our paddle to hit the ball! All we need to do is cram another check into update (poor method - promise to refactor it later!) to get things going:

if @ball_x >= @paddle_x and @ball_x < = (@paddle_x + @paddle.width) and @ball_y.round >= (400 - @ball.height)
  @ball_angle = (@ball_angle + 90) % 360
end

Note: WordPress has borked the less than operator in the code above. Eugh. Fix that by hand ;-)

And bingo, we have it. Run the game and give it a go. We have a simple, but performant, video game running on JRuby.

If you'd prefer everything packaged up and ready to go, grab this archive file of my /mygame directory.

What Next?

Object orientation

As I've taken pains to note throughout this article, the techniques outlined above for maintaining the ball and paddle are naive - an almost C-esque approach.

Building separate classes to maintain the sprite, position, and the logic associated with them (such as bouncing) will clean up the update method significantly. I leave this as a task for you, dear reader!

Stateful Games

Games typically have multiple states, including menus, game play, levels, high score screens, and so forth. Slick includes a StateBasedGame class to help with this, although you could rig up your own on top of BasicGame if you really wanted to.

The Slick wiki has some great tutorials that go through various elements of the library, including a Tetris clone that uses game states. The tutorials are written in Java, naturally, but the API calls and method names are all directly transferrable (I'll be writing an article about 'reading' Java code for porting to Ruby soon).

Packaging for Distribtion

One of the main reasons I chose JRuby over the Ruby alternatives was the ability to package up games easily in a .jar file for distribution. The Ludum Dare contest involves having other participants judge your game and since most participants are probably not running Ruby, I wanted it to be relatively easy for them to run my game.

Warbler is a handy tool that can produce .jar files from a Ruby app. I've only done basic experiments so far but will be writing up an article once I have it all nailed.

Ludum Dare

I was inspired to start looking into JRuby and Java game libraries by the Ludum Dare game development contest. They take place every few months and you get 48 hours to build your own game from scratch. I'm hoping to enter for the first time in just a couple of days and would love to see more Rubyists taking part.


more »

Ruby, Concurrency, and You »

Created at: 14.10.2011 19:41, source: Engine Yard Blog, tagged: Open Source Technology 1.8 1.9 concurrency GIL implementations ironruby jruby macruby maglev MRI parallelism rubinius ruby threads

tl;dr
Ruby Implementation Concurrency Parallelism
MRI 1.8
MRI 1.9
Rubinius 1
Rubinius 2
JRuby
MacRuby
Maglev
IronRuby

A big topic in the world of Ruby this year has been how to get more out of Ruby, specifically, how to get more done in parallel. The topic of concurrency, though, is one fraught with misunderstanding. This is largely due to the complexities of not only thinking about multiple things at once, but the limitations of Ruby implementations and operating systems.

In this article, I’ll lay the groundwork for understanding the difference between concurrency and parallelism. Then, I’ll look at how a programmer experiences them.

Concurrency vs. Parallelism

This has been discussed many times, but I sometimes still have difficulty with it. Let’s first break down the definitions of these two words:

  • Concurrent: existing, happening, or done at the same time
  • Parallel: occurring or existing at the same time or in a simple way

Hmm, ok. Well, that hasn’t improved our thinking about these two topics. We need to dig deeper into how the world of computing applies to these words. Rather than looking at the abstract, let’s instead consider some real world examples.

A “Real World” Example

Let’s say you’ve sat down for the evening to complete tomorrow’s homework. This evening you’ve got both Math and History worksheets to fill out. Tonight for some reason, you decide to do one problem in Math, then one problem in History, then back to Math, etc until all the problems are done.

In the parlance of computing, you’re now doing your Math and History worksheets concurrently. This is because your Current task list includes 2 items: Math worksheet and History worksheet.

Now, clearly you the reader can see a problem here. By switching back and forth, completing your homework will probably take longer than if you did the complete Math worksheet then did the History worksheet. In other words, if you did the worksheets in serial.

So, if concurrent means “having multiple outstanding tasks at once”, then what is parallel? Parallel is the ability to make progress on multiple tasks simultaneously.

Let’s say you’ve been asked to read the book One O’Clock Jump by Lise McClendon. You also need to drive down to San Diego for Comic-Con. Thankfully you find that One O’Clock Jump is available on audiobook!

You can now listen to the book while driving. You’re simultaneously making progress on two separate tasks. This is the equivalent of parallelism in computing.

I hope that these real world examples help illustrate the difference between concurrency and parallelism. Now let's apply this newfound knowledge to Ruby.

Back to Ruby

One reason this problem can be difficult to understand is because Ruby only provides a single mechanism for concurrency. But, whether or not these Threads are parallel depends on a number of factors.

MRI 1.8

Let’s look at MRI 1.8 (and MRI forks such as REE) to begin with, because it has the simplest model. MRI 1.8 uses a technique known as “green threads” to implement Threads. This means that every once in a while (around 100 milliseconds), the program says “oh, I should let another thread run now!” This saves the current info into the current thread and restores another thread. This is exactly like our homework example above. We can have as many things as we’d like in our task list, but we can only make progress on one of them at a time.

There is a wrinkle in the concurrency/parallelism game that I haven’t mentioned before now. This wrinkle is IO, namely how Threads interact when waiting for some external event. MRI 1.8.7 is quite smart, and knows that when a Thread is waiting for some external event (such as a browser to send an HTTP request), the Thread can be put to sleep and be woken up when data is detected. This simple consolation improves the usage of Threads so much that for a very long time the MRI 1.8.7 model was good enough for all Ruby programs.

MRI 1.9

Switching back to Ruby implementations, let’s look at MRI 1.9. As has been previously reported, MRI 1.9 removes the “green threads” we had in MRI 1.8 and uses native threads to implement the Thread class. Now, what are these “native threads”? These are are units of concurrency that the underlying operating system is aware of. A big reason to switch to use native threads is that it vastly simplifies the implementation of Threading. The operating system handles the low level parts of saving and restoring Thread information in a completely transparent way. Additionally, letting the OS know what parts of a program should be concurrent allows it to use the full resources of the computer to make that happen. In this modern world, that means using multiple cores.

Up until now, all we’ve talked about with Ruby’s Threading model was about concurrency, the ability to have multiple outstanding tasks at once. Now when we add in the idea of multiple cores, we can finally talk about parallelism. When a computer includes multiple cores (which is pretty much every computer now), those cores can run different code simultaneously, providing true parallelism. When a computer only has one core, there is no true parallelism, instead there is just simple concurrency, even at the OS level. The OS manages all the processes and threads in the system the same way you handled your Math and History worksheets, doing one for a little while, then grabbing another one.

Back to multiple cores though. Now that there is the opportunity to run things truly in parallel, we have to look at if Ruby can take advantage of that. Since MRI 1.9 uses OS threads, it can actually spread out your Ruby Threads to multiple cores!

Unfortunately, MRI 1.9 prevents the Ruby code itself from running in parallel by requiring that any thread running Ruby code hold a lock. This lock is commonly knows as the GIL (Global Interpreter Lock) or GVL (Global VM Lock).

There are a few reasons the GIL to exists, but for this discussion we will say that it’s because the non-Ruby parts of MRI 1.9 are not thread-safe. This means if data were manipulated by multiple threads at the same time, the data could become corrupt. The important thing for this post is how it applies to parallelism: the GIL inhibits parallelism within Ruby code.

MRI 1.9 uses the same technique as MRI 1.8 to improve the situation, namely the GIL is released if a Thread is waiting on an external event (normally IO) which improves responsiveness. MRI 1.9 also includes an experimental API that C extensions can use to run some C code without the GIL locked to utilize parallelism. This API is very restrictive though because no Ruby object may be accessed in any way while the GIL is not held by the current thread.

That about sums up the situation with MRI 1.8 and 1.9 with regards to concurrency and parallelism. Both provide concurrency of Ruby code, but neither provide parallelism of Ruby code.

Rubinius

Let’s take a quick look at other Ruby implementations where things are a bit different than MRI. I’ll start with Rubinius, since it’s the one I’m most familiar with. Rubinius 1.x also had a GIL and worked pretty much the same as MRI 1.9. With the upcoming 2.0 release though, the GIL will be removed, allowing Ruby code to run fully concurrent and fully parallel. We think this opens up a lot of uses for Ruby (parallel algorithms, etc) that Rubinius couldn’t handle well previously.

JRuby

JRuby layers the Thread class on top of Java’s thread class, so the threading model is whatever the JVM supports. That being said, OpenJDK is the primary JVM; it puts a Java thread directly onto an OS thread with no GIL. Thusly, JRuby almost always has full concurrency and parallelism available to it.

MacRuby

MacRuby also uses Cocoa’s NSThread as its abstraction, which runs without a GIL. So, this is another fully parallel implementation.

Maglev

Maglev runs directly on top of a Smalltalk VM and thusly layers the Thread class on top of a concept called Smalltalk Processes. In this case, the GemStone VM implements Processes in the same way as MRI 1.8, namely via “green threads” that don’t expose concurrency to the OS, and therefore, have no parallelism.

IronRuby

Lastly, IronRuby layers Thread directly on top of CLR’s threads without a GIL.

Conclusion

I hope that this helps to clear up what concurrency and parallelism are and how the different Ruby implementations address them. Having this understanding is critical for discussing and understanding topics such and thread-safety of libraries and performance of applications.

In future posts, we’ll look to build on this knowledge to help you make the best use of Ruby!


more »

Rails 3.1 and JRuby »

Created at: 10.10.2011 13:03, source: Ruby Rockers, tagged: Solutions Technology jruby rails

Hi Folks,

If you are doing any application in which you required JRuby as a platform. You can use Rails3.1 with that. activerecord-jdbc-adapter 1.2.0 is ok with that!

All the steps are same as for the normal Rails Application

You can find more details here http://blog.jruby.org/2011/09/ar-jdbc-1-2-0-released/

 

Cheers,
Arun


more »

JRuby GA on an Engine Yard Cloud Near You »

Created at: 28.09.2011 16:13, source: Engine Yard Blog, tagged: News Product Technology jruby jruby on appcloud jruby on engine yard cloud trinidad

We are very excited to announce the general availability of JRuby and Trinidad on Engine Yard Cloud!

Everyone who runs production Ruby web applications should be interested in JRuby. Want a list of life-changing reasons? Reasons you cannot get with any other Ruby implementation nor any other Platform as a Service?

Want to try Trinidad/JRuby on your laptop right this very instant? Do this. Do it now:

rvm install jruby
rvm use jruby
git clone git://github.com/engineyard/todo.git
cd todo
bundle
trinidad

Your application is now running in development mode on your laptop!

Want to try Trinidad/JRuby with your own Ruby web app this very instant? Here is a simple tutorial to get started!

Want to learn more about the awesomeness in JRuby and Trinidad (amongst other topics)? In New Orleans this week for RubyConf? Then on Saturday come and see “High Performance Ruby: Evented vs Threaded”.

We are so excited to be able to support JRuby and to finally be offering it and supporting it for big businesses and small on our Engine Yard Cloud and Engine Yard Managed platforms.

For the last two years, Engine Yard has been funding the development of JRuby and we are excited to provide fully supported JRuby for your application development. This is a major milestone for the JRuby project led by Charlie Nutter, Thomas Enebo, Nick Seiger, Hiro Asari, and David Calavera. Charlie has written a great post about the history and next steps of the project here.


more »

It’s All About JRuby »

Created at: 23.09.2011 19:56, source: Engine Yard Blog, tagged: community events Open Source javaone jruby san francisco jruby meetup

[caption id="attachment_10652" align="alignright" width="300" caption="Photo courtesy of Flickr user veganstraightedge*"][/caption]

On the tails of an excellent San Francisco JRuby meetup last night, we're delighted to be heading to JavaOne in a few weeks. JavaOne is October 2-5 and is held right in our backyard in downtown San Francisco. The multi-track conference is devoted to innovative developments and cutting edge implementations of Java. Naturally, we'll be dishing up all the sweet, sweet JRuby goodness you can handle.

Nick Sieger will be kicking it off right on Monday, October 3 with a talk about how you can add Ruby agility to your Java web stack.

On Tuesday night, October 4, be sure to stop by Engine Yard HQ around 7:30 for even more face time with the JRuby core team at our JavaOne after-party. Socialize with your fellow conference-goers and JRuby enthusiasts of all kinds at our rooftop penthouse. Don't miss special presentations by JRuby experts--drinks, snacks and networking will follow.

On Wednesday, October 5 our own Jacob Lehrbaum and Mike Piech will give you the inside scoop on how to leverage JRuby in your cloud-centric business. Tom Enebo, Charles Nutter and Dr Nic Williams will also be out and about repping JRuby, so don't be afraid to stop by the Engine Yard booth to discuss this awesome technology with the foremost experts over a beer. Great giveaways and prizes await!

JRuby will also be a contender again this year in the JavaOne Script Bowl! With competitors weighing in from the Clojure, Groovy and Scala sides, we need the community behind us to give JRuby the righteous victory it deserves. Come check it out on Wednesday, October 5 at 8:30am at the Hilton San Francisco, and judge for yourself which scripting language supplements your Java platform best. Support Dr Nic and the JRuby core team as they show off the latest and greatest in JRuby.

Lastly, for any interested JRubyists who missed the JRuby Jam virtual session last week, you can now watch the full presentation and view the slides.

JRuby Jam Session from Engine Yard on Vimeo.

We hope you’ll join us in celebrating JRuby virtually, or better yet, in-person!

*I <3 JRuby shirt photo courtesy of Flickr user veganstraightedge.


more »