Monday, February 28, 2011
Sudoku Player Posted
This game took me a lot longer to finish up than I thought it would. Total development time was 22 hours. Still, the source code has been posted to the blazing games site for those of you who want to look at it. The series of articles on the creation of this game will continue next week as they still have to be written. I am going to try to finish off all the articles before next week so that there will not be further delays in the series.
Sunday, February 20, 2011
DDTe1 Hour 5 to 7 - Image Button
The final decision that needs to be made before starting to implement the code for a button is the type of button to implement. For the needs of the DDT project, there are two types of buttons that would be useful. The first is the ImageButton, which uses a set of images to display the four states of the button. This allows total control over the look of the buttons but at the cost of having to create artwork for every button. The other type of button is the TextButton which draws the button itself using a string as the contents of the button. Because this type of button draws itself, no artwork is required to use it making it really nice for getting stuff up quickly. Because the text can be changed, it is also very flexible. It is a bit more difficult to code, so I have decided to go with the ImageButton initially. If I have time I will create a TextButton as well since having both options is handy.
The first implementation issue is how to have the images. As BGLayers already supports image strips, the states will be in an image strip. However, for increased flexibility, the bounds to use for each state can be set up manually. Each state is represented by a rectangle that defines the portion of the image to be shown for each of the four states. To make setting up a button easy, the constructor will automatically generate the clipping regions based on the width and height provided. As it was simple to do, I also added clickable image support (the whole image is all four states) making this function useful for things like adventure games or hidden object games.
Event handling will be done by having an onClick variable that holds the function to call when clicked. I see no use for onMove or onDown or onUp variables, but certainly if you prefer finer control over GUI button clicks those event functions could be added.
The rendering of the image is simply done the same way as image strips were handled in BGLayers, with the only difference being that the clip rectangle is determined based on the current state of the button. This only leaves the mouse handling. BGLayers already has some support for intercepting the browser mouse events. The ImageButton simply needs to write handlers for them.
MouseMove first looks at the state of the button. If the state is disabled or down then that state is left alone. I like allowing the mouse to be moved off the button after it has been clicked yet showing that the button is down but if you don't like that behavior, it could be changed easily enough. If the button is in a normal or over state, we then simply check to see if the mouse is over the button. If so, the state is kept/changed to over otherwise it is kept/changed to normal.
MouseDown first checks if the button is disabled. If so, this action is ignored. Next, the function checks to see if the mouse is over the button. If so, the state is changed to the down state.
Finally, the mouseUp function checks to see if the current button is in the down state. If it is down then we check to see if the mouse is still over the button. If it is, the onClick function gets called with the button being the parameter. This allows a single function to handle all the button clicks in a program by simply looking at which button called the function. The state then gets changed to normal.
That is all that is required to create a button. To make sure the button class works, a test page was created (which was a good thing as there were some bugs in my initial implementation). The next step then is the check box.
The first implementation issue is how to have the images. As BGLayers already supports image strips, the states will be in an image strip. However, for increased flexibility, the bounds to use for each state can be set up manually. Each state is represented by a rectangle that defines the portion of the image to be shown for each of the four states. To make setting up a button easy, the constructor will automatically generate the clipping regions based on the width and height provided. As it was simple to do, I also added clickable image support (the whole image is all four states) making this function useful for things like adventure games or hidden object games.
Event handling will be done by having an onClick variable that holds the function to call when clicked. I see no use for onMove or onDown or onUp variables, but certainly if you prefer finer control over GUI button clicks those event functions could be added.
The rendering of the image is simply done the same way as image strips were handled in BGLayers, with the only difference being that the clip rectangle is determined based on the current state of the button. This only leaves the mouse handling. BGLayers already has some support for intercepting the browser mouse events. The ImageButton simply needs to write handlers for them.
MouseMove first looks at the state of the button. If the state is disabled or down then that state is left alone. I like allowing the mouse to be moved off the button after it has been clicked yet showing that the button is down but if you don't like that behavior, it could be changed easily enough. If the button is in a normal or over state, we then simply check to see if the mouse is over the button. If so, the state is kept/changed to over otherwise it is kept/changed to normal.
MouseDown first checks if the button is disabled. If so, this action is ignored. Next, the function checks to see if the mouse is over the button. If so, the state is changed to the down state.
Finally, the mouseUp function checks to see if the current button is in the down state. If it is down then we check to see if the mouse is still over the button. If it is, the onClick function gets called with the button being the parameter. This allows a single function to handle all the button clicks in a program by simply looking at which button called the function. The state then gets changed to normal.
That is all that is required to create a button. To make sure the button class works, a test page was created (which was a good thing as there were some bugs in my initial implementation). The next step then is the check box.
Monday, February 14, 2011
The Disciples III delay
I would like to claim that I am late with the post this week because I wanted to wish everyone a happy Valentines day. This would be a lie. Before writing the post on implementing the buttons, I decided to play a couple hours of Disciples III. As with a lot of strategy games, the next thing I knew it was two in the morning. The fact that this happened is a clear indication that the low reviews the game received are not the whole story. Certainly, waiting until the game went on sale allowed a lot of the bugs to be fixed, so my experience with the game is probably a much better one than the reviewers had, but there were still a lot of bugs in the game. Bugs are one of the bigger issues that the game has. The big issue that I have with the game is with the campaign design. I have always found that the best way of learning is by making mistakes. If you can learn from the mistakes that somebody else has made, that is even better. So I am going to delay DDT again but since the source for the game is going to be released soon it might actually be better as then the articles can focus on the theory. Still, I have to get into the habit of writing the articles as I create the code instead of procrastinating, but nobody is perfect.
For people who are not familiar with the Disciples series, I highly recommend going to Steam or to GOG and getting a copy of Disciples II (2 not the latest one). It is fairly cheap and is a really good mix of Strategy and RPGs. The third one adds 3D to the series as well as expanding the combat system. The hex-based combat is similar to the combat system that I am developing for my own larger-scale games that are in development and is quite fun. The problem is that the new combat system makes each combat last a lot longer and as a result slows down the game considerably. If the game would have had less combat to compensate for this time-sink, it may have been better. Of course, you have the instant combat option and the auto-combat option but these are badly broken.
Instant combat is far too decisive as it doesn't take strategy into account, just troop strength. As a result a battle in which I would have easily won despite my weak troops results in a devastating loss. The reverse also happens meaning that a battle in which you are probably going to win but will take a lot of damage will result in a no-damage victory. The auto-combat is a bit better, but has the problem of really dumb AI. I suppose one could complain that this is the problem with the Disciples III combat system is that the AI is really poor. Once you have a rough idea of how the opponents are going to react, it is easy to take advantage of the flaws in their logic. This is a problem that most games have so really isn't a flaw but rather a shortcoming of current game-AI approaches.
The problem comes down to having too much combat resulting in combat fatigue. But that is only half of the problem with the campaign. The other problem is that the maps are fairly linear and not very well balanced. There seems to be very little incentive to have more than a single hero, as you are for the most part following a single path that twists over the map. Part of the fun from this type of game is exploring the world. When the world becomes a single path (with a couple of minor sub-paths), you lose the feel of exploration. I should point out that I am only on the 6th episode of the human campaign so can't say this problem extends to the other two campaigns but I suspect it does.
The combat balance is off as mix of easy and hard encounters seem pretty random. There are many cases where a minor game resource has the equivalent of a boss fight while the key points are guarded by pawns. The other problem is that the big boss battles tend to be the whack the big beast who seems to have a huge amount of health, armor and spell immunity until it dies. While these bosses are definitely tough, the battles are extraordinarily boring. Whack, heal, whack, heal, whack, heal, whack, heal, whack, heal. No strategy required, just patience and luck. This is the reason I tend to hate game bosses. While there are some really well designed bosses which make the boss fight exciting, far too often designers just have a tank as a boss.
The game, however, is fun in small bursts so if you have finished the other games in the series it is worth playing. I think the move to 3D may have put too much emphasis on glitz and not enough on game play but can only hope that this is not the end for the Disciples series. Sadly, poor sales often result in the death of a series so I fear that this may be the end of a really promising series.
For people who are not familiar with the Disciples series, I highly recommend going to Steam or to GOG and getting a copy of Disciples II (2 not the latest one). It is fairly cheap and is a really good mix of Strategy and RPGs. The third one adds 3D to the series as well as expanding the combat system. The hex-based combat is similar to the combat system that I am developing for my own larger-scale games that are in development and is quite fun. The problem is that the new combat system makes each combat last a lot longer and as a result slows down the game considerably. If the game would have had less combat to compensate for this time-sink, it may have been better. Of course, you have the instant combat option and the auto-combat option but these are badly broken.
Instant combat is far too decisive as it doesn't take strategy into account, just troop strength. As a result a battle in which I would have easily won despite my weak troops results in a devastating loss. The reverse also happens meaning that a battle in which you are probably going to win but will take a lot of damage will result in a no-damage victory. The auto-combat is a bit better, but has the problem of really dumb AI. I suppose one could complain that this is the problem with the Disciples III combat system is that the AI is really poor. Once you have a rough idea of how the opponents are going to react, it is easy to take advantage of the flaws in their logic. This is a problem that most games have so really isn't a flaw but rather a shortcoming of current game-AI approaches.
The problem comes down to having too much combat resulting in combat fatigue. But that is only half of the problem with the campaign. The other problem is that the maps are fairly linear and not very well balanced. There seems to be very little incentive to have more than a single hero, as you are for the most part following a single path that twists over the map. Part of the fun from this type of game is exploring the world. When the world becomes a single path (with a couple of minor sub-paths), you lose the feel of exploration. I should point out that I am only on the 6th episode of the human campaign so can't say this problem extends to the other two campaigns but I suspect it does.
The combat balance is off as mix of easy and hard encounters seem pretty random. There are many cases where a minor game resource has the equivalent of a boss fight while the key points are guarded by pawns. The other problem is that the big boss battles tend to be the whack the big beast who seems to have a huge amount of health, armor and spell immunity until it dies. While these bosses are definitely tough, the battles are extraordinarily boring. Whack, heal, whack, heal, whack, heal, whack, heal, whack, heal. No strategy required, just patience and luck. This is the reason I tend to hate game bosses. While there are some really well designed bosses which make the boss fight exciting, far too often designers just have a tank as a boss.
The game, however, is fun in small bursts so if you have finished the other games in the series it is worth playing. I think the move to 3D may have put too much emphasis on glitz and not enough on game play but can only hope that this is not the end for the Disciples series. Sadly, poor sales often result in the death of a series so I fear that this may be the end of a really promising series.
Sunday, February 6, 2011
Preparing for the Event
Having buttons and other GUI elements is nice, but before they are useful, your program need to be able to react to them. There are actually a large number of ways of dealing with this problem with the different solutions having their advantages. The most basic way of dealing with events is to use polling. This is essentially what is happening beneath the hood at the OS or BIOS level. Essentially, you loop through the objects that can cause an event to see if an event has been triggered. When an event is triggered, a handler is called. This works, is relatively simple to implement, very efficient, and is probably not appropriate to use in a scripting language.
Scripting languages are meant to respond to events. However, as the user interface elements that are being created are latching on to the events that the browser is passing to it, the mouse event handler could poll the current set of active UI objects to see if their state has changed and handle the changes. This fits into the scripting event model, is fairly quick and simple to do, and for the simple games like those being created under the Dozen Days project is more than adequate. One of the concepts of the extreme programming methodology is to not over-engineer problems as one common killer of projects is to make the code complex enough to deal with features that may be needed in the future but in reality never come. If at a later date you need the features after all, refactoring can be done. Still, if the extra functionality comes without the cost of more complex code, then it is worth doing so let us continue to look at the options.
The next level up is to simply have a callback function that gets called when an event gets triggered. This makes the events much easier to handle as they no longer have to be crammed into a single event handling function but can be spread out to as many functions as are desired. Again, this is very simple to implement and it adds a huge amount of flexibility. The only downside is that only one function can be tied to each UI item. This is rarely a problem.
To get around the problem of only having one callback function is to have functions register with the component as a listener. This requires a lot more complexity as you need to be able to add and remove listeners as well as call all the listeners when events happen. If implemented in a primitive object that you know the UI components are going to inherit from then this may make sense as the code can be written easily enough. Still, this is more work with very little extra value.
A similar approach to the above would be to have some type of global event manager. Any code could call the event manager to register itself as a listener to any event. When a component has an event to send, it just tells the global event manager. It would not need to worry about anything else. While it would be a fair bit of work creating an efficient event manager, it would make events a pleasure to deal with. While way to complex for my needs, it would be a technique that could easily be refactored into most the other approaches so is an approach to keep in the back of your mind.
Scripting languages are meant to respond to events. However, as the user interface elements that are being created are latching on to the events that the browser is passing to it, the mouse event handler could poll the current set of active UI objects to see if their state has changed and handle the changes. This fits into the scripting event model, is fairly quick and simple to do, and for the simple games like those being created under the Dozen Days project is more than adequate. One of the concepts of the extreme programming methodology is to not over-engineer problems as one common killer of projects is to make the code complex enough to deal with features that may be needed in the future but in reality never come. If at a later date you need the features after all, refactoring can be done. Still, if the extra functionality comes without the cost of more complex code, then it is worth doing so let us continue to look at the options.
The next level up is to simply have a callback function that gets called when an event gets triggered. This makes the events much easier to handle as they no longer have to be crammed into a single event handling function but can be spread out to as many functions as are desired. Again, this is very simple to implement and it adds a huge amount of flexibility. The only downside is that only one function can be tied to each UI item. This is rarely a problem.
To get around the problem of only having one callback function is to have functions register with the component as a listener. This requires a lot more complexity as you need to be able to add and remove listeners as well as call all the listeners when events happen. If implemented in a primitive object that you know the UI components are going to inherit from then this may make sense as the code can be written easily enough. Still, this is more work with very little extra value.
A similar approach to the above would be to have some type of global event manager. Any code could call the event manager to register itself as a listener to any event. When a component has an event to send, it just tells the global event manager. It would not need to worry about anything else. While it would be a fair bit of work creating an efficient event manager, it would make events a pleasure to deal with. While way to complex for my needs, it would be a technique that could easily be refactored into most the other approaches so is an approach to keep in the back of your mind.
Subscribe to:
Posts (Atom)