Vertex and pixel shaders are now fully supported. The engine defines a default vertex shader that it uses to render with extremely fast! on initialization (this also means the engine requires a video card that supports vertex shader version 1.1 at least).
With pixel shaders, though, the sky's the limit for cool effects. Want your entire game to be rendered embossed or add blur effects, read from multiple textures or add any other number of special effects? It's all possible now.
Shaders go through the exact same resource management as all other resources, and are extremely easy to load, set, and use. For example, below is an example of how to load and start using a pixel shader:
ps := PixelShaderResource get: 'my_ps.pso'.As you can see from the above example, the actual rendering has been pulled out of the engine finally into its own class: GameRender. This was done for two reasons: simplify the engine class and if in the future I wanted to do 3D, this is where it would be done - subclassing GameRender into an immediate 2D render class and a batch 3D render class.
GameEngine current render pixelShader: ps.
The GameActor class is now exactly how I want it - as just a node in the scene. It controls translation, rotation, and scaling. Actors can be parented to other actors, allowing for complex transformations (eg, a particle emitter attached to a sprite). The GameActor class now is subclassed into SpriteActor, which controls rendering of a sprite somewhere on the screen.
A pretty simple and well-featured particle system. Creating new particle effects in game and playing them is very simple and fast. There are 3 main classes which make up the particle effect system: GameParticleSystem (defines how particles will be emitted), ParticleEmitterActor (subclassed from GameActor), and ParticleActor (subclassed from SpriteActor). This has been the most flexible method of doing particles so far, as one GameParticleSystem can be used within many emitter objects very easily.
Spritemaps are now supported as a new resource type. They are extremely similar to fonts. An XML spritemap file is read off disk, which gives information about a texture and all the sprites inside of it. The spritemap object will create sprites that can then be referenced by SpriteActors by the name given to them in the XML file.
map := SpritemapResource get: 'sprites.xml'.Right now spritemaps are very convenient for organizing data, but later when I add scrolling, tiled backgrounds they will be worth 10x as much as they are right now.
ship := SpriteActor fromSprite: (map sprites at: 'ship').
The last, simple, yet nice addition is the ability to set different blending modes. The engine supports additive, multiplying, solid, and alpha blending modes.
That about covers most of the recent changes and additions. Next I hope to clean up some more code and centralize more of the rendering code to be more flexible and easy to use, add render targets to the mix (this will open another level is visual effects), and I need to start planning how I'm going to do user interface widgets.