Modern languages like Java or C# allow programmers to create new objects dynamically using class name ( ie. Class.forName() in Java ). This feature is not easy available in C++. The question is why to use any class factory at all? Basically, if you're a game programmer you should already know about such things like serialization and deserialization processes. Also, if you own a class factory then it's way easier to control all the allocations and memory usage.
I'm gonna show here is more like idea rather than fully working solution. Although it works on my side, here I had to cut down the code to make it clearer and to not reveal any commercial parts of course.
My major goal was to create a mechanism that didn't require any changes in any class ( for example I didn't want to have to implement any factory base class and stuff ). To use it you just have to call one macro anywhere inside any function ( and of course include proper header but this is kinda obvious ;) ).
Let's see some code. First I have implemented class CClassFactoryWorker. It's template based solution which gets new implementation for each class T. Also it stores a class name so it's gonna be easier to check if it really created an object of correct class.
template <typename T> class CClassFactoryWorker { public: static T * GetClass() {
std::cout << "returning class " << s_ClassName << std::endl;
Second part is an actual factory class. First take a look at the code below:
class CClassFactory { public:
typedef void * ( *ptr ) ( void );
template void RegisterClass( T * n, const char * name ) { ptr p = (ptr)(CClassFactoryWorker::GetClass); strcpy( CClassFactoryWorker::s_ClassName, name ); s_cfl.push_back( pair( HashString( name ), p ) ); }
void * GetClass( int idx ) { ptr p = (ptr)(pair(s_cfl[idx]).second); return p(); }
As you can see, there's type definition of a function pointer. It's just generic type that I could use for casting GetClass() functions. It always fits since any object pointer can be converted to (void*). RegisterClass() adds that function pointer and also hash value of string that represents the class name to the end of static vector. GetClass() is very simplified and it doesn't do any lookup yet, I just wrote this version this way to get clearer picture of whole thing. GetClass() takes one argument which is an index of element in s_cfl vector. Very last thing is to declare macro which does all the registration:
And this is all. Now you should be able to use it as below:
int main() { A * base = new A();
REGISTER_CLASS( A ); // registering class A REGISTER_CLASS( B ); // registering class B
CClassFactory::s_Singleton.GetClass(0); // create object of class A ( index 0 in s_cfl ) CClassFactory::s_Singleton.GetClass(1); // create object of class B ( index 1 in s_cfl )
return 0; }
Just in case, code I pasted in this blog is created for showing purposes and I don't guarantee it's gonna even compile ( ie. you may not have HashString() function ). I hope it's gonna help you to write your own class factory.
While I was checking out XNA stuff I saw many tutorials and examples of animated particles. WIth XNA it’s rather simple task. I tried to go a little harder way and implement similar solution on J2ME compatible device.
Particles are objects which have their own lifetime and specific motion behavior. After the time is up they just simply disappear. Particle system must handle multiple objects considering that they may own different motion behavior and also different lifetime.
Because mobile devices are rather slow I decided to use a bit more memory and created sprite images for each shading/blending level. All sprites are generated by the midlet. There are no PNG files but for making more fancy particles I’d rather go with PNG images. In this case there was no such need. There’s lot to be optimize yet but I’ve made my particle system in half an hour just for checking if the idea works ;).
for (int i = 1; i < SHADING_LEVELS; i++) { alphaValue += alphaStep;
for (int p = 0; p < particlePixels[0].length; p++) { int originalAlpha = (particlePixels[0][p] >> 24) & 0xFF; int newAlpha = originalAlpha - (alphaValue >> Maths.FP); if (newAlpha < 0) { newAlpha = 0; } particlePixels[i][p] = ((newAlpha & 0xFF) << 24) | (particlePixels[0][p] & 0xFFFFFF); } }
}
Each particle owns the following properties:
- life time in millis - x and y coords - motion listener
The motion listener uses ParticleSprite.ParticleMotionListener inner interface:
public interface ParticleMotionListener { public void updateParticlePosition(ParticleSprite s, int x, int y, int timeInMillis, int tickNumber); }
The method updateParticlePosition() takes current sprite, its coordinates, time that tells how “old” particle is in millis and number of tick/update as arguments. Variable timeInMillis and tickNumber are initialized with first particle update. tickNumber is initially set to 0 and timeInMillis takes current time as default.
All particles are part of particles pool. For current case I used Vector type to keep all elements together but it might be better to allocate an array of N elements and instead of adding/removing it from Vector better way could be to enable/disable specific particle. Maybe next time I will update it. I also implemented release pool that holds all elements which are marked to be terminated. In other words the update goes through following steps:
For each particle: - update current particle - if particle life time is over, mark particle to be removed and add it to release pool For each particle marked to be removed: - get particle object - remove its reference from particle pool - after all is done clear release pool
This is how updateSystem() method is implemented:
public static void updateSystem() { final int size = particleCount = vecParticleSystemPool.size();
if ( size == 0 ) { return; }
final long currentTime = System.currentTimeMillis();
final int removeSize = vecParticleRemoveSystemPool.size();
for ( int i = 0; i < removeSize; i++ ) { ParticleSprite sprite = (ParticleSprite)vecParticleRemoveSystemPool.elementAt(i); vecParticleSystemPool.removeElement( sprite ); }
Painting is even simpler, I don’t think it requires any additional comment:
public static void paintSystem(Graphics g) { final int size = vecParticleSystemPool.size(); for (int i = 0; i < size; i++) { ParticleSprite sprite = (ParticleSprite) vecParticleSystemPool.elementAt(i); int level = (int) (sprite.m_lastUpdateTime * SHADING_LEVELS) / sprite.m_lifetime;
This is actually everything. As you can see it’s not very complex.
The application handles two modes. First is auto smoke. It just generates smoke-like effect. Second mode is called DRAGGING and lets user make particles by dragging stylus/finger over the screen. Of course it’s only working if device has touch screen. Otherwise there’s no use for DRAGGING mode.
You might be worried about overall performance and if it’s worth using in any game. Certainly it requires good device. It won’t work with low-end phones so particles should be optional for better phones. I did some tests and phones like SE K700i, K750, K610, W890, W910i handled it really well and they can draw particles in game. Moreover, they can call initSystem() method and reinitializing is immediate. It means they may change color or size of particle on fly.
It’s hard to not notice that use of memory is pretty big. Lets say we have 16 shading levels and particles 32×32. This will take 64kb of ram for single particle. If we want to have more particle patterns ( for example different colors ) then we’ll have to use even more memory. Of course we can reduce number of shading levels but there’s one more optimization that comes to my head. Basically, each particle is a circle. It means we can generate only one quarter ( left top quarter ) and draw other quarters using manipulations. This will reduce amount of used memory by 4 times! 32×32 particles will take 16kb of ram. Sure it’s gonna work well only with devices with really fast drawRGB() but this is a battle and all tricks are allowed
To show better use of the system when I find a little of time I’ll try to make the effect a part of game-like application. For now take a look at simple demo:
“Circuit” is very simple game. The idea is based on the minigame from “Ratchet & Clank: ToD” for PS3. The player controls a ball to close a circuit whenever impulse is about to jump from one end of track onto another. The goal is to unlock electronic lock. Each impulse may split or collide with another one ( which makes them both disappear ). In oroginal PS3 minigame a player was supposed to use Six-Axis controller. Mobile game uses the accelerometer to control the ball.
As a base device I used SonyEricsson W910i which supports JSR256 quite well. Very first thing I had to do was enabling and implementing entire sensor related functionality.
I moved entire sensor implementation to the separated class which is called Accelerometer. This is how it looks:
/* dataReceived() is not optimized yet and contains some weird calcs */ public void dataReceived(SensorConnection connection, Data[] data, boolean b) {
int[] x = data[0].getIntValues(); int[] y = data[1].getIntValues();
The class implements simple features: - reading sensor asynchronously - reading sensor synchronously - sensor threshold - sensor sensitivy
Game uses only asynchronous reading because it’s simply faster. Method dataReceived() processes all data provided by sensor. It’s not optimized at all but still it works fast. So I’ve left it as it is for now.
Since it’s possible to read the sensor, the game can use it and change into ball motion. This implies simple physics. Nothing special, just combining gravity and friction forces:
if (doVibraX || doVibraY) { DeviceControl.startVibra( 80, 20 ); }
}
At the end of method you may notice a line containing startVibra(). The phone vibrates whenever ball hits any edge of screen. It makes nice illusion that ball weights and moreover it really feels like it hits specified edge. Method updatePositionBySensor() keeps maximum speed limited so the ball will never move too fast.
My name is Adam Bialogonski. My history as a programmer started in early 1990s. I had always been a self-learner with interest for new technologies, eager to gain knowledge and experience. I have been working with many different languages and platforms, however after a success of my J2ME title in 2002, mobile games became my main field in professional work.