SilenceEngine - A 2D/3D Game Engine

I don’t think that it has much overhead, that’s what most desktop games released with OneJAR or JarSplice do, they extract the natives on runtime and delete the natives afterwards. And moreover, that would simplify project setup, You just add the natives jar to the class-path just like you would do with other library jar, helping the user. I don’t think enable/disable flag is not useful.

Best of luck with the library/engine (you describe it as a hybrid of both imo).

The Vector classes, I think the components would be better public and remove the get/set methods. Every Vector class I have seen does this, it is definitely neater in code for me.

I can’t say much else on the batcher and that, as my knowledge with these are well, not great at all :p.

Reason behind the name?

I wanted the engine to hide all the OpenGL calls from the user, and carry them silently under the hood. Hence the name SilenceEngine, the engine that silences OpenGL calls for you.

Standard advice for every yet-another-home-brewn-game-engine: make a game (game means game not tech demo) in parallel if it shall get any good.
Anyway, have fun :wink:

I don’t claim that this feature is useless but I think that this implementation with no cache can be harmful in some particular cases. Moreover, the JARs containing the native libraries have nothing to do in the classpath but putting them into the same directory than the Java libraries that call them makes sense. JarSplice isn’t a good example because it’s quite buggy, its source code has never been released and as it seems to be unmaintained, you’re lost in the darkness or you have to decompile it to have a chance to fix it. Of course this feature simplifies the setup because you don’t have to use any platform-dependent variable or the Java library path to indicate where the native libraries are but it’s not suitable in some environments. Some virus scanners become crazy when they see a program extracting native libraries. I think that adding a flag into your engine is a good compromise, it’s simple to implement and it allows anybody to handle this aspect by himself if your loader gets in his way.

I agree with 65K, make a game with your engine, at least a small showcase.

Can you elaborate reasons behind making yet another “engine”. What are motivates. Why this is better than others or is it(in the future)? What is the future goals? Is this just for learning? Do you have game what drives the development?

Can you please explain those particular cases? I’m sure I didn’t get what you mean.

The main reason in making this “yet another engine” is that I can use it for my next personal projects, I just thought it would be cool to show you guys. Currently I cannot say why this is better, because it lacks a lot of features a engine would have, but I have plans to implement them soon. My current priority is fixing Mouse input. Future plans include writing classes for Meshes, and also some basic entity classes with collisions. I want to wrap all this into a Scene Graph.

As per the game, I’m having two games, one a 2D platformer and the other is a 3D FPS. They are too basic atm, and require more work on the engine. I’ll show them to you once they get to a playable state.

Think I should share some code on using Batcher. You create the batcher just like any normal java object.


batcher = new Batcher();

And then, use it to add vertices (triangle and other shape functions coming soon).


batcher.begin();
{
    batcher.addVertex(new Vector2(+0.0f, +0.5f), Color.CORN_FLOWER_BLUE);
    batcher.addVertex(new Vector2(-0.5f, -0.5f), Color.INDIAN_RED);
    batcher.addVertex(new Vector2(+0.5f, -0.5f), Color.OLIVE_DRAB);
}
batcher.end();

Produces the following on the screen.

Textures are the same, you load a texture in the init method like this.


texture = Texture.fromResource("com/shc/silenceengine/res/logo.png");

And you specify the texture coordinates along with the vertex position instead of the color.


texture.bind();

batcher.begin();
{
    batcher.addVertex(new Vector2(-0.5f, +0.5f), new Vector2(0, 0));
    batcher.addVertex(new Vector2(+0.5f, +0.5f), new Vector2(1, 0));
    batcher.addVertex(new Vector2(+0.5f, -0.5f), new Vector2(1, 1));

    batcher.addVertex(new Vector2(-0.5f, +0.5f), new Vector2(0, 0));
    batcher.addVertex(new Vector2(-0.5f, -0.5f), new Vector2(0, 1));
    batcher.addVertex(new Vector2(+0.5f, -0.5f), new Vector2(1, 1));
}
batcher.end();

It produces the logo in the screen like this.

It is also possible to add a tint to the texture. To do that, specify the tint color along with the vertex and texture coordinate.


batcher.addVertex(new Vector2(-0.5f, +0.5f), Color.GOLDEN_ROD, new Vector2(0, 0));
batcher.addVertex(new Vector2(+0.5f, +0.5f), Color.GOLDEN_ROD, new Vector2(1, 0));
batcher.addVertex(new Vector2(+0.5f, -0.5f), Color.GOLDEN_ROD, new Vector2(1, 1));

batcher.addVertex(new Vector2(-0.5f, +0.5f), Color.GOLDEN_ROD, new Vector2(0, 0));
batcher.addVertex(new Vector2(-0.5f, -0.5f), Color.GOLDEN_ROD, new Vector2(0, 1));
batcher.addVertex(new Vector2(+0.5f, -0.5f), Color.GOLDEN_ROD, new Vector2(1, 1));

And the output will be like this.

This is the Batcher class, stay tuned for more updates!

  • you don’t have enough rights to create a directory or a file to extract the native libraries
  • another library, framework or installer already takes care of extracting and loading the native libraries
  • the virus scanner doesn’t like your program and blocks or takes a long time to scan the native libraries each time you extract them
  • the startup time is considered to be too long

Okay, added an option to disable NativesLoader. To do that, run the program with [icode]-DNativesLoader=false[/icode] but note that doing so, you need to manage natives yourself. The default value for that property is true.

Now added Transformations!! All you have to do is to create an instance of [icode]Transform[/icode] class and apply that to the batcher. Here’s a crappy gif that I’ve recorded (747 KB)

All you have to do is manipulate the Transform object and before rendering, apply to the batcher with [icode]batcher.applyTransform(transform)[/icode] and the changes apply instantly. More coming soon, I’m already working on the Camera, so stay tuned!!

Nice, how are you handling transforms?

Are you just using standard Vector code or matrix transforms? I am new to Matrices, waiting patiently for the updated repo :D.

Batcher is the place where all the rendering takes place in SilenceEngine. It has a Transform object whose matrix is passed to the shaders internally. Everytime you apply a transform, the internal transformation matrix will get multiplied, allowing the changes for that frame. That’s how it works.

And on the end of every frame, the internal transform will be reset, to an identity matrix. Also whenever you apply a transform, the previous contents gets flushed before transformation, meaning that the transform will apply to the vertices that were batched after the application. If you want to change the transform, you have to end the batch, and re-start batching with the new transform.

The transform and batcher classes are located in the [icode]com.shc.silenceengine.graphics[/icode] package, take a look at them to get an understanding.

Update: Added Cameras! I’ve written two Camera classes [icode]OrthoCam[/icode] and [icode]PerspCam[/icode] for orthographic and perspective cameras. Both the cameras are very basic in behaviour, though. The [icode]OrthoCam[/icode] should be used to render 2D stuff, and can be used to render HUDs in the games.

The [icode]PerspCam[/icode] provides you a method called [icode]setPositionAndLookAt(Vector3, Vector3)[/icode] which can be used to position the Camera anywhere on the scene, and make it look at a point. This is particularly useful in FPS style games, you position the camera behind the player, and make it look at the player, making it simple and easy.

Here’s how to use the Cameras, you have to pass the camera to the batcher in the begin method. You can also pass in a transform along with the camera, and also, it is possible to set the camera by using the [icode]applyCamera(ICamera)[/icode] method of the batcher. Here’s the screenshot of the CameraTest.

The triangle in the top-left corner is rendered using [icode]OrthoCam[/icode] while the one in the center is rendered using [icode]PerspCam[/icode] and a rotating Transform. I think I should document the classes now…

TrueTypeFonts!! Thanks to NegativeZero for sharing some of his code to load from AWT Font. To render the font, you have to use ortho camera. This is because in PerspCam, the coordinates will be -1 to 1, instead of 0 to width and 0 to height.

As usual, here’s some code!


// Draw some text: Warning, requires OrthoCam
batcher.begin(cam);
{
    font.drawString(batcher, "Hello World!!", 10, 10);
    font.drawString(batcher, "Colored Text!!", 10, 10 + font.getHeight(), Color.RED);
    font.drawString(batcher, "Multi line\nText!!", 10, 10 + 2 * font.getHeight(), Color.GOLD);
}
batcher.end();

Stay tuned for more!! Coming up are entity and world system for 2D.

trollwarrior might have something else to suggest. There are a few AWT-free solutions to loads TrueType fonts. If you use AWT, forget once for all Android support.

Thanks for the info, I’ll contact him now. BTW, I really had no plans for Android, I’m only thinking of GWT for now.

I was justing needing a bit of help with my game engine so I had a quick look around at yours on github if that is alright… It is really amazing, you did a good job…

Just one question tho… In Display.setFullscreen it seems like you are recreating the window and the OpenGL context… Does this mean that the OpenGL context will restart? So will all textures, VBOs, etc. need to be redone? Or are you hiding some sort of trick and somehow keeping the same context? :persecutioncomplex:

It is just that I am trying to change to fullscreen in game while keeping the same context.

Thx in advance…

@matanui159

Sorry, accidental medal, was browsing through mobile. To answer your question, I’m only creating one context: Every window I create shares that context, because it is the only way to implement fullscreen switching in GLFW.

But every time you create a window, you call GLContext.createFromCurrent()
Doesn’t this make a new OpenGL context?