When I was a developer on the jME (http://www.jmonkeyengine.com) project it is what led me to write "StandardGame" as far too commonly developers would end up with basically the same "Game" implementation for all their games, but it either consisted of a lot of copy and paste from other projects or a lot of re-writing the same code each time a new project was created.
If you look at previous posts the code has always been moderately simple and no more than a dozen or so lines of code to accomplish a basic task. However, I still had visions for improving further.
Perhaps I've gone a bit overboard in my agenda to simplify, but I've created a new trait in Sgine called "StandardDisplay" that is the spiritual successor to the ideas I put forth in jME years before. With Scala and Sgine a lot of possibilities for simplification have been opened up that were never possible before, such as putting the main method in a trait so it need not be explicitly defined. Further, one of the big problems with JRE applications today is deployment. Whether you want an Applet, a WebStart application, a desktop application, or all three it is a great deal of pain to get the end result you want. One of the goals of StandardDisplay is to be able to simply extend and execute in any display model you desire. Couple this with the idea of a deployment generation system I have yet to write and deployment of applications can be a simple afterthought instead of a major headache holding you back from getting your projects out.
Okay, I've droned on long enough without some actual code to show. If you've read this blog from the beginning you'll remember the very first post I made with an actual example with the following code to display an image of my dogs:
package org.sgine.render import org.sgine.math.Matrix4 import javax.imageio._ import org.lwjgl.opengl.GL11._ object TestRenderer { def main(args: Array[String]): Unit = { val r = Renderer.createFrame(1024, 768, "Test Renderer") val t = new Texture(700, 366) TextureUtil(t, ImageIO.read(getClass.getClassLoader.getResource("resource/puppies.jpg")), 0, 0, 700, 366) val m = Matrix4().translate(z = -1000.0) val i = Image(t) val fps = FPS(1.0) r.renderable := RenderList(MatrixState(m) :: i :: fps :: Nil) println("Renderer started!") } }
That concept has firmed up a lot since then with the scenegraph system and the UI package to more recently look like:
package org.sgine.ui import org.sgine.core.Resource import org.sgine.render.Renderer import org.sgine.render.scene.RenderableScene import org.sgine.scene.GeneralNodeContainer import org.sgine.scene.ext.ResolutionNode object TestImage { def main(args: Array[String]): Unit = { val r = Renderer.createFrame(1024, 768, "Test RenderScene") val scene = new GeneralNodeContainer() with ResolutionNode scene.setResolution(1024, 768) val component = new Image() component.source := Resource("puppies.jpg") scene += component r.renderable := RenderableScene(scene) } }
Though much more concise and simplified I still was not satisfied. After all, I just wanted to display a picture of my puppies on the screen. Enter StandardDisplay:
package org.sgine.ui import org.sgine.core.Resource import org.sgine.render.StandardDisplay object TestImage extends StandardDisplay { def setup() = { val component = new Image(Resource("puppies.jpg")) scene += component } }
That's right, two lines of actual logic code to display an Image with puppies. Yes, this technically could have been reduced to a single line, but the goal was concise, not showing how I used to write code in Perl. ;)
This can be executed as an application since StandardDisplay trait contains a "main" method that calls "start" and the only requirement is that a "setup" method be implemented. You can go much further than this if desired to customize and configure how and what you want to display but this is all that is required to get going.
There is still a lot of work to be done to support Applets, WebStart, etc. but the core is functional and pretty impressive if I do say so myself. :)
I really like that last example! :)
ReplyDeleteHowever, often you want to define your own main method for larger projects (for reading command line arguments and various initializations) - in that case it seems you can just create a subclass of StandardDisplay and call start on it.
And support for webstart (and other deployment methods) will be great too!