- Create a Position component.
- Create an ImageRenderable component with corresponding ImageRenderSystem.
import org.newdawn.slick.Image; public class ImageRenderable implements Component { private Image image; public Image image() { return image; } public ImageRenderable image(Image image) { this.image = image; return this; } }
Easy enough, as long as you don't mind my Smalltalk-esque style — using the same method name for both an accessor and mutator, and returning this
from the mutator.
This conceptually-simple unit test just checks that if we set an image, that the property accessor returns that image:
@Test public void testImageAccessorAndMutator() { final String RESOURCE_LOC = "images/white-1x1.png"; try { new AppGameContainer(new BasicGame("Test") { @Override public void render(GameContainer container, Graphics g) throws SlickException { final Image image = new Image(RESOURCE_LOC); ImageRenderable ir = new ImageRenderable().image(image); assertEquals(image, ir.image()); container.exit(); } @Override public void update(GameContainer container, int delta) throws SlickException { } @Override public void init(GameContainer container) throws SlickException { } }).start(); } catch (SlickException e) { fail("Failed to create game: " + e); } }
Here's a breakdown:
- The game needs a container in order to run, so we create an AppGameContainer.
This is the class used when launching games as applications, in contrast with
AppletGameContainer.
- The inner class overrides the three methods required, but only render is interesting to this test, so it's the only one that matters.
- The
image
variable references the actual Slick image object, which is then referenced byir
. We don't actually need anyEntity
objects here: we're just testing the component.
assertEquals
ensures that the image we put into the component is the one we get out.
- After the test, we call the container's
exit
method to gracefully shut down Slick.
- The start() call on the game container actually starts the test game.
Unit tests for accessors and mutators are nigh unnecessary, but this set-up allows us to do something more interesting with the system that processes these components. Here's a simple implementation of ImageRenderSystem
, which assumes that its Entity
arguments have both Position
and ImageRenderable
components.
import java.util.List; import org.newdawn.slick.Graphics; public class ImageRenderSystem { public void render(Graphics g, Listentities) { for (Entity e : entities) render(g, e); } public void render(Graphics g, Entity e) { Position p = e.as(Position.class); ImageRenderable i = e.as(ImageRenderable.class); g.drawImage(i.image(), p.x(), p.y()); } }
Simple. Here's the corresponding unit test (which was written first, natch).
@Test public void testImageRendering() throws Exception { new AppGameContainer(new BasicGame("Test") { private Entity e; @Override public void render(GameContainer container, Graphics g) throws SlickException { ImageRenderSystem sys = new ImageRenderSystem(); sys.render(g, e); assertEquals(Color.white, g.getPixel(0, 0)); container.exit(); } @Override public void update(GameContainer container, int delta) throws SlickException { } @Override public void init(GameContainer container) throws SlickException { BasicEntityManager mgr = new BasicEntityManager(); e = mgr.createEntity(); e.add(new Position().x(0).y(0)); e.add(new ImageRenderable().image(new Image( "assets/white-1x1.png"))); } }).start(); }
This has the same structure as the previous one. I am using the init
method to set up the test. Technically, this could be done in render
as in the previous example, but it seems that init
is a good place to do initialization. The render method calls out to the ImageRenderSystem
render
method, and then we check that the pixel in the upper-left corner is indeed a white one. To finish the test, we should check that the rest are black, but that's left as an exercise for the reader.
This shows how to set up rendering-related unit tests in Slick. The real moral of the story, though, is: make sure you know what you're doing before you show up in class. This was supposed to take about fifteen minutes, and it took me over an hour to puzzle through all the parts. It's always easier the second time.
Thanks to David Craft for the post explaining how to set up SyntaxHighlighter in blogger.
No comments:
Post a Comment