Jump to content
  • Advertisement

YAAG

Sign in to follow this  
  • entries
    7
  • comments
    2
  • views
    8567

About this blog

Yet Another ASCII Game

Entries in this blog

 

The Arena Update

After taking a long week to help a friend build a game for the Week of Awesome I took a little time to convert the ASCII game into a GameJolt game.

This doesn't mean it is power by their servers it just means you can download it from their site and use your GameJolt user and token to login to the game. As I continue to work on the game more of the GameJolt features will be added like using the score board to show players how well their doing compared to other players.

The GameJolt API on the surface seems very simple and to get a test project up took only a couple of minutes. The hard part was getting it to work with my few thousands lines of code. I really didn't want to reprogram the game to include the integration of the API but for a while the compiler errors I was getting was difficult to solve. To first issue was my project uses Multi-threaded runtime libraries so that I can also use Crypto++ in my project for encrypting the user password. Now I no longer will need this since it uses a token from GameJolt but I didn't want to just throw away the ability to have some kind of encryption. So I created a project that would compile the GameJolt into a Static Library. Once I figure out that it also needed and could be set to the Multi-Threaded runtime things started to flow together.

Next came the issue that the GameJolt API really needs to be the first library my project includes. This took some time to figure out and I finally stumbled on it by accident. Moving it to the main code file as the first line of code cleared up all the errors I was getting during the compile stage.

So now every got setup properly and the APi is working. The couple of issues I now need to figure out is the best way to go about saving the data. In the old design it was easy to just do a quick file save and go on. But with the data on the internet this can cause several game screens to load very slowly. This will be the next experiment is to start using the non blocking data set functions instead of the current blocking functions.

For those interested in seeing and playing the progress you can find play the game at:

http://gamejolt.com/games/the-arena/86683

lede

lede

 

The Arena Update

Introduction
The Arena (YAAG) has turned a corner in development that I wanted to document for other developers who have started their own new project.

The Beginning
Every project I have started the beginning starts out quickly and things seem to build quickly. This stage is full of great ideas, new experiments, and a host of thinking how great this game is going to be. But yet it is still in the idea and planning phase which I like but can't wait to start laying down some code. The foundation of the new idea is important because later stages will depend on the organization of the starting point. The Arena was developed based on a book I was reading and I wanted to try out the new ideas presented to me from the book. So for this project I spent a lot of time thinking about how the game engine was going to work and with my past experiences traps I wanted to avoid.

The Middle
At some point the development turned from planning and more focused towards development. This phase seemed to move slowly because there was a lot of foundation code that needed to be developed before being able to focus on game play and game design. Many of the releases on the surface seemed to have little or no difference but the underlining systems were starting to take shape and provide the power needed to make the game more functional and easy to manage.

The problems I ran into in this phase was man of the planneded features require systems to help handle the different game design needs. During the middle phase I noticed several issues that were difficult to manage so breaking them out into their own system made more sense then trying to make one system handle everything. These parts are as follows:
The Game Engine
The Entity Manager
State Management

The Game Engine
The core game engine was designed to manage most of the games looping needs. I used the Update pattern that would allow the entities to run an update process every frame. Once all updates completed and if there was enough time left over the engine would then run the graphic routines to draw everything to the windows console screen. For the most part once the core game engine was completed I rarely ever touched the core code which to me seemed a good initial design.

The Entity Manager
Yes the game engine is also responsible for simulating the entities in the game but I found that expecting the game engine to do everything would limit its design. So the entity manager is used to handle the creation of game objects like all the monsters and the player. I also added the combat field to the entity manager for simple collision detection. Hooks were added to this system that allowed the game system to validate movement. There are several interfaces used to help trim down and make the entity manager accessible in several location of the game.

State Management
Originally I was trying to implement this in the Entity Manager but it started to get convoluted so I moved it to its own system that would handle all the game states. At this point the game went from one state to about 14 different states. Think of a state like a menu in a typical Windows program. One of the major design decisions was to enable the manager to overlay different states so when one state was done it would be removed from the stack and the previous state would be active again. I used an array as a stack so that it handled the different states as they would be added and removed from the game.

The original design of the state manager was to help with in game menus but as I created it the idea started to percolate in my head to use this for managing all the different screens of the game. For the latest release it integrated all the login, create account, death screens, and anything else that would be needed as a screen for the player. During this process the game started to take on a whole new feel for me on how it played. Instead of just now randomly being attack constantly by the game players now exit after each battle. Can select a new monster or exit and return to the home screen.

The one last thing I would like to say though about the state manager, it has been probably the most boring and tedious part of the development process. I spent many hours programming UI code then I would like to admit but the final design has made it fairly flexible. Now I know why many project include a dedicated UI programmer and if I could afford this luxury I would.

The Next Stage
At this point I feel the middle stage is complete and now I'm going down a new section of the project. Many different doors have opened up and the game doesn't seem so limited. Players can make a few choices that helps them focus their character on their personal play style. Most games I have worked once they entered this stage of the project I had a few weeks to do all the clean up and push the project out the door. But on this project I plan on spending as much time on this phase to add as many refined features as I possible can.

It is also important for me to also include as much testing on this current build and to do some balancing to make the game seem a little more challenging as players progress up their levels.

Conclusion
It has been a short development cycle for this game. I've spent maybe a few months to get the game to this point and will probably spend a couple more to finish the game. The one thing I learned and need to be careful of is how addicting the development has been to me. I've found myself spending way to much time working on this game then I should of but it has just been way to much fun! Getting to where the current state of this project has been a massive amount of work but well worth the effort.

This project has been a major learning experience for me. The first thing I have learned is how important a good foundation is needed to keep the game easy to develop. This doesn't mean I didn't run into some difficult design decisions but I did find having a solid foundation is very helpful. Next has been to not tie myself into one design decision or think that one object can do everything. Breaking complex parts of the game into more manageable pieces has been on of the biggest learning experiences for me.

lede

lede

 

Game Loop Speed 2.0

Introduction
Yesterday I posted a game loop speed test which I have taken down because it had some major flaws and bad data. This is the second iteration in my tests and I am here to provide my results. Here are a list of flaws that need to be addressed in my game loop test:
All data structures perform a sequential process with no adding or removing of entities
The test was with a small number of entities and needed to be expanded
The results only showed a basic idea and I had drawn some poor conclusion from the data sets
The lists are not sorted so searches will be slower then needed.
The differences between debug and release builds

For today I'm going to address items 2, 3, and 5. I will address 1 and 4 in my next journal entry.

Small to Large test group (2)
The initial tests were done with a small set of entities with and without frame rate management (Just means I paused the frame when there was extra time). Initially I wanted to provide some basic results on a small set of entities but the time it took to perform these tests were insignificant. We are talking about very small fractions of time so it was very difficult to see any difference between data structures. To change this and do a better stress test I have set the entity max to 128000 for the release builds and 6400 for the debug builds.

Debug vs Release (5)
In this version of the test I will provide times for both the debug version and release version on the graph so there will be a direct comparison. The reason for this is during my testing I found there was a very surprising result that I wanted to add to the findings.

New Results (3)
The conclusions of the tests will be provided with more of a analysis of the data and how it performs for this specific scenario. Data structures are like Golf Clubs, each one is designed for a specific obstacle and has their special use. The key here is how the golfer will use them in different situations and how programmers should really know how their data structures will perform.

Debug Test Results
Because I'm lazy and short of time these days I only tested this build with 6400 entities which gives a good example of the results. Here are the results of running the test 6 different times and then taking the average:



These results are very comparable to yesterday's tests but with the 6400 entities you can see that the standard link list is slow and couldn't keep up with the frame rate. If we stopped here and drew our results from these numbers it would be clear that the std::list would be a poor solution. But I didn't stop here so lets look at the release results and see what happens.

Release Test Results
With this build I cranked the entities up to 128000 because the engine needed a larger number in order to register time on the clock. So after cranking up the number of entities to handle in the test here are the results:


Now after running this test we can see that my crappy attempt at making a quality linked list template failed. Which means I maybe going back to the drawing board to fix it after these test results. Anyways the interesting thing here is the std::list performed way better in these tests. Still not at the speed of a solid array but still very decent for 128000 entities.

Release vs Build
This graph was just for fun to see a direct comparison between the two build. Even though this isn't apples to apples you can see the difference in times for the data structures. Every single one of them gained a major performance boost between the two different build types.



As you can see the time are significantly large in the debug build. Here is one simple optimization you can do to get more speed out of your game. Build with the release options. I'm sure there are more things we can do but this is a good start.

The Code
I've included a copy of the Visual Studio 2013 project files I used to perform these tests. As the sole author of this code I give the rights to anyone who wants to use it but with this simple warning: Use at your own risk I do not provide any warranty with this code. If you find it useful please let me know.

Conclusion
So after all the testing the question may remain which data structure should I use? Honestly it really boils down to what you need to do with the entities in your game. The real test is you need to take these data structures into your current build and test to see really which one will perform better for your situation. The other thing to also remember is what build are you using. As the numbers point out it doesn't matter if your using an array or a standard linked list. When your running under a debug build it will always be slower. In the case of the std::list it was massively slower compared to the other data structures.

In the big picture of things if you think about the time and frame rate each data structure performed optimally for their load even under the debug versions except the linked list. In theory each game loop should of ran for 60 seconds but because I disabled the frame rate manager we were able to process the same number of frames in 1 or 2 seconds with 128000 entities. Depending on your game though you may need to bleed as many calculations out of your processor each frame. This just means don't pick one data structure and think your done. Test it and make sure what you have added is not taking longer then it should.

Lastly I want to say don't be afraid to try something new! Just don't take my word that these are faster because of A,B, and C. Know they are faster because you have put the effort out to make sure your getting the best performance for your scenario. Take my project and play around with it to see what work and doesn't work. Try building different test cases and see how it performs and then compare results.

lede

lede

 

What Happens in Update?

Introduction

In a previous post I talked about my game loop and mentioned that the Update method was where a lot of the calculations for the engine are done. I've highlighted the method in this picture of the UML diagram:



I extracted most of the calculations from the RunEngine loop for a few reasons.
The RunEngine loop was getting rather long and hard to follow.
Now I can add the engine to another engine to process updates.
If the game needs to for some reason to update the engine it now has access to this method externally.

Those are just a few reasons I broke the main game loop into sections. So here is most of the update code for today's discussion:[code=auto:358]void GameEngine::Update(){ std::queue tranObjects; // Get start position of entity array unsigned int pos = eFront; while(pos != eBack) { // Check if the entity fell asleep if(entityArray[pos].IsAsleep()) { // Add entity to the transfer queue tranEntity.push(entityArray[pos]); entityArray[pos] = new NullEntity(); }else { // Process update method of entity entityArray[pos]->Update(); } pos = (pos + 1) % MAX_ENTITIES; } // Transfer sleeping entities while(tranEntity.size() > 0) { // Get front entity we are sleeping IEntity* enty = tranEntity.front(); tranEntity.pop(); sleepArray[sBack] = enty; sBack = (sBack + 1) % MAX_ENTITIES; enty->GoingToSleep(); }}
Discussion

The first thing to notice in the update method is there are three main loops. This would put this algorithm at Big O(n) * 2 or Big(2n) depending on how you like your math. In the first loop we go through all game entities and check weather they are asleep. If they are then we add them to a standard queue for later processing. If their still awake then we run their update method

Sleeping Entities

The idea behind having two stacks is that a game entity may no longer need to do calculations but we still need to draw it to the game field. So in this example when the entity feels it has fallen asleep then we no longer worry about running its update. Currently the down side in my design is once an entity goes to sleep it will be there until the engine gets a clear all call. I do plan on though adding in to the engine a way to wake up the sleeping object and put it back in the mainstream entity updates.

Once an object has been put to sleep I do call a special entity method GoingToSleep() this is to allow the entity itself to do any last frame maintenance before it is dormant for ever. Well kind of for ever, they still get drawn so there is potential to do something there. The one thing to note in my PlayerEntity class the IsAsleep() method when called will always return false. Which means if your playing my game you can't fall asleep I won't let you...

The other advantage here is that if I have game field objects that are not moving and want to add more active objects we are not limited to the max entity game limit. Currently this is set to 16 but there is no reason it couldn't be bigger. Is this to small of a number? for a different game that could potentially have more moving parts yes this would not work. but for my simple ASCII RPG type game where there is usually only one palyer and one monster it maybe over kill. But potentially we could setup the random monster generator to not just create one monster but add a pack of monster for you to deal with. Yes this is planned in the game.

Data Structures

You maybe wondering why did I decided on using an Array instead of something like a linked list or any other awesome and amazing data structure out there? This is actually a good question and one of my original engine designed did use a custom double linked list because I liked the ability to adhoc put objects into the game and not worry about any limits. This was fairly naive of me in thinking this would be a good performer. If you know how a processor will read memory and cache hits and cache misses then you might understand the round trip to the memory banks actually slowing down your algorithms. The idea is if we can keep all our data together then we have a higher chance in getting a processor cache hit when it is working on our calculations. Using a linked list leads to memory fragmentation.

This subject could use some hard number and tests performed to prove how much more efficient either data structure can be. For now I will leave this for another discussion so I can take the time and perform these test and provide solid results.

The other thing to note on the game array is that I keep a record of the start and end of the active items in the array. This is so we don't have to loop through say 16 items every time the update loop is ran. It also allows me to remove items from either the front or back of the array and then update the pointer. Another cool trick you can do with arrays which is fun to exploit.

Conclusion

It is worth mentioning that in the actual engine code there is another loop that runs which is primarily for items in the engine that just need to perform updates and not do any rendering. This kind of makes the update run in Big O(3n) time. Overall though this update method provides decent abstraction and power to the core engine. Because of this design it made it quite easy to fix my render flaw when the frame draw got skipped.

lede

lede

 

How to squash bugs!

Yesterday we talked about the game loop and that in my current version there was a bug. This particular bug was rare and would only be seen on older or very slow computers. So the first step in figuring out a bug is to work out a way to reproduce the issue. Several of my testers were not able to give me specific steps to reproduce the bug. But in this specific issue I had already ran into the bug when I was fooling around with the frame rate.

This specific bug is a good example to work together on and see different steps to working through the problem. Our report from the testers was that in some cases the character would show up multiple times on the game field. So here is snap shot of the bug in action:



To produce this image all I had to do was first set the FPS to 60, run the game and press down on the keyboard. What is happening is the engine will skip drawing a frame if it runs out of time on a frame. So when we want to move the engine will always process the calculations. For example the following image the player is in position 4 of the grid and wants to move towards the square labeled as 1:



So the user pressed down the [A] key and the game knows now to move the player to the left by one square. But because of the processor overhead the game engine runs out of time on the calculations so it skips the drawing. Next frame comes around again and the player is still pressing the [A] key so the game knows to keep moving him left. This time we have time to render and now we get the artifact showing up on the game field like in the next image:



So this basically equates to the following frame sequence:

Start calculating frame 1
Loop through all active objects and process their update method
Player is moved left one square x = 43 and old position recorded to the right old_x = 44

calculate elapsed time
do we have time to render? No skipping rendering

Start calculating frame 2
Loop through all active objects and process their update method
Player is moved left one square x = 42 and old position recorded to the right old_x = 43

calculate elapsed time
do we have time to render? Yes render frame now!
Move to x position 43 and draw the cached value of the game field (Erase the characters old drawn position.)
Move to x position 42 and draw the player.


If you followed the calculations the first time the player was drawn to the game field was when he was at the x position of 44. So when we skip rendering a frame the player is never removed from the old position as it gets updated every time we move.

So technically there are two solutions to this problem. One would be to change when we update the old players position which would mean we would then need an event to handle drawing inside the IEntity class. Doing it here could get very complicated and add a ton of code to the Entity class that I'm not sure is necessary. The second fix would be to change the game engine loop to alternate between calculating game entities and drawing them to the screen. In this fix we could add a Boolean value that would set to be true every time the engine gets a chance to render. So the update version of the code would look something like this:[code=auto:108]//... Init code has been clipped for brevity.// The game loopdouble time;bool gfxDrawn = true; // Addeddo{ time = clock(); if(gfxDrawn) // Added { Update(); } // Check default controller for the [ESC] key if(Controller()->ChkInput(VK_ESCAPE)) { _isRunning = false; // Set the run state to false, Game over man! continue; } int sleepTime = static_cast(time + MS_PER_FRAME - clock()); gfxDrawn = false; // Added if(sleepTime > 0 || !gfxDrawn) // Added the not gfxDrawn check { //... Cliped more code from this section for this discussion gfxDrawn = true;// Added // Burn some time since we got done with out work early today! std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); }}while(IsRunning()); // Shutdown the engine code as we exitreturn iRetVal;
This worked perfectly because now I can crank up the frame rate and no longer worry about artifacting on the game field. The caveat to this fix is I decided as the engine designer to sacrifice calculations for graphics. Depending on your type of calculations this may not be an option. In a different environment like a tile or sprite based game this fix wouldn't be needed. But for a text based game that has very little physics or calculations it was okay to skip a calculation for one frame.

Another thing to think about is the pros and cons of each way to fix the problem. Remember this isn't generic to every problem but is specific to this game. If we decided to move the update of old position to the drawing process then it would only record the last drawn position and we could properly update the character being drawn. The problem that I can foresee is that when a render frame is skipped the player would jump a massive amount of spaces on the field. Most of the time when it is 2-3 pixels of a jump it isn't that big of a deal. But for this game since we are using text jumping 2-3 squares will make the character very difficult to move around the game field. As it is when the frame rate gets over 25 the character is very hard to line up with the monsters.

The moral here is many times the fix is dependent on the type of problem and each problem may have a unique solution. Please feel free to ask questions if something doesn't make sense to you.

lede

lede

 

The Game Loop

The original game was played over the modem and was a turned based game. Since BBS are fairly scarce these days I have made this a stand alone game. Also since blocking input was very common in older games I've changed the game engine to not block input and be more interactive like today's games.

Another difference is the 286 and 386 computers only could run one thread unless you had a multi processor board which in the 80's was very rare. Since this is being made in C++ in a modern compiler I will work on adding multi threading support to the game. Right now because the frame rate is very low (12 FPS) that gives me a ton of time to calculate and draw changes to the ASCII graphics engine.

Last time we discussed the Entity system that I created and we only talked about high level design of the code. This is all fine on a high level but the bugger is in the details of the code. Like last time though I will keep with the painful UML diagrams so we can have a good discussion about the code and how the objects communicate between systems.



The first thing I would like to explain is the text in green "IEntity" is referring to the previous UML diagram I posted yesterday. If you need it again please let me know and I'll re-post the image. Now then as you can see the UML diagram is getting complex quickly. There are a lot of interface classes that help abstract items in the core engine. This designs allows for me to have the freedom to create similar type objects without having to ever touch the core engine. In the past month since the core engine had been completed I have rarely touched the code because of this design.

Now then lets start with one of the fundamental parts of the engine. To me the term engine means it loops infinitely or until the user or computer needs it to stop. This is where threading comes into play because now we can have the GameEngine, PhysicsEngine, and SoundEngine run on their own threads. I tried to break the components down into section that either would have a lot of calculations or would take time to load. So the core function in the IEngine class is RunEngine. This is like when you start your car or pull the ripcord on a lawn mower. Once the engine starts running it goes until it is time to quit. The reason for the return value int is so that we can use that to report back to the OS how the program exited.[code=auto:108]//... Init code has been clipped for brevity.// The game loopdouble time;do{ time = clock(); // Get when this frame time started Update(); // Run the update system // Check default controller for the [ESC] key if(Controller()->ChkInput(VK_ESCAPE)) { _isRunning = false; // Set the run state to false, Game over man! continue; } int sleepTime = static_cast(time + MS_PER_FRAME - clock()); if(sleepTime > 0) { /... Cliped more code from this section for this discussion // Burn some time since we got done with out work early today! std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); }}while(IsRunning());// Shutdown the engine code as we exitreturn iRetVal;
So this is the engine loop or game loop which ever you prefer to call it. Most of these loops I have seen use a while and in this one I used a do. This was because I wanted the engine to run at least one frame since it was fairly safe to do even if everything was not properly setup. I'm also not a big fan of the while(1) loop idea because it leaves room for an infinite loop bug. I prefer the bool variable based loop control so that my code can properly handle shutting down the main loop. There really is no advantage to either way and is a personal preference of mine. You could re-write the loop using a while(1) and just add a break instead of the continue statement to shutdown the game engine.

The nice thing in the engine if you want to disable the [ESC] key from shutting down the engine and you want to take over this control in the game logic then you can do that by setting the controller to a NullController instance. Originally in my game before I had the game logic built to exit the game I used the [ESC] key to shutdown the game. But once I had the exit define and it was able to gracefully shutdown the game I removed the KeyboardController from the game engine and put the NullController there instead. If you are doing the same then let me warn you first make sure your game logic will shut down perfectly before turning this functionality off.

The next important thing is the timing of each frame. I know there are a lot of complicated calculations out there and I believe from my Game Patterns book he recommended using a simple approach to the frame rate. In this example I just calculate how long each frame should take which is MS_PER_FRAME = 1000 / 12. Now when the engine has extra time left over it will put the thread to sleep so your computer can do something else. Other designs try and suck every tick out of your processor and leave your computer in a defunct state until the game exits. I prefer to let you use your computer and play my game at the same time.

Now the hidden part of the code is in the Update method. This method gets called each frame and will process updates for every Entity and Updater item in the list. If we have time left over then we can draw the updates to the screen which has introduced an update lag and draw error. I haven't solved this issue yet but I have an idea that if in one frame you ran the update but ran out of time to draw it to the screen the next frame should draw and not update. This would solve the issue where the game could freeze and the next time a frame gets drawn you jump across the screen. Also since I'm using an ASCII graphics engine and don't render the full screen every time it would help prevent artifacts from drawing on the game field.

That is all I have time for today but stay tuned for the bug fix and the update method.

lede

lede

 

Introduction

Welcome to Yet Another ASCII Game (YAAG).

Why did I name this journal YAAG? Well the initial name comes from a programming term that is used when you develop your own programming language Yet Another Compiler Compiler (YACC). But this journal is not about writing a programming language it is about my journey in creating a game I loved to play as a child on the old BBS systems. You may hear from time to time that I call this game The Arena which was a name I called my own version of this game in the late 80's. Its now been 20+ years since I had worked on a project like this so my old code is gone and I have started from scratch building the game and engine together.

Why did I build an engine on top of the game? The short answer is I love writing engines and learning how to write optimized code. That and I read an amazing book on Game Patterns that inspired me to try and make a game and after a bit I decided on this ASCII game. That and I wanted to focus more on Game Design then graphics. All the graphic game projects I have worked on typically get bogged down with tedium work while game play gets skipped.

Will you be porting this to other systems? This is a good question. Maybe someday I will work on the port process but for now this will only run on a current Windows computer. On the surface the engine is just C++ code and should be able to be built with just about any system as long as the graphics engine is created during the port process.

The Arena Game



This is where I was after a couple of days. It was playable and in this image is a test of adding multiple monsters into the engine. To get here the engine needed to have some basic functionality like the ability to create and add different type of entities to the core engine for simulation. To start this process in needed a way for the entity system to be flexible enough to handle just about anything my feeble mind could create. So this is the basic UML diagram for the entity frame work.



Sorry if I got the diamond facing the wrong way its been a while since I've written a UML diagram. But the idea here is that the IEntity has a mover object which controls the entities ability to move around the game world. The mover has a controller class that either brings keyboard input into the game engine or we could use just about any other device like a Joystick, XBox Controller, etc.. In this flow you can see I even connected my AI engine to the controller. This allowed me to reduce having to build a ton of different movers because most of my movement is for all the game entity shared all the same needs. Abstracting it this was exciting to see if I plugged a keyboard controller into a monster then I could control the monster. Also being able to plug in the AI in this matter allows be to create so many different AI system without really getting to complex.

The next couple of things for me still to work on in this paradigm is to add a network controller so that a server and client system can be developed and the engine can do network play. This is my goal but I haven't gotten to this point yet of the game, still working on the game play.

So now that the basic entity system is built is was time for a massive amount of game design. With a lot of work the engine and game started to take shape but I quickly found that this low ASCII resolution was not going to give me the game board and interface I really wanted to use. So doing some research into the Windows Console I found there are a couple of ways to increase the size so that now I can add in a lot more interface design and not be so cramped on a 24 line command prompt window.



In this there is a fully functioinal exit. No longer can you just hit eascape to flee the monster but you have to make it to the exit before the monstger has a chance to end your life. The current monster database consists of about 25 different monster you can encounter, 51 different weapons, and 27 basic armor. Originally all the data was hard coded in C++ code which was easy to maintain while I didn't have so many different items. Now I have moved all this from code to Excel and use a CSV parser to compile the data into a simple DAT file the game can quickly consume an directly instantiate object from the data.

Death to the Singleton!

So the patterns book I read really opened my eyes to this pattern which up until this was the bread and butter of my global classes. But in this iteration of my game engine I really made the effort to not have a singleton class anywhere. For instance if you remember the UML diagram from before it showed an interface called ILogger. In the past I have typically created this as a singleton pattern because I just wanted to be able to grab an instance and start logging. When you don't have a lot to log this was fine. But even in this small engine I found there were so many times my log file would grow to a few thousand lines and finding what I wanted was way to diffuclt. So throwing that idea out was the best thing I learned in my pattern book.

Now when the debug version of the engine starts up I have several logging system to track the core engine, entities, AI, and a few other systems that are to small for me to remember. Then there is the new NullLogger class. The odd thing was I had actually started to use this class in other projects before I learned about it. But if you get tired of always checking to see if an object has been instantiated then why not just make a Null version of that interface that really does nothing and can be safely plugged into any system that would need it. This is typically called the Null Object Pattern and for me has been really useful. Most of the time now when I careate an interface the next step for me is to create a null version of this interface.

Well for now this will have to do for me getting started. I'll keep working on this design journal and my journey to making one of the games I had a blast playing as a kid. Also it was a lot of fun to break out my old UML skills so hopefully this will become a norm when talking about design ideas.

lede

lede

Sign in to follow this  
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!