Monday, March 26, 2012

Proof Of Concept


Here you can see my vision of EventRecorder I've implemented. I've summoned all my mad msPaint skills and hopeing that it looking as well clear as funny. Let me describe how it works:

recording:
EventsRecorder subscribed as observer to EventManager. Every income message it push into _eventsQueue. Every iteration of main loop(sync), engine calls EventsRecorder's sync method and all events from queue falling down into the file.

playback:
Every iteration of main loop (sync), EventsRecorder clear _eventsQueue and push events from file to events queue. Then push it back into EventManager.

Video of working demo: http://www.youtube.com/watch?v=6AcXYGLH4vE

I've forked scummvm on github and trying to understand how can i work with code (all this repositories, branches and collaborate work is very new for me).  Now there is only clone of scummvm in my repository, but anyway, here is link for it:
https://github.com/jakimushka/scummvm

Friday, March 23, 2012

At the beginning of a long journey


I want to take part in summvm development as a part of the Google Summer of Code Event. Here I’ll tell about work done, about my impressions from this project and about other things related to this.

 It was highly recommended to make bugfix or path of existing code for participation  in the project. But I have some problems with them. After trying about ten bugs from bugtracker, I can’t reproduce any of them. That’s why, I’m going to start working on the idea I want to implement during this project.

So, my aim is to write testing framework, which can record or reproduce user’s actions. There is already implemented module in the project, but it has some problems with synchronization with states of engine. After analyzing the existing sources, I’ve found that previous version of the recorder was based on the idea that input events are in the form of interrupts and they linked to the time. In fact, events are state of input controls during the current iteration of engine. So for the recorders correct work, it’s necessary to store/restore the state of input controls in each iteration.
It looks much easier than previous version cause there is no necessity to make any time calculations. But difficulty lay in the fact that calling of recorder must be implemented in every supported engine and different implementation of main loop in engines also can be a problem. So calls recorder’s interface must be as easy and compact as possible. Ideally, recorder must be encapsulated into Event Manger.

My first step is implementation of Event Recorder class and integration into one of the existing engines (I think it going to be Sky engine, cause it is very easy to find game for testing) and testing until it will work perfectly.
Then I’ll try to integrate it into another engine and analyze what difference it has and what should I change in engines to make integration easy. 

Next I’ll integrate it into all engines and will write guidelines for using it in new engines. 
The main loop of engine was easily found in go() method of SkyEngine class. This method implements all game logic and it calls delay() function which sync engine with FPS and also processes events. 

Actually, I do not really like main loop implementation, and if it would be permitted, I refactor it. 
Firstly, I think that methods 
delay() and doIntro  isn’t routines. They are states of engine! And engine is a classic state machine, which can be in following states: 
STATE_INTRO - playing of intro, which can be interrupted by escape key pressing and going into action state 
STATE_ACTION - working iteration of engine. Makes updates in logic graphicks, analyze input 
STATE_IDLE - state for syncing with FPS 
STATE_PAUSE - ingame pause
Now it works how statemachine but logic “smoothed“ with the code. Function delay() , following its name must pause application work. But it also makes an events processing (btw, events processing loop wants to be extracted from delay method). 

To test my idea, I’m adding public methods saveEngineInputState and restoreEngineInputState into EventRecorder class. They are only writing given state of keyboard and mouse to file depends from recorder state. (if recorder in writing state - restoreEngineInputState doesn’t work. if recorder in playback state, saveEngineInputState doesnt work) . I’m going to store input state after processMessages routine and push stored messages into EventManager before processMessages routine (faking real events). 

Pseudocode: 
g_eventRec.restoreEngineInputState(); 
processMessages(); 
g_eventRec.saveEngineInputState(_keyBoardState, mouseState, mouseClicked); 

After testing, I’ve noticed that this principle works really great in things related to synchronization. But it also has some problems, which must be solved:
only mouse and keyboard events are processing now. And only aim engine routine. For instance, EVENT_QUIT willn’t handle. Keys pressing will not handling properly too. (but that moment I thought it was due to weak engine architecture)
  • aren’t processing mouse movement events
  • there may be some problems with using it in different engines
  • aren’t processing random (easy to fix)
In general, I think, I get awesome progress for few hours of work. I’m looking forward for any suggestions and criticism comments.