I am a Scala newbie and attempting to improve my skills. I have decided to be playful about it and work to do a conversion of the spaceinvaders game supplied with the LWJGL. It consists of 10 Java classes of which I have loaded, compiled and successfully ran from Eclipse.
My first Scala step is to replace the Sprite.java class with a SpriteNew.scala class. I have completed the first pass (see below). However, I have several questions:
- How do I make class SpriteNew only have instances created by Object SpriteNew.create? In Java, I would just make the constructor private. Since I cannot do that, I am wondering if I am missing how I must approach a problem like this different than how I do so with Java.
- In Object SpriteNew, I don't like how I used a var to temporarily define a field so that I can reference/return it in the final line of the load method. Are there any better ways to write this method keeping the intention of isolating the Java/null-ness/Exception-ness?
Any feedback, coaching, guidance, suggestions you can give me on this would be greatly appreciated.
For brevity, I have stripped the comments out of the original Sprite.java class (go here if you would like to see the original unmodified source for Sprite.java):
package org.lwjgl.examples.spaceinvaders;
import java.io.IOException;
import static org.lwjgl.opengl.GL11.*;
public class Sprite {
private Texture texture;
private int width;
private int height;
public Sprite(TextureLoader loader, String ref) {
try {
texture = loader.getTexture(ref);
width = texture.getImageWidth();
height = texture.getImageHeight();
} catch (IOException ioe) {
ioe.printStackTrace();
System.exit(-1);
}
}
public int getWidth() {
return texture.getImageWidth();
}
public int getHeight() {
return texture.getImageHeight();
}
public void draw(int x, int y) {
glPushMatrix();
texture.bind();
glTranslatef(x, y, 0);
glBegin(GL_QUADS);
{
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(0, texture.getHeight());
glVertex2f(0, height);
glTexCoord2f(texture.getWidth(), texture.getHeight());
glVertex2f(width, height);
glTexCoord2f(texture.getWidth(), 0);
glVertex2f(width, 0);
}
glEnd();
glPopMatrix();
}
}
And here is my first pass at the Scala version as a Factory (using both object and class):
package org.lwjgl.examples.spaceinvaders
import java.io.IOException
import org.lwjgl.opengl.GL11._
object SpriteNew {
def create (textureLoader: TextureLoader, resourceName: String): SpriteNew = {
def load: Texture = {
var texture: Texture = null
try {
texture = textureLoader.getTexture(resourceName)
}
catch
{
case ioe: IOException => {
println(ioe.getStackTraceString)
System.exit(-1)
}
}
texture
}
val texture = load
new SpriteNew(texture)
}
}
class SpriteNew (val texture: Texture) {
val width = texture.getImageWidth()
val height = texture.getImageHeight()
def draw(x: Int, y: Int) {
glPushMatrix
texture.bind()
glTranslatef(x, y, 0)
glBegin(GL_QUADS)
glTexCoord2f(0, 0)
glVertex2f(0, 0)
glTexCoord2f(0, texture.getHeight())
glVertex2f(0, height)
glTexCoord2f(texture.getWidth(), texture.getHeight())
glVertex2f(width, height);
glTexCoord2f(texture.getWidth(), 0)
glVertex2f(width, 0)
glEnd
glPopMatrix
}
}
Update (2011/Nov/22 - 15:00 CDT):
I am incorrect in question 1 about not being able to make the constructor private. Placing the keyword "private" after the Scala class name and before the constructor parameter list allows the class to remain public while the constructor become private. In other words, snippet above "class SpriteNew (val texture: Texture) {" would be altered to become "class SpriteNew private (val texture: Texture) {"