Tuesday, May 18, 2010

Query mouse motion

The solution to the flood of mouse events is to filter out receiving all mouse motion events. Then we can do a manual query for mouse location. Easy fix actually, and solved the issue immediately. :)

Slow down & Mouse Motion

After making a series of changes, the performance of the level editor was extremely sluggish. Button clicks took 20 seconds to occur. The cause of this slow down was the addition of handling mouse motion events. The mouse motion events are used to determine pane focus and draw the tile shadow on the edit pane. It turns out that any small movement in the mouse sends a flurry mouse motion events which are all FIFO buffered. With SDL there is a way to set keyboard event repeat rates, but not for mouse events. Currently looking for a creative solution. This makes the editor otherwise unusable.

Function Pointers

I implemented the restructuring of the level editor away from using game states by using function pointers. It makes it much much easier to define the actions of a button and it breaks up the code in a more meaningful fashion. I am able to perform actions without the delay of wait for the game states to propagate.

The refactoring also gave a clear way to direct the keyboard/mouse input to the proper GUI panes. Before it was directed based on the game state, but now there is a pane designate with the focus. Change the focus between panes simply determined by mouse location, so there is no need to click to change focus.

Memory management is cleaner. Few state changes meant few creation and deletion of objects. This refactoring also gave me an opportunity to replace many heap allocations to stack allocations. Dialog panes are also reused; they are turned non-visible instead of destroying them.

The header files are much cleaner. When I originally wrote version 1.0, I hadn't quite mastered the art of resolving circular dependencies. During my revisit I added forward declarations and removed unnecessary include files.

Overall there is a lot more work to be done. It was an excellent learning process for the use of function pointers in C++, an amazing feature which I plan to use all the time.

Saturday, May 8, 2010

State design refactoring

Abstraction is a great thing to have in your program for many reasons. It allows the separation of different levels of functionality and it minimizes the amount of work you need to add/update sections of code. It also encourages modularity. However, I took the abstraction a bit too far for level editor version 1.0. I achieved a nice amount of modularity, but updating code was a painful process.

When writing version 1.0 I had decided to decouple the dependencies between the GUI panes as much as possible, such that, the GUI panes never talked to each other directly. In fact the GUI panes merely indicated which operation needed to be performed. The code for each operation was then packaged in sections at one location, which also handled the communication between GUI panes. This design made it real easy to rearrange the GUI components without affecting the operational code.

Essentially I implemented a finite-state machine. The main loop of the program simply did a switch/case on the current game state and performed to corresponding operations. The GUI panes indicated which operation needed to be performed by changing the editor's game state. When an operation finished, the editor's game state was changed again. It was a pretty neat design but it required that every operation have its own corresponding game state (over 35 game states). Below is a simplified state digram of the editor.

[state diagram, version 1.0] (click to enlarge)

With this model the GUI buttons served only to change the current game state. Only after the game state was changed, did the code for the operation run. It was an indirect way of calling code. Below is a UML sequence diagram showing the resulting function call communication of an example operation.

[sequence diagram, version 1.0] (click to enlarge)

Unfortunately this design produced a complex and unintuitive web of game states. Adding GUI components turned out to be a headache, since determining a button's game state required intimate understanding of the game state transitions. I actually had to draw out the game state diagram to reference when coding. Another hiccup with this design was that much of the information required to perform an operation resided on the GUI panes. It was a hassle to correctly manipulating the information and keeping the GUI panes in sync.

I needed to simplify the game states. After applying bits of the Hopcroft DFA minimization algorithm, it was able to drastically trim down the number of game states by allowing the GUI panes to directly talk with each other. It greatly reduced the communication burden on the main loop.

[sequence diagram, version 2.0] (click to enlarge)

It eliminated all of the one-shot game states (states which only existed one pass through the main loop). Now, the only operations which warrant a new game state are the operations which alter the way the input is handled.

[state diagram, version 2.0] (click to enlarge)

In the end I lost a bit of abstraction and modularity in exchange for cleaner and simpler code. Updates to the code are now a breeze.

State diagrams were created using graphviz. Here are the .gv file for v1.0 and v2.0.
UML sequence diagrams were created with http://www.websequencediagrams.com/

Monday, April 5, 2010

Schedule Set!

Just laid-out and prioritized a list of all the fixes and new features. After that I made cursory estimates for time needed to complete each task. Then, setting aside 10 hours a week, put tasks to a schedule. link

As with any coding project there is always too many features and too little time. I've heard many times that the rule of thumb is to make time estimates, and then double it. That being said I believe my schedule is more towards the under-estimated side. Worst case scenario I see the all features upto the undo functionality being complete. Best case scenario I finish the schedule on time.

I look forward to attacking the tasks. When I wrote the level editor last semester I made sure to comment the code well and design it in a very modular fashion. And of course it's always easier to update one's own code than someone else's. The messiest part I see is in reorganizing the level editor's layer modes. Currently it's a fragile tangle of boolean flags, and now it's time implement it with a legitimate code. Creating new GUI components will be easy, since I have a sanely structured hierarchy of GUI object classes. The GUI hierarchy resembles that of Java Swing (which I had just recently worked with in OOSE).

Best of all this will be fun! We have a working game with great features. The only thing it lacks is a complete set of levels. And with a polished level editor it will prevent Planet Zolton from becoming forgotten-ware.

Issues and solutions

Just added a detailed list of issues with the current layout/functionality and proposed a list of solutions. link

Layout pictures

Added images of the current level editor layout and the propsed layout. link. A detailed list of the layout to come soon.