Computer Science Canada [Tutorial] Polymorphism and Game Engines |
Author: | Stove [ Wed Jul 23, 2008 1:30 am ] | ||||||||||||||
Post subject: | [Tutorial] Polymorphism and Game Engines | ||||||||||||||
Edit: I forgot to turn off smart quotes when I was writing this, so any random question marks are quotation marks As the title implies, this tutorial is about polymorphism and game engines. I'm pretty sure no one has done a tutorial on this before (not that it's too big of a deal anyways) so here goes? Table O' Contents Preface Introduction Setting up your "object" class Setting up the game manager Creating game elements Adding game elements Conclusion Preface Ok, so I randomly decided to write a tutorial in Turing. I'm not sure why I chose to write it in Turing. It must have been because of its great features, like full support for dynamic arrays, excellent performance, placeholder functions, its great company support and version 4.1.1's super small exe size. No wonder most of Ontario's computer science classrooms are filled with the sounds of happy carefree students nonchalantly building their first programs in a warm and fuzzy language, definitely not pounding their weary heads against their keyboards, staring into the black and white abyss of their monitors, screaming in painful agony as the happy sunset of the Turing logo mocks them in their desolate misery. Moving on? This is the first tutorial I've written and hopefully this won't turn into a mess. As to why I chose to write this is Turing: I absolutely hate Turing (as evidenced), because of its many technical limitations and annoying syntax, however Turing is a beginner language and more people will therefore benefit from my tutorial if I write it in Turing. Anyways, I'll try to keep things straight forward and include pictures or diagrams wherever possible (although my MS Visio trial ran out). I recommend reading some other tutorials about classes and polymorphism before reading this one, as I don't plan on completely explaining them in this tutorial. Introduction For this tutorial I will be explaining how to build your own simple reusable and self managing game engine using polymorphism and classes in Turing. In case you're new to the idea of a "game engine", a game engine is essentially a centralized system which handles all input, output, updating and management for a game. The game engine is responsible for loading, displaying and processing all of a game's content, be it levels, sprites, textures, shaders etc. These resources are not part of the game engine itself, but stored in external files. As well as loading content, the game engine is in charge of interfacing (although not usually directly) with various hardware, such as the video card and sound card. Essentially, a game engine is the skeleton of a game, which supports all of the content of a game. There are many advantages to using a game engine over hard coding everything. Having a game engine makes updating content and adding functionality a lot easier, as it is possible to change the content of a game without having to rebuild everything or do additional programming. This allows more time to be spent on actually designing a game instead of worrying about the loading of resources and the updating of game objects. As well, game engines can be reused again and again for different projects, making it worth the effort it takes to create a good engine. Although game engines are a must for large and complex games such as RPGs and shooters, most small and simple games don't need to be made using a game engine. For example, a simple game of pong doesn't need to load many resources or need to worry about many complicated things, so it's alright, and probably a good idea to hard code it. However, when you begin to have more complex object interactions and needs, like 20 objects which collide with each other, having a game engine makes it possible to have this automatically managed and handled for you without any sort of direct or specific or programming. Now that you (hopefully) understand what a game engine is, let's talk about how a game engine works programmatically. A game engine is usually represented as a class which contains an array or collection of game objects, and methods (procedures and functions) which control the game. The game engine is either told to start the game (it updates itself) or a loop in the main program calls an update function. For the sake of convenience, the game engine I will be building will use the first method. When the start method is called, the game engine enters an infinite loop where it calls each object's draw, and update procedure. This is achieved through polymorphism; each game entity inherits from a master "object" class which provides overrideable methods which perform certain tasks for the entity. Anyways, enough talk, let's actually start building something. Setting up your ?Object? Class When you first build your generic object class, you want it to encompass all the features that your game entities will possess. Usually in larger engines you have multiple of these generic classes which are specific to certain types of objects, for example, if you had an object that needed only to draw itself and was never going to move, it might be in your interest to create a "detail" type class, which contains only the parts it needs to draw itself and nothing more. This way you can conserve memory, and be able to target specific entities of your game (you would store "detail" objects in a different array or collection than say, all your moving objects). This gives your game engine more flexibility in what it can do. However, for this tutorial I'm going to keep it simple and only use one type of class. So let's first start off by defining our class. It will contain variables for a position, an image, speed and direction as well as a creation and destruction procedure and two "deferred" procedures which will serve as the game engine's means of "communication" with the object. As well, the class will contain a few other "internal" procedures such as a procedure for moving (not using speed and direction). Remember this is only the blueprint for an entity in the game, so you don't want to make anything specific to the actual game you are creating, as that is defined elsewhere.
Ok, so there's the code for our basic game entity. It's fairly straight forward, just some basic variable and method declarations. The only "not straight forward" part of the class is the declaration of the deferred or abstract procedures at the bottom. Basically what's happening, if you're not sure, is that we're telling Turing that we will write the actual code for the procedures in another class that inherits this one. Overriding these functions, as it is called, gives us the ability to make our objects perform specific things, like having one entity move left when its update procedure is called, and another entity move right when its update procedure is called. Now that we have our basic game entity class, we will move on to making the actual game engine itself. Setting up your Game Manager The game engine class is probably going to be the most complex part of the tutorial, but I'll try to keep it relatively simple for this tutorial. It will consist of a dynamic array of game entities, variables for controlling the frames per second and a few procedures which control the game engine. These procedures are responsible for adding and deleting objects and updating the game. So let's start this off with a couple code snippets.
Firstly we have the main variable declarations, it should be pretty straight forward but I want to take a moment to explain how the "Entities" array works. The array begins by having two empty elements of the generic game entity type "Object". It?s basically like having a list of people, every person is different, but still has the same basic features (a name, eyes, ears, etc.) which you can ask for, e.g. everyone would (hopefully) have a response for "what is your name?". The Entities list works the same way, but the "same basic features" are the ones inherited from the "Object" class.
Next, we have the Create procedure, which should be called before the Run procedure. It assigns the Fps variable which is used to assign the "FpsMilli" variable. The "FpsMilli" variable is used to tell how often (in milliseconds) the game should be updated based on the "Fps" variable. For instance, at 1000 fps the game is updated every millisecond (or it attempts to), and at 30 fps the game updates every 33 milliseconds (1000 div 30).
Next, we have the Run procedure, which is called when you want to run the game (what a shock). First the "thisTime" variable is assigned the current time since the program began, this is used next to find the time since the last update. If the time is greater than or equal to the "FpsMilli" variable, the game updates. Each time the game updates, the "lastTime" variable is assigned the current time which will reset the timer. Then the screen is cleared, and if the escape key is pressed the Run function exits, ending the game. Next we iterate through the Entities array. This is where the deferred procedures come into play, for each Object in the array we call its overridden procedure for drawing and updating. You should always draw each object last or after everything has been handled, otherwise whatever is on the screen will always be one step behind everything else. After all the objects have been updated we call "View.Update()" to swap the back buffer.
Finally, we have the AddObject function, which simply adds an object pointer to the Entities array and reserves another spot in the array for the next call. You'll notice this is a function and not a procedure. This is so you're able to both add an object to the game engine and call its Create procedure in the same line. Well, there it is, a really simple game engine. But wait! We're not done; we still have to make it do something! So let's move on and make the game engine do something. Everything up to this point has been written in the "Engine.t" Turing file in the accompanying zip archive. However, the next two sections will refer to "Objects.t" and "Game.t", spreading code across files makes things easier to edit and provides further encapsulation. Creating Game Elements Ok, it's all pretty straight forward from here; to define a new game entity you simply inherit Object then overwrite the abstract procedures by marking them as a "body procedure". When you inherit from the Object class you now have access to all of its variables regardless of their protection level (whether they are exported or not) and you can freely manipulate them. As well you can add new variables to the class, but be aware that you won't be able to access them externally.
The one I wrote for this tutorial simply draws a red block (loaded from an image, you'll see in the next section) and moves the block based on keyboard input. Pretty straight forward and there's not really much to explain. And there shouldn't be much to explain, making a new type of entity is as easy as that, the game engine handles everything else. All you have to do is add instances of the objects to the GameEngine class, which I will talk about next. Adding Game Elements Well, we've reached the final part of this long tutorial, adding instances of our game entities to the GameEngine class. This is just a matter of defining a pointer and initializing new instances with "new". Take a look at the "Game.t" file in the zip archive.
Once again, pretty straight forward. Here I show how the AddObject function works; you can use the value it returns to call the Create procedure on the same line. This about wraps up the tutorial. Conclusion I hope you've learned something from this tutorial, and I encourage you to play around with the code, not that it really does much. The generic object class we built in this tutorial doesn't really provide much functionality but I encourage you to add to it. Normally, the game engine would contain other things like collision checking, particles, other entities etc. I may write a second part to the tutorial which addresses making and loading levels, although I?m not sure if it can be done in Turing, at least to the level of automation I have achieved in other languages. Anyways, thanks for reading my tutorial and happy coding. |
Author: | Zampano [ Wed Jul 23, 2008 6:38 am ] |
Post subject: | Re: [Tutorial] Polymorphism and Game Engines |
Nice; you should have some bits. |
Author: | SNIPERDUDE [ Wed Jul 23, 2008 10:58 am ] |
Post subject: | RE:[Tutorial] Polymorphism and Game Engines |
Agreed. Good Tutorial. +bits |
Author: | Stove [ Sun Jul 27, 2008 12:19 am ] |
Post subject: | Re: [Tutorial] Polymorphism and Game Engines |
Glad you both liked the tutorial, and thanks for the bits ![]() |
Author: | cavetroll [ Sun Jul 27, 2008 2:19 am ] |
Post subject: | RE:[Tutorial] Polymorphism and Game Engines |
Wow. Nice tutorial, I didn't even know that this was possible in Turing. +bits Edit: Wow. I'm terrible at math. I was trying to get you to exactly 100 bits but I miscounted. Guess I'll just blame it on the hour. Oh well, you deserve them. |
Author: | Insectoid [ Sun Jul 27, 2008 3:18 pm ] |
Post subject: | RE:[Tutorial] Polymorphism and Game Engines |
Wow, I don't even know what half of those commands do! Very useful stuff to know, I guess. |
Author: | Stove [ Mon Jul 28, 2008 1:03 pm ] |
Post subject: | Re: [Tutorial] Polymorphism and Game Engines |
Once again, glad you both liked it, and thanks for the bits cavetroll! I'm planning on writing a second part soon, which will hopefully cover: deleting objects, collision checking (bounding box), menus, depth ordering (I'm trying to avoid the Turing sprite class altogether), various game "GUI" elements, maybe even a basic particle system. I won't be writing it for a while though, as I have a few other projects on the go that I want to finish first. |
Author: | SNIPERDUDE [ Tue Jul 29, 2008 12:10 am ] |
Post subject: | RE:[Tutorial] Polymorphism and Game Engines |
Cool, planing on creating a general Particle engine for my programmes. Including depth. |
Author: | TheFerret [ Sat Oct 11, 2008 3:05 pm ] |
Post subject: | RE:[Tutorial] Polymorphism and Game Engines |
Added to Wiki: Polymorphism_And_Game_Engines |
Author: | Zren [ Tue Dec 02, 2008 7:02 pm ] |
Post subject: | Re: [Tutorial] Polymorphism and Game Engines |
This is a crazy awesome tutorial, I can't wait for the collision checking part if you ever get around to it. Since I can't manage to get how to use it in an engine like this. Let alone find a way to have one object react to another. |
Author: | Flipmc [ Fri Jan 30, 2009 6:40 pm ] |
Post subject: | RE:[Tutorial] Polymorphism and Game Engines |
Sweet man, I could start a 2D RPG! But I might stick with text-base for now. |
Author: | saltpro15 [ Fri Jan 30, 2009 9:24 pm ] |
Post subject: | RE:[Tutorial] Polymorphism and Game Engines |
wow, great tutorial, have some bits, please do one with collision checking |
Author: | Stove [ Tue Feb 03, 2009 7:12 pm ] |
Post subject: | Re: [Tutorial] Polymorphism and Game Engines |
Thanks everyone ! ![]() For those who are interested, I started writing the second part of the tutorial over the weekend. It's hopefully going to cover a lot of topics (including collision checking), so I plan to break it into parts. I'm not sure if most of what I will be covering is going to be possible in Turing though. Its limited and clunky OOP capabilities are really hard to work with, so I may end up "resorting" to c++. Anyways, I hope to be finished the first part by next week. - Stove |