Finite Improbability

Just programming and math, no spontaneously jumping undergarments

Game dev in Scala II

More playing around with Scala and slick. Here’s the GeomTest.java file rewritten in scala:

/* A conversion of the GeomTest.java program from the slick tests to
 scala. Of special note is the replacement of the ternary operator
 with a value storing an anonymous fnction.  */

import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Circle;
import org.newdawn.slick.geom.Ellipse;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.RoundedRectangle;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.geom.Transform;

/**
 * A geomertry test
 */
object GeomTest {
  class GeomTest(s : String) extends BasicGame(s : String) {
    /** The rectangle drawn */
    val rect = new Rectangle(100,100,100,100);
    /** The rectangle drawn */
    val circle = new Circle(500,200,50);
    /** The rectangle tested */
    val rect1 = new Rectangle(150,120,50,100).transform(Transform.createTranslateTransform(50, 50));
    /** The rectangle tested */
    val rect2 = new Rectangle(310,210,50,100).transform(
      Transform.createRotateTransform(Math.toRadians(45).asInstanceOf[Float], 335, 260));
    /** The circle tested */
    val circle1 = new Circle(150,90,30);
    /** The circle tested */
    val circle2 = new Circle(310,110,70);
    /** The circle tested */
    val circle3 = new Ellipse(510, 150, 70, 70);
    /** The circle tested */
    val circle4 = new Ellipse(510, 350, 30, 30).transform(
      Transform.createTranslateTransform(-510, -350)).transform(
        Transform.createScaleTransform(2, 2)).transform(
          Transform.createTranslateTransform(510, 350));
    /** The RoundedRectangle tested */
    val roundRect = new RoundedRectangle(50, 175, 100, 100, 20);
    /** The RoundedRectangle tested - less cornders */
    val roundRect2 = new RoundedRectangle(50, 280, 50, 50, 20, 20, RoundedRectangle.TOP_LEFT | RoundedRectangle.BOTTOM_RIGHT);

    /**
     * @see org.newdawn.slick.BasicGame#init(org.newdawn.slick.GameContainer)
     */
    override def init(container : GameContainer) { }

    /**
     * @see org.newdawn.slick.BasicGame#render(org.newdawn.slick.GameContainer, org.newdawn.slick.Graphics)
     */
    override def render(container : GameContainer, g : Graphics) {
      g.setColor(Color.white);
      g.drawString("Red indicates a collision, green indicates no collision", 50, 420);
      g.drawString("White are the targets", 50, 435);

      g.scale(10, 10);
      g.setColor(Color.red);
      g.fillRect(10,0,5,5);
      g.setColor(Color.white);
      g.drawRect(10,0,5,5);
      g.scale(1/10.0f, 1/10.0f);

      g.setColor(Color.white);
      g.draw(rect);
      g.draw(circle);


//       Since Scala doesn't have a ternary operator (that I know
//       of) we'll replace it with a custom function here. Without
//       digging into support for lazy evaluation and such I can't
//       implement an exact analog of a ternary operator.

      val pickColor = (s1 : Shape, s2 : Shape) => {
    if(s1.intersects(s2))
      g.setColor(Color.red);
    else
      g.setColor(Color.green);
      }

//       Just to clean things up a bit, we'll encapsulate the
//       pickColor->draw motion in a named function.

      def drawIntersection(s1 : Shape, s2 : Shape) {
    pickColor(s1, s2);
    g.draw(s1);
      }

      drawIntersection(rect1, rect);
      drawIntersection(rect2, rect);
      drawIntersection(roundRect, rect);
      drawIntersection(circle1, rect);
      drawIntersection(circle2, rect);
      drawIntersection(circle3, circle);
      drawIntersection(circle4, circle);

      g.draw(roundRect2);
      g.setColor(Color.blue);
      g.draw(new Circle(100,100,50));
      g.drawRect(50,50,100,100);

    }

    /**
     * @see org.newdawn.slick.BasicGame#update(org.newdawn.slick.GameContainer, int)
     */
    override def update(container : GameContainer, delta : int) { }

    /**
     * @see org.newdawn.slick.BasicGame#keyPressed(int, char)
     */
    override def keyPressed(key : int, c : char) {
      if (key == Input.KEY_ESCAPE) {
    System.exit(0);
      }
    }
  }
  /**
   * Entry point to our test
   * 
   * @param argv The arguments passed to the test
   */
  def main(argv : Array[String]) {
    try {
      val container = new AppGameContainer(new GeomTest("Geometry Test"));
      container.setDisplayMode(800,600,false);
      container.start();
    } catch {
      case e : SlickException => e.printStackTrace();
    }
  }
}
1 comment

Game dev in Scala I

I’m starting work on a 2d Java game. I’ve been kicking around an idea for a while, and some of the capabilities of the Java platform here make it a really good choice for this task. Webstart, for instance, would allow me to distribute the game to friends by simply having them click a link and let the program run. The JVM and some of the available 2d game engines make writing cross platform code a snap. And I don’t have to futz around with manual memory management, which is always a bonus.

The big problem in this equation is Java. The language isn’t outright bad, but it isn’t terribly good either. Some things that I think would make this game easier to develop simply aren’t available. So, I spent a while poking around on alternative langauges that compile to the JVM. Jython was out immediately for several reasons: speed (not that I worry much about this, but even slower than CPython? ouch), Java interoperability (at least the FAQ makes this look confusing), and lack of static type checking (evidently the borg have gotten to me). I didn’t consider JRuby, mainly by assuming that the same points about Jython would apply. Mozilla Rhino looks interesting, but the whole time I was looking at it I kept thinking I really would like to have static typing.

So, I went with Scala. I’m still getting up to speed on it and the game libraries involved, but so far it looks interesting if nothing else. The language is decently flexible, and seems to play nice with Java as much as possible. Most of my code will be pretty simple Scala->Java calls, so it should be fine. It looks like even building Java->Scala->Java code bases is a mess, but that seems kind of obvious to me.

As a teaser, here’s a simple translation of a “Hello World” program for the slick game library with the original Java code:

import org.newdawn.slick._

// Since we're planning on running this directly out of a .jar we need
// a (singleton) object so the main function is static, hence the
// object with an inner class implementation. An outer class would
// have worked as well, but there you are.
object TestProgram {
  // Take note: Due to scoping rules (i'm assuming) this TestProgram
  // is the one referred to in main below.
  class TestProgram(s : String) extends BasicGame(s : String) {

    override def init(container : GameContainer) {}

    override def update(container : GameContainer, delta : int) {}

    override def render(container : GameContainer, g : Graphics) {
      g.drawString("Hello, Slick (from scala) world!", 0, 100);
    }
  }

  def main(args : Array[String]) {
    try {
      val app = new AppGameContainer(new TestProgram("TestProgram"));
      app.start();
    } catch {
      case e : SlickException => e.printStackTrace();
      case ex : Exception => ex.printStackTrace();
    }
  }
}

And the Java version:

import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.AppGameContainer;
public class SimpleTest extends BasicGame {

    public SimpleTest() {
    super("SimpleTest");
    }

    @Override public void init(GameContainer container) throws SlickException {}

    @Override public void update(GameContainer container, int delta) throws SlickException {}

    @Override public void render(GameContainer container, Graphics g) throws SlickException {
    g.drawString("Hello, Slick world!", 0, 100);
    }

    public static void main(String[] args) {
    try {
        AppGameContainer app = new AppGameContainer(new SimpleTest());
        app.start();
    }
    catch (SlickException e) {
        e.printStackTrace();
    }
    }
}

The scala version is a line longer due to comments, but cheats a little with the unqualified import. Right now the happyplace for me is that I don’t have to write “T foo = new T()” and can let Scala infer from usage that if I’m making a new object of type T, I’m probably holding a reference to it that is of type T as well.

No comments

My Thoughts exactly…

Stolen from http://arcanux.org/lambdacats.html

The rest of the time I'm stuck in a carpet box monad

No comments

Category test

If this shows up in the emacs and programming categories, that would be awesome.

No comments

I’m stupid, Part I

When on a Mac, there are two locations to install a Framework: system-wide (/Library/Frameworks) and user-local (~/Library/Frameworks). The user-local location is (obviously) checked first.

If you’re trying to install GHC and it keeps giving you error messages like:

checking for path to top of build tree... dyld: Library not loaded: GMP.framework/Versions/A/GMP
Referenced from: /Users/ajones/programming/haskell/ghc-6.8.2/utils/pwd/pwd
Reason: Incompatible library version: pwd requires version 8.0.0 or later, but GMP provides version 7.0.0 

It might be worthwhile to make sure you don’t have an old version of GMP.Framework installed in your user local frameworks library.

No comments

Testing markdown mode

This is a test of markdown support in blogging, through emacs.

For some reason I doubt this will work, but if it does I will be super happy about it.

update

Ok, I’m super happy. Even more so since updating works.

No comments

Emacs Test

Here’s a test of blogging from emacs, hurray.

No comments

« Previous Page