Quick viewing(Text Mode)

Implementation of a 2D Game Engine Using Directx 8.1

Implementation of a 2D Game Engine Using Directx 8.1

Science

Daniel Linds¨ath and Martin Persson

Implementation of a 2D Game Engine Using DirectX 8.1

Bachelor’s Project 2004:24

Implementation of a 2D Game Engine Using DirectX 8.1

Daniel Linds¨ath and Martin Persson

2006 The author(s) and Karlstad University

This report is submitted in partial fulfillment of the requirements for the Bachelor’s degree in Computer Science. All material in this report which is not our own work has been identified and no material is included for which a degree has previously been conferred.

Daniel Linds¨ath

Martin Persson

Approved, 2004-06-03

Advisor: Hannes Persson

Examiner: Donald F. Ross

iii

Abstract

This paper describes our game engine written in C++, using the DirectX libraries for graphics, sound and input. Since the engine is written using DirectX, an introduction to this system is given. The report gives a description of the structure of the game and the game kernel. Following this is a description of the graphics engine and its core components. The main focus of the engine is on the physics and how it is used in the game to simulate reality. Input is discussed briefly, with examples to show how it relates to the physics engine. Implementation of audio in the game engine is not described, but a general description of how sound is used in games is given. A theory for the basics of how artificial intelligence can be used in the engine is presented. The system for the architecture of the levels is described as is its connection to the graphics engine. The last section of the report is an evaluation and suggestions for what to do in the future. A user manual for the level editor is included as an appendix.

v Contents

1 Introduction 1 1.1 Problem ...... 1 1.2 Purpose ...... 2 1.3 Limitation ...... 2 1.4 Goal ...... 2 1.5 Disposition ...... 3

2 DirectX and COM 4 2.1 The DirectX Kernel ...... 4 2.2 HAL and HEL ...... 6 2.3 The Components of DirectX ...... 6 2.3.1 DirectDraw ...... 6 2.3.2 DirectSound ...... 8 2.3.3 DirectSound3D ...... 8 2.3.4 DirectMusic ...... 8 2.3.5 DirectInput ...... 8 2.3.6 DirectPlay ...... 9 2.3.7 ...... 9 2.3.8 DirectSetup ...... 9 2.3.9 DirectX Graphics ...... 9 2.3.10 DirectX Audio ...... 10 2.3.11 DirectShow ...... 10 2.4 COM ...... 10 2.4.1 The COM Objects ...... 11 2.4.2 GUID ...... 11 2.5 DirectX and COM ...... 12

vi 3 Game Engine Structure 13

4 The Kernel 16

5 Graphics Engine 18 5.1 Bitmaps ...... 18 5.2 Bitmap Object Blitter ...... 20

6 Physics 22 6.1 Newtonian Mechanics ...... 22 6.1.1 Movements — Acceleration and Inertia ...... 22 6.1.2 Drag ...... 23 6.1.3 Free-fall ...... 24 6.2 Physics Within the Game ...... 25 6.3 Collision Detect ...... 27 6.3.1 Running Through Walls ...... 27 6.3.2 The Bresenham Algorithm ...... 29

7 Input 32 7.1 Forces ...... 32 7.2 Impulses ...... 33

8 Sound and Music 34 8.1 Sound in the Engine ...... 34

9 The Basics of Artificial Intelligence 35

10 The Level System 36

11 Conclusion 38 11.1 Achievements ...... 38

vii 11.2 Evaluation ...... 39 11.3 Future Plans ...... 40

References 42

A User Manual for the Map Editor 43

B winconsole.cpp 45

C motor.h 48

D bob.h 52

E game.h 55 E.1 Terrain ...... 56 E.2 Character ...... 56 E.3 Enemy ...... 57 E.4 Player ...... 58 E.5 Sublevel ...... 58 E.6 Level ...... 59 E.7 Game ...... 59

F mapeditor.h 61

G Screenshot 64

viii List of Figures

2.1 “Classical” Programming vs. DirectX ...... 5 2.2 DirectX and Windows ...... 7 3.1 Module Overview ...... 13 3.2 Object Diagram of the Game Structure ...... 14 4.1 Game Kernel structure ...... 16 5.1 Bitmap Example ...... 18 5.2 BOB Inheritage ...... 21 6.1 Velocity Vector ...... 26 6.2 Collision Example ...... 28 6.3 Another Collision Example ...... 28 6.4 Line Approximations ...... 30 10.1 The Different Layers ...... 37 A.1 Empty Level Editor ...... 43 G.1 A Screen Shot of an Example Game ...... 64

ix

1 Introduction

According to the authors, the gaming industry of today focuses solely on 3D games, often with wondrous graphics as their main goal. This has had the effect that modern games seldom have any depth, story or “feel” to them. The authors think that this is a shame, and decided to create a 2D game engine in the hopes of returning some of the feel of the old games.

1.1 Problem

A 2D game engine is a relatively complex thing to design. The main problem is to make the physics in the game correspond — in a good looking way — to the objects on the screen, using the existing graphics engine BOB [1]. The engine will, except for the the graphics API, be built from scratch.

Problems that have to be solved is how to make the architecture of the levels1 be useful to the physics. A great part of the problem with the physics will be collision detection between the player and the map2 itself. The input handling using DirectInput will have to be integrated to the movement physics of the player. How to make the enemies in the game orientate themselves in the environment will also have to be solved. A level editor using the same map system as the game will also have to be implemented so that levels created using that editor can be loaded into the game. The main part of the work will be programming the engine itself, and parallel to the implementation write a documentation describing the engine.

1A level is an object containing a set of terrain, a number of enemies and events which one may interact with. 2The terrain parts of a level. Sometimes used interchangeably with level.

1 1.2 Purpose

The purpose of this dissertation is to create a fully working game engine that can be used to create two dimensional platform games using DirectX. The engine will also be the base that Martin will use when he creates his first commercial computer game.

1.3 Limitation

A fully functioning game engine is, of course, a massive project that can hardly be completed in the amount of time available for this paper. The authors have therefore decided to create the level system and the game physics and then make the rest of the details if there is enough time.

1.4 Goal

When this dissertation is complete the following shall be done:

• A well documented and working game engine API that allows programmers to create 2D games with a minimum amount of foundation coding, so that they may focus on the gaming experience.

• A good implementation design that will make it easy to add new features later.

• A working two dimensional physics engine.

• A useful level editor that can be used to create the maps of the game.

• A simple and general way to program the AI of the enemies in the game.

• A virtual class for enemies.

2 1.5 Disposition

Section 2 gives a shallow, technical introdction to DirectX and COM. These tools are then used in sections 5, 7 and 8. Section 3 shows how the modules of the game are connected and gives an introduction to sections 4 through 9. Section 4 gives a description of the game kernel which handles startup, exec- tution and shutdown of the game engine itself. Section 5 explains image formats, and relates back to the second section with DirectDraw. Sections 6 and 7 show how a player may alter the playing realm through input and physics. Section 6 also describes some of the issues related to physics in games. Sections 8 and 9 discusses sound and artificial intelligence, none of which have actually been implemented yet. Instead they show how an implementation could be used in the future and what to think about. Section 10 describes how the system for levels and maps works. This is the sys- tem that tells the graphics engine what to draw and where. The levels also contain all the information used by the physics engine, such as gravity and atmospheric density. Finally, Section 11 is a conclusion which summarizes the whole thesis.

3 2 DirectX and COM

The purpose of this chapter is to give the reader a brief introduction to the basic concepts of the DirectX Application Programming Interface3 (API) and Component (COM). The chapter comprises:

• An introduction to DirectX

• An introduction to COM

• How DirectX and COM relate

2.1 The DirectX Kernel

DirectX is an abstraction of many sub components that allows the programmer to utilize any hardware that is DirectX compatible. Rather than creating a module for each hardware manufacturer (as was common a few years ago), a programmer may use DirectX to get working code for virtually any home computer configuration. DirectX is a single component, controlling the communication with all hardware in a faster and more stable way than regular Windows components, such as Graphics Device Interface4 (GDI) and Media Control Interface5 (MCI), (see Figure 2.1) which are standard Windows libraries for graphics and sound. The functionality of DirectX is such that it gives the programmer close to direct control of the hardware. DirectX achieves this by using a multitude of libraries and drivers — written by both Microsoft and the companies who design and construct hardware. Microsoft defined a set of data structures and algorithms to be used by

3A by which a program can access services such as the file system or monitor. It is used to abstract underlying logic, thus enabling portability. 4The Windows standard COM object for graphics. 5The Windows standard COM object for sound.

4 Figure 2.1: “Classical” Programming vs. DirectX the hardware creators’ programmers when they make DirectX compatible drivers for their components. This way, the only functions that are being called are DirectX functions, and the application programmer has no need to know what happens at the backend.

With DirectX 8.0, Microsoft integrated DirectDraw and Direct3D into a single component; DirectX Graphics. DirectDraw and Direct3D still exist, but they are no longer updated. The same applies to DirectSound, DirectSound3D and DirectMusic, which are now bundled into DirectX Audio. A great advantage of this system is complete backwards compatibility; any program that works with old versions of DirectX will work with new versions. Thanks to the usage of COM there’s not even a need to recompile programs when a new version of DirectX is released. Another advantage is that when you learn one version of DirectX, you basically know them all. New versions don’t alter old functions, merely add more functionality.

5 2.2 HAL and HEL

Figure 2.2 shows a couple of things that have not been mentioned thus far: Hard- ware Abstraction Layer (HAL) and Hardware Emulation Layer (HEL). Their pur- pose is to fill any gaps in hardware drivers. If some hardware component does not support a certain function, HAL and HEL will take care of it. HAL is, as the name suggests, a layer that communicates directly with the hardware. DirectX makes sure that available hardware is used whenever possible, to minize the load on the central processing unit 6 (CPU). The HAL implementa- tions lie within the drivers of the hardware. When HAL cannot be used for a specific task, due to hardware restrictions, HEL will emulate hardware capabilities to let the CPU take care of the calculations instead. This results in slower, but working code, and is vital to ensure universal compatibility. Compared to the 80s, programmers have an easy job creating games with DirectX.

2.3 The Components of DirectX

Figure 2.2 shows how the components of DirectX are interconnected, below are semi detailed descriptions of each component.

2.3.1 DirectDraw

DirectDraw is the main rendering device of bitmap7 graphics. DirectDraw also controls the graphics memory, which is the main medium through which all graph- ics must go before it can be displayed on the monitor. DirectDraw more or less

6The part of a computer that does most of the data processing; the CPU and the memory form the central part of a computer, to which the peripherals are attached. 7The most basic of image formats, stores each pixel as three byte of data; one for each of the colours Red, Green and Blue.

6 Figure 2.2: DirectX and Windows

7 controlls the graphics card. DirectX 8.0 and above don’t use DirectDraw as a component in its own right, but runs everything through DirectX Graphics.

2.3.2 DirectSound

This component helps standardising sound playback. Before DirectSound existed, sound programming was black magic where every manufacturer sup- plied their own drivers and the game programmers had to make a routine for each card. Remember old games where you had to chose sound card, IRQ and DMA? Thanks to DirectX you don’t have to do that anymore.

2.3.3 DirectSound3D

The 3D version of DirectSound allows you to place sound sources in a room, the same way you do with regular 3D objects. When you move around in the room the sound will change according to your movements. DirectSound3D supports, among other things, reflection, refraction and the Doppler effect.

2.3.4 DirectMusic

The component handles the music in your games is called DirectMusic. Mainly MIDI8, MP39 and CD tracks are used.

2.3.5 DirectInput

DirectInput handles all the input from devices such as the keyboard, mouse or joystick. It supports Force Feedback10 . At the moment there’s no support for 8A standard for representing musical information in a digital format. MIDI does not use recorded sound for playback, but rather mathematical formulae for how each note should sound for every instrument. 9MPEG-1 layer 3. An audio compression standard that can compress CD-tracks about ten times with very little quality loss. 10A standard for input devices that allows the user to feel a fairly natural response from the game.

8 speech recognition or voice control, but this would be the logical place to put that when it arrives.

2.3.6 DirectPlay

This is the network communications component of DirectX. DirectPlay allows you to create abstract connections with other with an IP address through any medium. You don’t have to know much, if anything, about network program- ming to be able to use DirectPlay properly. There’s no need to understand the protocol stack, or know which socket to use. DirectPlay supports sessions and lobbies. A session is an ongoing network game and a lobby is a connection that you connect to inbetween games.

2.3.7 Direct3D

The 3D graphics part of DirectX is split into two subcomponents; Direct3D Re- tained Mode (Direct3DRM) and Direct3D Immediate Mode (Direct3DIM). RM is a basic high level system that is relatively simple, but slow. IM is a low level sys- tem that is alot more complicated, but also alot faster. The science of 3D graphics optimization is well outside the scope of this document.

2.3.8 DirectSetup

DirectSetup is used to simplify the installation of DirectX components. DirectX is very complex, and therefore hard to install manually.

2.3.9 DirectX Graphics

With version 8.0 of DirectX, Microsoft combined DirectDraw and Direct3D to enhance performance and allow 3D effects in a 2D environment. Both DirectDraw

9 and Direct3D still exist and work, but to call them you have to use the interface from before version 8.0.

2.3.10 DirectX Audio

As with DirectX Graphics, Microsoft combined the sound components Direct- Sound, DirectSound3D and DirectMusic into DirectX Audio. The old components still exist for backwards compatibility.

2.3.11 DirectShow

This is the component that is used for playing video in DirectX. It will automat- ically locate any and use it if it exists. This component is very useful since you don’t have to care about anything but loading the film and playing it on the monitor.

2.4 COM

Computer programs of today can contain millions of lines of code. Red Hat 7.1, for example, contains over 30 million lines of code [15]. The sheer size of this code requires a structured hierarchy and data abstraction to avoid chaos. COM, short for , is one solution to this problem. COM is designed to be modular, like pieces of Lego or microchips. They work the same way, no matter what you connect them to. They are all modular and they care only about what input they get, not what sent it to them. In the same way, COM doesn’t care what language is used to send it input, as long as it gets input it knows how to deal with. This modularity comes with a few nice advantages; It provides for easy re-implementation of a component — since any COM object with the same interface can replace another — and it allows components to be

10 programmed in different languages, thus giving the developers a chance to utilize the language that is best for any given task. Yet another step towards modularity comes from the fact that COM objects are compiled into Dynamically Linked (DLL) files which are loaded during execution rather than during compilation, this means that components can be exchanged without meddling anything with the main program.

2.4.1 The COM Objects

A COM object is a class that implements a number of interfaces used to commu- nicate with it. The most basic object implements the interface IUnknown which doesn’t really do anything. For an object to be useful, however, the programmer has to implement at least one interface of his own and add functionality to it. Since the objects are completely binary11, and have a uniform calling conven- tion, it doesn’t matter what they are coded in, nor does it matter what language they are called from. They will always behave predictably. One of the authors waits for the day when DirectX and COM are ported to Linux so games will be platform independent, whereas the other claims that this could already be the case if only developers used OpenGL12 and SDL 13

2.4.2 GUID

To create a COM object a Global Unique IDentifier (GUID) is needed. A GUID is a 128 bit long integer that is created by the . The integer is divided into a four byte word, three two byte words and six single byte words [5]. The whole GUID is always unique within the system and is used to distinquish

11As opposed to containing any code. 12Open Graphics Library. 13Simple DirectMedia Layer. The SDL implementation in Windows uses DirectX for input and sound.

11 objects. A GUID is assigned to a COM object, during runtime, by the operating system itself. The programmer doesn’t have to concern him- or herself with it. As mentioned earlier in this thesis, the authors won’t go into detail regarding the COM objects, but this introduction is included because DirectInput uses GUIDs to locate hardware (keyboards, mice, joysticks, hand controls etc).

2.5 DirectX and COM

DirectX comprises a large number of COM objects. These objects are located in DLL files that are loaded when a DirectX program is started. Once in the memory the DirectX program can begin to use their interfaces which in turn use their methods to manipulate data. When Microsoft created DirectX they had to offer more than efficient execution; The game programmers wanted the API to be as easy to use as possible. Since COM isn’t a very nice interface to work with, MS encapsulated about 90 % of all COM calls in DirectX functions, thus hiding the fact that it’s COM one has to deal with. Compiling a DirectX program requires a number of library files and associated header files. Each component in DirectX usually has a lib file and a header file, but these files don’t contain the actual COM object, but rather shells and references to the DLL files, which do. DirectX objects are almost exclusively called using a function pointer (or function reference). The value of this pointer is set during runtime, not compilation, and is yet another step to modularization and hardware independence.

12 3 Game Engine Structure

Figure 3.1 shows a simple overview of the modules used within the engine. The first step is initialization which then allows the main to take control and start executing game instructions. The main event loop — consisting of input handler, AI executioner, physics simulator and graphical engine — continues until the exit command is given by the user, most commonly by pressing the escape key.

Figure 3.1: Module Overview

The only purpose of the main event loop (also known as the Kernel) is to tell the other objects when it’s their turn to execute, and to make sure that each frame14 within the game takes place at its correct time. Input is handled by the Player object. DirectInput is called to check if any of the used keys are pressed, and variables are set with corresponding values.

14A frame is one image on the screen. When a game is played, a multitude of frames are shown every second to ensure smooth movements.

13 For example, if the left key is pressed, the variable walk force is set to a value appropriate for walking to the left. When this is done, the physics engine is called into action. The values set by the input are calculated into accellerations which then affect the velocities of the object in question (mainly the player character, but also weapons he might fire or other objects that he can move). After the player is done, the computer takes care of all of its own characters with artificial intelligence. This is similar to the input stage, but instead of reading from input devices such as a keyboard, the computer executes predefined AI functions for all of its characters. The AI physics is handled the same way as player physics. In fact, they’re most likely the same function, inherited from the Character class15.

Figure 3.2: Object Diagram of the Game Structure

Note in Figure 3.2 that Game, Level and Sublevel all contain the same player object. Also note that the pointers Fiender in Level and Level Fiender in Sublevel both point to the same memory area. Once the velocities have been set, the physics engine moves all the objects

15Enemy units can have uniquely implemented physics functions if they aren’t supposed to adhere to the normal laws of the world.

14 to their new positions and check for collisions. Collisions are treated depending on the objects that collide; a player colliding with a wall will simply stop, but characters colliding with bullets will take damage. After the objects have moved, they will be dispatched to the graphics engine where they are drawn on a surface which then replaces the image that is currently on the screen. It’s now time to check for new input and repeat until the program is terminated.

15 4 The Kernel

The kernel is the module of the game that keeps track of all other modules. It tells them when to execute and makes sure they’re all working in the right order. In the engine, the kernel consists of the object Game. Game has three member functions; Init, Main and Shutdown. Init is used to start DirectX and set state variables within the engine. Main is a simple state machine that keeps track of what level the player is currently in. Shutdown closes DirectX and deallocates all dynamic memory. The function Game Main() is repeatedly called from within WinMain()16 (see Appendix B). Each call to Game Main() represents a single frame update in the game (sometimes called a ‘tick’).

Figure 4.1: Game Kernel structure

Game Main() in turn calls the different modules that make up the game. Fig- ure 4.1 shows a simplifiied call tree with time increasing from left to right and, to a lesser extent, from top to bottom. Most of the individual blocks will be described in the following sections. The function is basically a finite state machine that chooses which sub event loop should be called. The object Game (see Appendix E.7) has member data

16the main function in a Windows program

16 to supervise the player and levels. One of the members is of type Level (see Appendix E.6), which is a master level with a number of sublevels (Appendix E.5). These sublevels contain the actual maps that the players can see and interact with. The Level object has a function called Playing Level(). The function acts like a state machine, deciding what sublevel to call. Playing Level() has to be called once for each frame, just like Game Main(). The sublevels have a method called Playing() which handles input and logic for the game. The sublevel also contains the enemies and events. Some of the enemies are local to the sublevel and will disappear/reappear when the player enters and exits the room, while others belong to the master Level object and can only be killed once. A good example of a similar system is Zelda II [10] where the castles are levels, and all the rooms one can enter are sublevels. The game logic and physics is implemented in the object Character, which inherits BOB and is inherited by Player and Enemy. The Player object has a pointer to the terrain in sublevel which is used when the player moves. It is not, in fact, the player that moves, but all the surrounding terrain and enemies that are moved around the player which always stays centered on the screen. Player and Enemy are fairly similar. The main difference is that where Player has the function Input() that makes calls to DirectInput to do what the player wants it to do, the Enemy class has the member AI() to simulate user input. Both classes use the function Logic() which handles basic collision detection and movement. Events, such as doors one can walk through, will be implemented on a case to case basis. These implementations will deal with special animations, sounds and possible movie sequences.

17 5 Graphics Engine

A graphics engine is the part of a game that simplifies the drawing of things on a screen. Using a graphics API such as DirectX or OpenGL directly is quite arduous with lots of repeated function calls and similar. The graphics engine used in this program is a rewritten version of Andr´e LaMothe’s engine described in [1] and [2]. The main difference is that this version is object oriented with classes as the main datatype, rather than structs. The central object is the Bitmap Object Blitter (BOB) (see Appendix ) which loads a bitmap and shows it on the screen.

5.1 Bitmaps

Bitmaps constitute the simplest form of . They consist of a matrix of numbers corresponding to colours.

Figure 5.1: Bitmap Example, courtesy of [6]

18 There are different versions of the bitmap format, among these are:

1 bit Also known as monochrome. Each value in the value matrix points to one of two colours in a small palette. These are usually black and white, but can be changed to other values.

8 bit Like the monochrome format, the values point to palette entries. The dif- ference is that the palette has room for 256 colours rather than just two.

16 bit Two bytes are used to represent the colour of each pixel. Each prime colour uses five bit each, so the format actually only uses 15 bit, not 16. 24 bit graphics can be converted to 16 bit by dividing each of the bytes with 8 and then appending the values to eachother in a two byte variable (col16bit = ((red8bit >> 3) << 10) + ((green8bit >> 3) << 5) + (blue8bit >> 3);).

24 bit Each pixel is made up of three bytes representing the colours red, green and blue. These prime colours are then combined, with values from 0 to 255, to make just about any colour possible.

Animations with bitmaps are accomplished by loading a number of images to the video memory and then switching between them rapidly. All these images are stored in the same bitmap which is partitioned into squares. The Bitmap class is used to read data from a file and is then used as an argument for loading graphics into a BOB. Look at the end of the first page of Appendix D for a class definition of the bitmap.

19 5.2 Bitmap Object Blitter

As mentioned previously, BOB is the central image component of this engine (See Appendix C and D). It is an object oriented version of the struct created by Andr´eLaMothe. BOB is an abstraction on top of DirectDraw and is designed to implement a more user friendly interface. The class uses DirectX by creating a DirectDraw object and two drawing surfaces which are used to make sure the drawing of a new frame is smooth. BOB takes care of the coordinates at which a bitmap will be drawn, what image should be shown, how quickly images should change and in what direction and velocity the object is moving. BOB also draws the image on the surface. When Draw() is called, BOB simply tells DirectDraw where to draw, and what to draw by using the Blt() method of a DirectDraw surface. Figure 5.2 shows how BOB is inherited by the other graphical components of the game. Character is the base of all movable objects and is inherited by Player and Enemy which are somewhat more specialised. Player is the object that handles input from a human player, and Enemy is an abstract class that is inherited by all computer controlled characters in the game. Enemy contains a virtual function AI(), which replaces the Input() function of the Player class. Rullare and Hoppare are the two enemy types used in the demo games created for this report.

20 Figure 5.2: BOB Inheritage

21 6 Physics

For a game to be satisfyingly realistic, it will have to use realistic physics. This means that the movements of characters, monsters, projectiles and simlar will have to adhere to the same laws of physics that act in the real world. This chapter will explain what laws will be needed, why they are needed, and how they apply to the objects in a game. Most formulae in this chapter are taken from [4] and [7]

1. Law of Inertia — If no force is acting on a body, it will remain at rest or move in a straight line at a constant velocity.

2. Law of Acceleration — The acceleration of a body is proportional and in the same direction as the resultant force that is acting on it.

3. Law of Action and Reaction — For any action (force) on a body, there is an equal and opposite reaction (reacting force).

6.1 Newtonian Mechanics

Newtonian, or classical, mechanics is the first part of physics most will learn in school. It deals with how forces interact with bodies and is based on Newton’s laws of motion:

6.1.1 Movements — Acceleration and Inertia

To alter the velocity of an object, in any direction, the application of a force is required. the change in velocity is proportional, and equal in direction, to the force according to the following: m a = F

22 Example code:

// Temporary velocity variable used to calculate the drag float tempvx = xv + walk force / mass;

6.1.2 Drag

When objects move through gases or fluids, the surrounding environment acts as a resistance to slow them down. There are two formulae to describe this resistive force:

Fv = −Cf (0.5 · ρ · vA) and

2 Fv = −Cf (0.5 · ρ · v A) where Fv is the viscous drag force, Cf is the fluid drag coefficient, v is the speed of the object, ρ is the density of the air, A is the cross section area of the moving object and the minus sign means that the force works in the opposite direction of the speed. The first formula is valid for objects moving slow enough not to cause any turbulence in the fluid or gas (currently not used in the game engine). The second is for fast moving objects that causes the flow streamlines surrounding it to become disturbed. Cf is usually not equal for these two formulae.

Example code:

float dragx = −(0.5 f ∗ sublev−>rho ∗ tempvx ∗ tempvx ∗ area ) ∗ Cd ∗ sign(tempvx);

23 6.1.3 Free-fall

Objects falling towards a large body will experience acceleration due to gravity, the general formula for this is

m · M F = G · r2 ¨m¨ · M ¨m¨a = G · r2 M a = G · r2 where F is the force acting on both bodies, G is Newton’s Universal Constant (gravitational constant), m is the mass of the smaller object, M is the mass of the large body and r is the distance between the center of graivty of both bodies. The vector a is the acceleration resulting from the force.

Example code:

// Check to see if object is on the ground i f ( On Ground ()&ON GROUND) { // the ground sets the gravity acceleration to 0 yv=0; } else { // is it touching the roof?

24 i f ( On Ground ( )&HITTING ROOF) { // set speed downwards to 1g/s yv=sublev−>GRAVITY; } else { // apply regular gravity yv+=sublev−>GRAVITY; } }

6.2 Physics Within the Game

The formulae described above are used in the game engine to make objects move as naturally as possible. The most basic is the gravitation that pulls all objects towards the ground, this is implemented using actual gravitational constants and masses for all objects and the resulting accelleration is stored in the Level objects. The next part is drag and user input. Both these instances cause force variables to be set to certain values. The drag calculations are performed with the actual area of the object in question, aswell as proper density and pressure values. When all forces have been correctly setup the physics engine will calculate the proper acceleration and alter the velocity variables xv and yv (Appendix D) accordingly. Figure 6.1 shows a player character with the velocity vector actually drawn next to it. This was only used in debug mode, the vector does not show in normal gameplay.

25 Figure 6.1: Velocity Vector

26 Example code:

// The actual velocity variable xv += ( int ) ( ( w a l k force + dragx) / mass);

Finally, there’s collision detection which prohibits objects from falling through the ground they’re being pulled towards. When an object touches a piece of ground, its velocity along the y axis is set to 0. When touching the ceiling, the same velocity vector is set to 0 and gravity kicks in. Collision with walls are handled the same way as with the ground, but it’s the veolcity along the x axis that is affected.

6.3 Collision Detect

There must be a way to prevent objects from moving through walls, floor and ceilings, as well as making sure that something happens when objects collide with eachother. The BOB object has a function which will check if two BOBs are overlapping. There is, however, another problem.

6.3.1 Running Through Walls

Keeping track of the speed and direction of a moving object in a game can easily be done with a velocity variable for each axis. For each frame, the position of the object will change as many pixels as the velocity variables state in each direction. Now, imagine a 20 pixel wide object moving at the speed 200 pixels per frame towards a wall (Fig. 6.2 a). The object is 50 pixels away from the wall, which is 50 pixels thick. Let’s move one frame forward; without collision detect, or with

27 collision detect only on the position where the object ends up, it would move through the wall and stop 80 pixels farther away (Fig. 6.2 b).

Figure 6.2: Collision Example

This is, of course, not acceptable in a game claiming to have a decent physics engine. Imagine how irritated a player (Fig. 6.3 a) would be if he went straight through a ledge he aimed for (Fig. 6.3 b), rather than stopping at it (Fig. 6.3 c). Or, possibly worse, imagine people running through all the walls from the beginning of a level to the end, cheating their way through a whole game.

Figure 6.3: Another Collision Example

A simple solution would be to limit the maximum speed, but that wouldn’t conform well with the idea of a realistic physics engine.

28 The solution chosen for this engine is to move the object one pixel at a time, following a line from its start location to the end point, and perform a collision detect on every step. This way a collision is discovered the first time a pixel is overlapping another, and proper actions can be taken. Of course, a good line approximation algorithm is essential to this approach.

6.3.2 The Bresenham Algorithm

Drawing exact lines on a computer is impossible, since lines are defined as an infinite number of zero-area points which lie between two end points. The smallest unit on a computer screen is the pixel, and its area is quite alot more than zero. Approximations on the other hand, are quite easy to draw if you use floating point operations:

void draw line ( int x1 , int y1 , int x2 , int y2 ) { int dx = x2 − x1 ; int dy = y2 − y1 ; float m = dy / dx ; for ( int x = x1 ; x < x2 ; x++) { int y = m ∗ x + y1 + 0 . 5 ; putpixel(x, y); } }

This, however is too slow to be acceptable in a game where speed is of the

29 essence. The solution is Bresenham’s midpoint algorithm [13] that will compute the point coordinates correctly, using only integer math.

Figure 6.4: Line Approximations

Figure 6.4 shows how pixel positions (the dots in the corners of the grid) are chosen depending on the true line’s (the line between the bottom left corner and the top right corner of the grid) position relative to a midpoint (short horizontal lines). If the blue line is below the current midline, we plot the next pixel to the right. If, however, the blue line is above the midline, we should plot above and to the right:

If ( BlueLine < Midpoint ) P l o t R i g h t P i x e l ( ) ; Else Plot AboveRight Pixel ( ) ;

Now to determine if a line is above or below a midline at the specific point. To do this we work a bit with the line funktion y = kx + m where we replace k with dy/dx: dy y = · x + m, dx dx · y = dy · x + dx · m,

30 0 = dy · x − dx · y + dx · m.

Any point (x, y) above the line will give a negative result, and a point below the line will give a positive result. We use this fact to define a function F such that F (x, y) = 2 · dy · x − 2 · dx · y + 2 · dx · m, the factor 2 will become evident shortly. When provided with a midpoint between the two possible next points the function F will return < 0 when the true line is below the midpoint and > 0 when the true line is above.

If we start at point (x1, y1) the next point will be either (x1 + 1, y1) or (x1 + 1, y1 + 1) so the reference midpoint will be (x1 + 1, y1 + 1/2). In order to determine which point is the best approximation we evaluate F for the midpoint:

 1  1 F x + 1, y + = 2 · dy · (x + 1) − 2 · dx · y + + 2 · dx · m 1 1 2 1 1 2

Since F (x1, y1) = 2 · dy · x1 − 2 · dx · y1 + 2 · dx · m = 0 we conclude that

  1   (( F x + 1, y + = 2 ·dy · x + 2 · dy − 2 ·dx · y − dx + (2 ·(d(x · m 1 1 2  1  1 = 2 · dy − dx

This is the initial decision variable and will be designated d0. Changes in midpoint values can be calculated using incR = F (Mx + 1, My) − F (Mx, My) = 2 · dy when the pixel is to the right and incUR = F (Mx + 1, My) − F (Mx, My) = 2 · dy − 1 · dx when it’s to the right and up. This means that all that has to be done to figure out what the next pixel should be is to add incR or incUR to the current di value and check if it is positive or negative. See [13] for more details.

31 7 Input

A player has to be able to interact with the game or the game will have no purpose whatsoever. The interaction between the player and the game is called input. So far, only keyboard input is supported by this game engine, but eventually it will also take care of mouse events and joysticks (including gamepads). Player input is handled by the Player class. The Input() function uses input functions through wrapper macros such as KEY DOWN():

#define KEYDOWN( vk code) ((GetAsyncKeyState(vk code ) & 0x8000) ? 1 : 0)

7.1 Forces

Input() sets physics variables such as walk force in the Player class and the Logic() function then calculates movements based on these values.

i f (KEYDOWN(VK LEFT) ) { // is he not already walking left i f ( State !=WALKING LEFT) { // Om stillast˚aende s¨att walk f o r c e t i l l w a l k b e g l e f t i f ( On Ground ()&ON GROUND ) w a l k f o r c e = WALK BEG LEFT; else

32 w a l k f o r c e = WALK BEG LEFT / 4 ; // set walking left State=WALKING LEFT; // set face left D i r e c t i o n=FACING LEFT; // set the walking left animation Set Animation(1) ; } }

7.2 Impulses

Only once does input alter a movement variable directly; on impulses17 such as jumping:

i f (KEYDOWN(VK SPACE) ) { i f ( On Ground ()&ON GROUND) yv=−50; // the initziation speed in the y axis from the jump }

17The change in momentum over a short period of time. The collision between too billiard balls is a good example of an impulse; the energies and momenta of both balls change momentarily.

33 8 Sound and Music

Even though sound isn’t implemented within this engine, it is an important enough subject to merit a brief discussion. Music and sound effects help giving depth and emotions to a gaming experience. Compare it to the sounds in a movie; the soundtrack can enhance or destroy the whole viewing exprience and the sound effects most certainly affect us. A good example is eerie music and sudden sound effects in horror movies. Old games rarely used digitally sampled sound — since this requires enormous amounts of memory for storage — instead, they used formats such as MIDI which use notation representations to play short sampled sounds, thus creating music. Later, with the advent of CDs, games began using CD tracks for their music. Eventually, HDD space became cheaper and wav-files were used. At that time the quality of both sound effects and music increased alot thanks to the capabilities of the sound format. Nowadays the use of compressed sound formats such as MP3 and OGG are gaining in popularity since they permit alot of sound to be stored with a small amount of space.

8.1 Sound in the Engine

As mentioned above, there currently is no sound support within the engine. Even- tually though, it will be, and should then use the existing DirectX Audio API within a simple wrapper class. Music will be part of the Sublevel class, possibly to be triggered by events (see Section 10). Ambient sounds will be part of sublevels to be played semi randomly and sound effects will be triggered by events and character actions.

34 9 The Basics of Artificial Intelligence

Since Artificial Intelligence is a whole science, this thesis won’t be able to do more than scratch the surface. The object Enemy has a member function calles AI() which replaces the Input() function of the Player object. Since the player orientates himself by looking at the screen, the enemies will have to orientate themselves in a similar fashion. The class Character, which Enemy inherits, has a reference to the terrain of the level and can use this to “see” what surrounds it. In his book [3], Steve Rabin includes an article that mentions how to implement intelligent maps with objects that send useful information to computer controlled characters. The game in question was The SimsTM, in which items that may provide food for the characters tell the characters about this if they come close. The characters then evaluate their current needs and wants, and if the want for food is high enough they will then approach the object and get something to eat. A similar feature in this game engine would be to let obstacles and hiding places tell the enemy characters that they may hide there, and if the enemies think that an ambush is appropriate, they will hide. A more advanced AI would make sure that the object is large enough to hide it completely, and try to stand as close to the center as possible to ensure protection. A simpler implementation of AI would be something that prevents enemies from falling over edges, perhaps by making them stop and change direction, or by making them look for platforms to jump to. None of the ideas above have been implemented yet, but they are all possible for future versions.

35 10 The Level System

A graphical game without a playing field of some kind doesn’t have much to offer and — unless the game in question is a board game — a game with only a single layout grows old rather quickly. Therefore this game engine comes with a level system and level editor to simplify the creation of new levels. A level comprises five different parts; foreground, ground, background, enemies and events. foreground, ground and background consist of Terrain objects. Enemies is an abstract class that is inherited to create moving objects which are controlled by artificial intelligence. The only implementation that has to be done is constructors, destructors, the AI function and, in some cases, the physics and logic functions. Events are areas on a map which trigger special occurances when the player enters them. Each event has to be implemented separately to work properly. Events currently use the Terrain class, but that will change in future versions. Objects are drawn in the following order; background, ground, events, enemies and foreground with background being drawn first and foreground last. The player is drawn concurrently with the enemies. Internally within the layers, objects are drawn in the order they are placed on the map. If a cloud were to be placed after a bush, the cloud would appear in front of the bush. Objects in background, ground and foreground have an attribute called Speed- Factor. By changing its value, the object’s speed relative to the player changes. A value of 0 makes the objects freeze on the screen and follow the player’s move- ments. It is not recommended to change the value of this attribute for objects in the ground layer. Collision detect is only performed on the ground layer, foreground and back- ground are solely for graphical purposes. Figure 10.1 shows how the layers are drawn on the screen. The long bar at the

36 bottom is part of the ground layer. The cloud and the left bush are obviously in the background since the player character is partially blocking them. The rightmost bush is in the foreground.

Figure 10.1: The Different Layers

The meta data which describes the objects of the maps are stored in arrays which are allocated and deallocated each time a player enters or exits a sublevel. DirectX was used for the level editor, simply because this made it easier to save the data to a format that could easily be read by the game engine. Any graphics API could have been used instead, with a little more work. Some basic instructions for how to use the map editor is shown when the program is executed.

37 11 Conclusion

The result of the dissertation is a fully working, although pretty basic, game engine with an accompanying level editor used for creating level meta data so one can make new levels. A good system that vill be used for the implementation of AI has been created. The system for keeping track of the terrain blocks in the game has been designed and implemented. The terrain blocks inherits the main graphics object, BOB as does the class where the physics is implemented — Character — which is then derived into Player and Enemy. The level system in the game uses the graphics engine in the sense that all objects on the map use types derived from the base class BOB, but the level objects themselves use no graphics except for debugging purposes. The Level object contains the character objects, Players and Enemies, which uses the physics and graphics engine. The Input part of the project has been implemented as macros that check if a certain key is pushed or released. Neither sound, AI nor networking has been implemented, due to lack of time.

11.1 Achievements

• A well documented and working game engine API that allows programmers to create 2D games with a minimum amount of foundation coding, so that they may focus on the gaming experience.

- Mainly succeded, what is missing in the engine is good grahics, sound effects, music and a good story. Once these elements exist, it could be called a complete platform game.

• A good implementation design that will make it easy to add new features later.

38 - Done. Is is easy to add new terrain types and new enemies to the game. The level editor uses a general system for the maps in the game that is easily modified. The only coding that needs to be done for each game is for the events, but that can’t possibly be avoided.

• A working two dimensional physics engine.

- Done. No bugs discovered so far.

• A useful level editor that can be used to create the maps of the game.

- It is useful and general. The level designer needs no knowledge of program- ming to use it.

• A simple and general way to program the AI of the enemies in the game.

- AI is never simple when it tries to be good, but the Enemy class has a virtual method called AI() that was not implemented in this tesis.

• A virtual class for enemies.

- Done, derived from character. There are no actual enemies of the class Enemy in the game since all enemies are inherited from the virtual Enemy class.

11.2 Evaluation

The end result is more than satisfactory, The collision detect system in the physics part of the engine uses a much more complex algorithm than was originaly planned and the system for maps has pixel precision for placing objects on maps. There has been no great problems throughout the work on the engine. The goals for the project were set before the implementation and design began so the work has been a more or less straight line from the beginning to the end.

39 Not all originally planned goals — namely network, sound and AI — were completed, due to lack of time. But this doesn’t mean they won’t ever be imple- mented, they have merely been postponed to a later project; a real game using the engine.

11.3 Future Plans

Sound and music haven’t played very large parts in the work so far. The very first sound related thing to do in the future, is to add support for sound objects. Music will be added to the Sublevels and possibly be directed by events. Sound effects will belong to the objects responsible for making noise. For example, the sound of gunfire will be stored in the character object that holds the gun. Ambient sounds can be stored in Sublevel and be played somewhat randomly to enhance the atmosphere of the map. This might include dripping water, the rush of wind in trees and sounds of distant traffic. Transient sounds may be handled by events and played when a player reaches a certain place on the map or performs a task. The graphical objects Terrain, Characters and its descendants are inherited from BOB. This isn’t a very good way to do things since it complicates relocation to another graphics library such as DirectX Graphics or OpenGL. It would be better if the graphical objects included a BOB or simliar as a data member. It would also be a good idea to implement characters as a number of smaller BOBs for different parts such as the main body, the weapon, armour etc. This allows the character to change appearance depending on equipment. This obviously assumes that each group of equipment will be fairly uniform so the same animations can be used for at least most of them to save memory and ease implementation. A nice side effect of such a system would be that it would allow separate collision detect and physics for different parts of the character. This would allow

40 for special vulnerable points where extra damage would be dealt, or part of the character acting as a mˆel´eeweapon. The map system wouldn’t notice this change since there’d still be a general collision function for the whole object which would be used to detect collisions between the terrain and character. The map editor has to be altered so objects can be moved “outwards” and “inwards” within a layer. As it is now, they have to be placed on the map in the correct order at once or they’ll be rendered incorrectly. This is a major drawback if one should chose to alter a map. Player and Enemy should be reimplemented somewhat to make them more similar to the kernel. A common interface used by the kernel would be a good idea, so it can simply store all moving objects in the same list, and call their respective input/AI, physics and graphics functions without discrimination.

41 References

[1] Andr´eLaMothe, Tricks of the Windows Game Programming GURUS, Sams, 2nd Edition, 2002.

[2] Andr´eLaMothe, Windows Spelprogrammering f¨orDUMMIES, IDG AB, ISBN 91-7241-006-X, 1999.

[3] Steve Rabin, AI Game Programming Wisdom, Jenifer Niles, 1st Edition, 2002.

[4] David M. Bourg, Physics for Game Developers, O’Reiley & Associates, 1st Edition, 2002.

[5] Unknown author, Component object model — Wikipedia, the free ency- clopedia, home page, http://en.wikipedia.org/wiki/Component object model, 2004-04-28.

[6] Unknown author, Raster graphics — Wikipedia, the free encyclopedia, home page, http://en.wikipedia.org/wiki/Bitmap, 2004-05-14.

[7] Carl Nordling and Jonny Osterman,¨ Physics Handbook for Science and Engi- neering, Studentlitteratur, Lund, 6th Edition, 1999.

[8] J. M. Meriam and L. G. Kraige, Engineering Mechanics Statics SI version, Wiley, 5th Edition, 2003.

[9] J. M. Meriam and L. G. Kraige, Engineering Mechanics Dynamics SI version, Wiley, 5th Edition, 2003.

[10] Zelda II: The Adventure of Link, Nintendo, 1988.

[11] Robert A. Adams, Calculus, Addison Wesley, 4th Edition, 1998.

[12] Bjarne Stroustrup, The C++ Programming Language, Addison Wesley, Spe- cial Edition, 2000.

[13] Hexar, Drawing Lines — The Bresenham Algorithm, Graphics Tutorial, home page, http://gamedev.cs.colorado.edu/tutorials/Bresenham.pdf, 2004-05-10.

[14] Charles Petzold, Programming Windows, Microsoft Press, 5th Edition, 1998.

[15] David A. Wheeler, More Than a Gigabuck: Estimating GNU/Linux’s Size, home page, http://www.dwheeler.com/sloc/redhat71-v1/redhat71sloc.html, 2004-05-30.

42 A User Manual for the Map Editor

The level editor isn’t exactly user friendly, but all functionality is described in a text field on the left hand side of the monitor. Some debuggning information is still printed. The screen is partitioned into two surfaces; edit area and toolbox. The edit area is the actual map as it will look in the game and the toolbox contains all the objects that can be placed on the level. Figure A.1 shows what the editor looks like before any objects have been placed on the edit area.

Figure A.1: Empty Level Editor

To begin with, ignore the blue doll. To place an object on the map, left click

43 the object in question in the toolbox and then left click on the edit area where you want it placed. To move the object to another place, use the arrow keys. O and P are used iterate the list of placed objects. The space key is used to change between terrain, enemies and events. To specify the terrain layer, use the keys 0, 1 and 2. To make objects move faster or slower than the player, K and L are used for changing the speed factor. The default value is 1, which means that object is stationary on the map, this is the best value to use for most objects. A value less than 1 makes the object move slower than the player (appearing to be farther away from the “camera”), and a higher value makes it move faster (therefore close to the “camera”). Even the objects in the ground layer can have their speed factor altered, but this isn’t advisable since it would look rather strange. The view is changed by using the arrow keys when no object is marked. The speed facter isn’t used when moving around in the editor, only within the game itself. Press S to save the map. It will be called level00.ban and placed in the same folder as the map editor. To open the map level00.ban in the editor, press D.

44 B winconsole.cpp

#define WIN32 LEAN AND MEAN #define INITGUID

#include // include important windows stuff #include #include #include #include // include important C/C++ stuff #include #include #include #include #include #include #include #include #include #include

#include ”ddraw . h” // directX includes #include ” dinput . h” // directX includes #include ”dsound . h” // directX includes

#include ”game . h” // My Game Engine

// DEFINES ////////////////////////////////////////////////////////////////////

// defines for windows #define WINDOW CLASS NAME ”WINXCLASS” // class name

#define WINDOW WIDTH 64 // size of window #define WINDOW HEIGHT 48

// GLOBALS ////////////////////////////////////////////////////////////////////

HWND main window handle=NULL; // pointer to toe the window handle HINSTANCE m a i n instance=NULL; // pointer to the instance

/////////////////////////////////////////////////////////////////////////////// // STANDARD WINDOW FUNCTIONS ////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

LRESULT CALLBACK WindowProc (HWND hwnd , UINT msg , WPARAM wparam , LPARAM lparam ) { // this is the main message handler of the system

PAINTSTRUCT ps ; // used in WM PAINT HDC hdc ; // handle to a device context

// what is the message switch ( msg ) { case WMCREATE: { // do initialization stuff here

45 return ( 0 ) ; } break ;

case WM PAINT: { // start painting hdc=BeginPaint(hwnd,&ps) ;

// end painting EndPaint(hwnd,&ps) ; return ( 0 ) ; } break ;

case WM DESTROY: { // kill the application PostQuitMessage(0) ; return ( 0 ) ; } break ;

default : break ; } // end switch

// process any messages that we didn’t take care of return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc

/////////////////////////////////////////////////////////////////////////////// int WINAPI WinMain( HINSTANCE hinstance , HINSTANCE hprevinstance , LPSTR lpcmdline , int ncmdshow ) { // this is the winmain function

WNDCLASS w i n c l a s s ; // this will hold the class we create HWND hwnd ; // generic window handle MSG msg ; // generic message HDC hdc ; // generic dc PAINTSTRUCT ps ; // generic paintstruct

// first fill in the window class stucture winclass.style =CS DBLCLKS |CS OWNDC|CS HREDRAW| CS VREDRAW; winclass.lpfnWndProc = WindowProc; winclass.cbClsExtra =0; winclass.cbWndExtra =0; winclass.hInstance =hinstance; winclass.hIcon =LoadIcon(NULL, IDI APPLICATION) ; winclass.hCursor = LoadCursor(NULL, IDC ARROW) ; winclass .hbrBackground = (HBRUSH ∗)GetStockObject(BLACK BRUSH) ; winclass.lpszMenuName = NULL; winclass .lpszClassName = WINDOW CLASS NAME;

// register the window class i f (! RegisterClass(&winclass)) return ( 0 ) ;

// create the window, note the use of WS POPUP i f ( ! ( hwnd=CreateWindow (WINDOW CLASS NAME, // c l a s s

46 TITLE , // title of the window WS POPUP| WS VISIBLE , 0 ,0 , // x , y WINDOW WIDTH, // width WINDOW HEIGHT, // h e i g h t NULL, // handle to parent NULL, // handle to menu hinstance , // i n s t a n c e NULL) ) ) // creation parms return ( 0 ) ;

// save the window handle and instance in a global pointer main window handle = hwnd; m a i n instance = hinstance;

Game Spel ; // perform all game console specific initialization Spel . Game Init ( ) ;

// enter main event loop while ( 1 ) { i f (PeekMessage(&msg,NULL,0 ,0 ,PM REMOVE) ) { // test if this is a quit i f (msg . message==WM QUIT) break ;

// translate any accelerator keys TranslateMessage(&msg) ;

// send the message to the window proc DispatchMessage(&msg) ; } // end i f

// main game processing goes here Spel . Game Main ( ) ;

} // end w h i l e

// shutdown game and release all resources Spel . Game Shutdown() ;

// return to Windows like this return ( msg . wParam) ;

} // end WinMain

///////////////////////////////////////////////////////////////////////////////

47 C motor.h

/∗======; ∗ ∗ Copyright (C) 2004 Martin Persson. Directly stolen from Andr´e LaMothe. ∗ ∗ File: motor.h ∗ Content: Game Engine include file ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/

#ifndef m o t o r h #define m o t o r h

// DEFINES ////////////////////////////////////////////////////////////////////

// default screen size #define SCREEN WIDTH 1600 // size of screen #define SCREEN HEIGHT 1200 #define SCREEN BPP 8 // bits per pixel

// basic unsigned types typedef unsigned short USHORT; typedef unsigned short WORD; typedef unsigned char UCHAR; typedef unsigned char BYTE;

#define MAX SOUNDS 64 // max number of sounds in system at once

#define SOUND NULL 0 #define SOUND LOADED 1 #define SOUND PLAYING 2 #define SOUND STOPPED 3

// voc file defines #define NVB SIZE 6 // size of new voice block in bytes

// screen transition commands #define SCREEN DARKNESS 0 // fade to black #define SCREEN WHITENESS 1 // fade to white #define SCREEN SWIPE X 2 // do a horizontal swipe #define SCREEN SWIPE Y 3 // do a vertical swipe #define SCREEN DISOLVE 4 // a pixel disolve #define SCREEN SCRUNCH 5 // a square compression #define SCREEN BLUENESS 6 // fade to blue #define SCREEN REDNESS 7 // fade to red #define SCREEN GREENNESS 8 // fade to green

// MACROS /////////////////////////////////////////////////////////////////////

// these read the keyboard asynchronously #define KEYDOWN( vk code) ((GetAsyncKeyState(vk code) & 0x8000) ? 1 : 0) #define KEY UP( vk code) ((GetAsyncKeyState(vk code) & 0x8000) ? 0 : 1)

// initializes a direct draw struct #define DD INIT STRUCT( d d s t r u c t ) {memset(&ddstruct ,0 , s i z e of (ddstruct)); \ ddstruct .dwSize=s i z e of (ddstruct); } // sets the volyme to 0−100 whitout crapy logaritms #define DSVOLUME TO DB( volume ) ( (DWORD) ( −30∗(100 − volume ) ) )

// TYPES //////////////////////////////////////////////////////////////////////

48 // this holds a single sound typedef struct pcm sound typ { LPDIRECTSOUNDBUFFER d s b u f f e r ; // the ds buffer containing the sound int s t a t e ; // state of the sound int r a t e ; // playback rate int s i z e ; // size of sound int i d ; // id number of the sound } pcm sound , ∗ pcm sound ptr ;

// PROTOTYPES /////////////////////////////////////////////////////////////////

// DirectDraw functions int DD Init ( int width , int height , int bpp ) ; int DD Shutdown ( void ); LPDIRECTDRAWCLIPPER DD Attach Clipper (LPDIRECTDRAWSURFACE lpdds , int num rects , LPRECT c l i p l i s t ) ; LPDIRECTDRAWSURFACE DD Create Surface ( int width , int height , int mem flags ) ; int DD Flip ( void ); int DD Wait For Vsync ( void ); int DD F i l l S u r f a c e (LPDIRECTDRAWSURFACE lpdds , int c o l o r ) ; UCHAR ∗ DD Lock Surface (LPDIRECTDRAWSURFACE lpdds , int ∗ l p i t c h ) ; int DD Unlock Surface (LPDIRECTDRAWSURFACE lpdds , UCHAR ∗ s u r f a c e b u f f e r ) ; UCHAR ∗ DD Lock Primary Surface ( void ); int DD Unlock Primary Surface ( void ); UCHAR ∗ DD Lock Back Surface ( void ); int DD Unlock Back Surface ( void );

// general utility functions DWORD Get Clock ( void ); DWORD S t a r t C l o c k ( void ); DWORD Wait Clock(DWORD count ) ; int C o l l i s i o n T e s t ( int x1 , int y1 , int w1 , int h1 , int x2 , int y2 , int w2 , int h2 ) ; int Color Scan ( int x1 , int y1 , int x2 , int y2 , UCHAR s c a n start , UCHAR scan end , UCHAR ∗ s c a n b u f f e r , int s c a n l p i t c h ) ;

// graphics functions int Draw Clip Line ( int x0 , int y0 , int x1 , int y1 ,UCHAR color , UCHAR ∗ d e s t b u f f e r , int l p i t c h ) ; int C l i p L i n e ( int &x1 , int &y1 , int &x2 , int &y2 ) ; int Draw Line ( int xo , int yo , int x1 , int y1 , UCHAR c o l o r ,UCHAR ∗ v b s t a r t , int l p i t c h ) ; int Draw Pixel ( int x , int y , int c o l o r ,UCHAR ∗ v i d e o b u f f e r , int l p i t c h ) ; int Draw Rectangle ( int x1 , int y1 , int x2 , int y2 , int c o l o r ,LPDIRECTDRAWSURFACE lpdds ) ; int S c r e e n Transition( void ); void HLine ( int x1 , int x2 , int y , int c o l o r , UCHAR ∗ v b u f f e r , int l p i t c h ) ; void VLine ( int y1 , int y2 , int x , int c o l o r , UCHAR ∗ v b u f f e r , int l p i t c h ) ; void S c r e e n Transitions( int e f f e c t , UCHAR ∗ v b u f f e r , int l p i t c h ) ;

// palette functions int S e t P a l e t t e E n t r y ( int c o l o r i n d e x , LPPALETTEENTRY c o l o r ) ; int Ge t Pa l e tt e En t r y ( int c o l o r i n d e x , LPPALETTEENTRY c o l o r ) ; int Load Palette From File ( char ∗ filename , LPPALETTEENTRY p a l e t t e ) ; int S a v e P a l e t t e T o F i l e ( char ∗ filename , LPPALETTEENTRY p a l e t t e ) ; int S a v e P a l e t t e (LPPALETTEENTRY s a v p a l e t t e ) ; int S e t P a l e t t e (LPPALETTEENTRY s e t p a l e t t e ) ; int Ro tate Colo rs ( int s t a r t i n d e x , int c o l o r s ) ; int B l i n k C o l o r s ( void );

49 // gdi functions int Draw Text GDI( char ∗ text , int x , int y ,COLORREF c o l o r , LPDIRECTDRAWSURFACE lpdds ) ; int Draw Text GDI( char ∗ text , int x , int y , int c o l o r , LPDIRECTDRAWSURFACE lpdds ) ;

// error functions int O pen Erro r Fi le ( char ∗ f i l e n a m e ) ; int C l o s e E r r o r F i l e ( void ); int Write Error ( char ∗ string, ...);

// sound int Load VOC( char ∗ f i l e n a m e ) ; int Load WAV( char ∗ filename , int c o n t r o l f l a g s=DSBCAPS CTRLPAN|DSBCAPS CTRLVOLUME| DSBCAPS CTRLFREQUENCY) ; int Replicate Sound ( int s o u r c e i d ) ; int Play Sound ( int id , int f l a g s =0, int volume=0, int r a t e =0, int pan=0) ; int Stop Sound ( int i d ) ; int Stop All Sounds ( void ); int DSound Init ( void ); int DSound Shutdown ( void ); int Delete Sound ( int i d ) ; int D e l e t e A l l S o u n d s ( void ); int Status Sound ( int i d ) ; int Set Sound Volume ( int id , int v o l ) ; int Set Sound Freq ( int id , int f r e q ) ; int Set Sound Pan ( int id , int pan ) ;

// in put int D I n p u t I n i t ( void ); void DInput Shutdown ( void ); int DI I n i t J o y s t i c k ( int min x=−256, int max x=256 , int min y=−256, int max y=256) ; int DI Init Mouse ( void ); int DI Init Keyboard ( void ); int DI Read Joystick ( void ); int DI Read Mouse ( void ); int DI Read Keyboard ( void ); void DI R e l e a s e J o y s t i c k ( void ); void DI Release Mouse ( void ); void DI Release Keyboard ( void );

// EXTERNALS ////////////////////////////////////////////////////////////////// extern FILE ∗ f p e r r o r ; // general error file extern LPDIRECTDRAW lpdd ; // dd o b j e c t extern LPDIRECTDRAWSURFACE lpddsprimary ; // dd primary surface extern LPDIRECTDRAWSURFACE lpddsback ; // dd back surface extern LPDIRECTDRAWPALETTE lpddpal ; // a pointer to the // created dd palette extern LPDIRECTDRAWCLIPPER l p d d c l i p p e r ; // dd clipper extern PALETTEENTRY p a l e t t e [ 2 5 6 ] ; // color palette extern PALETTEENTRY s a v e palette [256]; // used to save palettes extern DDSURFACEDESC ddsd ; // a direct draw surface // description struct extern DDBLTFX d d b l t f x ; // used to fill extern DDSCAPS ddscaps ; // a direct draw surface // capabilities struct extern HRESULT ddrval ; // result back from dd // c a l l s

50 extern UCHAR ∗ p r i m a r y b u f f e r ; // primary video buffer extern UCHAR ∗ b a c k b u f f e r ; // secondary back buffer extern int p r i m a r y l p i t c h ; // memory line pitch extern int b a c k l p i t c h ; // memory line pitch extern DWORD s t a r t c l o c k c o u n t ; // used for timing

// these defined the general clipping rectangle extern int m i n c l i p x , // clipping rectangle max clip x , m i n c l i p y , ma x cli p y ;

// these are overwritten globally by DD Init ( ) extern int screen width , // width of screen s c r e e n h e i g h t , // height of screen screen bpp ; // bits per pixel extern LPDIRECTSOUND l p d s ; // interface pointer extern DSBUFFERDESC dsbd ; // directsound description extern DSCAPS dscaps ; // directsound caps extern HRESULT d s r e s u l t ; // general directsound result extern DSBCAPS dsbcaps ; // directsound buffer caps extern LPDIRECTSOUNDBUFFER lpdsbprimary ; // the primary mixing buffer // the array of secondary sound buffers extern pcm sound sound fx [MAX SOUNDS] ; extern WAVEFORMATEX pcmwf ; // generic waveformat structure

// globals extern LPDIRECTINPUT8 l p d i ; // dinput object extern LPDIRECTINPUTDEVICE8 l p d i k e y ; // dinput keyboard extern LPDIRECTINPUTDEVICE8 lpdimouse ; // dinput mouse extern LPDIRECTINPUTDEVICE8 l p d i j o y ; // dinput joystick extern LPDIRECTINPUTDEVICE2 l p d i j o y 2 ; // dinput joystick extern GUID joystickGUID; // guid for main joystick extern char joyname[80]; // name of joystick

// these contain the target records for all di input packets extern UCHAR k e y b o a r d state[256]; // contains keyboard state table extern DIMOUSESTATE mouse state ; // contains state of mouse extern DIJOYSTATE j o y s t a t e ; // contains state of joystick extern int j o y s t i c k f o u n d ; // tracks if stick is plugged in

#endif // m o t o r h

51 D bob.h

/∗======; ∗ ∗ Copyright (C) 2004 Martin Persson. Directly stolen from Andre LaMothe. ∗ ∗ F i l e : bob . h ∗ Content: Bitmap Objekt Blitter include file ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/

// watch for multiple inclusions #ifndef b o b h #define b o b h

// DEFINES ////////////////////////////////////////////////////////////////////

// defines for Bobs #define BOB STATE DEAD 0 // this is a dead bob #define BOB STATE ALIVE 1 // this is a live bob #define BOB STATE DYING 2 // this bob is dying #define BOB STATE ANIM DONE 1 // done animation state #define MAX BOB FRAMES 64 // maximum number of bob frames #define MAX BOB ANIMATIONS 16 // maximum number of animation // s e q u e c e s #define BOB ATTR SINGLE FRAME 1 // bob has single frame #define BOB ATTR MULTI FRAME 2 // bob has multiple frames #define BOB ATTR MULTI ANIM 4 // bob has multiple animations #define BOB ATTR ANIM ONE SHOT 8 // bob will perform the animation // once #define BOB ATTR VISIBLE 16 // bob is visible #define BOB ATTR BOUNCE 32 // bob bounces off edges #define BOB ATTR WRAPAROUND 64 // bob wraps around edges #define BOB ATTR LOADED 128 // the bob has been loaded #define BOB ATTR CLONE 256 // the bob is a clone

// bitmap defines #define BITMAP ID 0x4D42 // universal id for a bitmap #define BITMAP EXTRACT MODE CELL 0 #define BITMAP EXTRACT MODE ABS 1

// this builds a 16 bit color value #define RGB16BIT(r,g,b) ((b%32) + ((g%32) << 5) + ( ( r %32) << 10) )

// bit manipulation macros #define SET BIT(word, bit flag) ((word)=((word) | ( b i t f l a g ) ) ) #define RESET BIT(word, bit flag) ((word)=((word) & (˜bit f l a g ) ) )

// class deffinitions /////////////////////////////////////////////////////////

// Bitmap typedef class Bitmap { p u b l i c : // this contains the bitmapfile header BITMAPFILEHEADER b i t m a p f i l e h e a d e r ; // this is all the info including the palette BITMAPINFOHEADER bitmapinfoheader ; // we will store the palette here

52 PALETTEENTRY p a l e t t e [ 2 5 6 ] ; // this is a pointer to the data UCHAR ∗ b u f f e r ;

Bitmap ( void ); int Flip Bitmap (UCHAR ∗image , int b y t e s p e r l i n e , int h e i g h t ) ; int Load File ( char ∗ f i l e n a m e ) ; int Unload File ( void );

} Bitmap File , ∗ Bitmap File Ptr ;

// Bob typedef c l a s s Bob // the Bitmap Object Blitter class Bob { p r o t e c t e d : // the bitmap images DD surfaces LPDIRECTDRAWSURFACE images [MAX BOB FRAMES] ; // the surface to draw on LPDIRECTDRAWSURFACE ∗ Destination S u r f a c e ;

p u b l i c : LPDIRECTDRAWSURFACE∗ G e t Destination S u r f a c e ( void ) {return (Destination S u r f a c e ) ; } LPDIRECTDRAWSURFACE∗ Get images ( void ) {return ( images ) ; }

p r o t e c t e d : int s t a t e ; // the state of the object (general) int a n i m s t a t e ; // an animation state variable, up to you int a t t r ; // attributes pertaining to the object (general) int x , y ; // position bitmap will be displayed at int xv , yv ; // velocity of object int width, height; // the width and height of the bob int w i d t h f i l l ; // internal, used to force 8∗ x wide surfaces int c o u n t e r 1 ; // general counters int c o u n t e r 2 ; int max count 1 ; // general threshold values; int max count 2 ; int v a r s I [ 1 6 ] ; // stack of 16 integers f l o a t varsF [ 1 6 ] ; // stack of 16 floats int c u r r f r a m e ; // current animation frame int num frames ; // total number of animation frames int c u r r a n i m a t i o n ; // index of current animation int anim counter ; // used to time animation transitions int anim index ; // animation element index int anim count max ; // number of cycles before animation int ∗ animations [MAX BOB ANIMATIONS ] ; // animation sequences

p u b l i c : // Bob metods Bob( int x , int y , int width , int height , int num frames , int a t t r , int mem flags ,LPDIRECTDRAWSURFACE ∗ destination s u r f a c e ) ; virtual ˜Bob( void ); Bob( void ); int Draw( void ); int Draw Scaled ( int swidth , int s h e i g h t ) ; int Load Frame(Bitmap File Ptr bitmap , int frame , int cx , int cy , int mode) ; int Animate ( void ); int S c r o l l ( void ); int Move( void ); int Load Animation ( int Anim index , int Num frames , int ∗ sequence ) ;

53 int Set Pos ( int X, int Y); int Set Anim Speed ( int speed ) ; int Set Animation ( int Anim index ) ; int S e t V e l ( int Xv , int Yv) ; int Hide ( void ); int Show( void ); int Collision(Bob ∗bob2 ) ; Bob(Bob ∗ b o b s r c ) ; } ∗ Bob ptr ;

#endif // b o b h

54 E game.h

/∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ ∗ Copyright (C) 2004 Martin Persson. All rigths reserved. ∗ ∗ File: game.h ∗ Content: Main Game include file ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/

// watch for multiple inclusions #ifndef game h #define game h

// INCLUDES /////////////////////////////////////////////////////////////////// #include ”bob . h”

// DEFINES ////////////////////////////////////////////////////////////////////

#define TITLE ” Martins Spelmotor ” // Title of the window // terrain layertype defines to keep track of what you are doing #define BACKGROUND 0 #define GROUND 1 #define FOREGROUND 2

// only used for the ground layer of terran to indicate that pixelscan should // be used insted of the ordinery Bob::Collision #define TERRAIN TYPE NON SQUARE 1

#define NUM ORIGINAL GROUND 6 #define NUM ORIGINAL ENEMIES 2 #define NUM EVENT TYPES 1 #define HOPPARE 0 #define RULLARE 1

// character defines #define STANDING STILL 0 #define WALKING RIGHT 1 #define WALKING LEFT 2

#define FACING LEFT 1 #define FACING RIGHT 2

#define IN FREE AIR 0 #define ON GROUND 1 #define HITTING ROOF 2 #define ON LEFT WALL 4 #define ON RIGHT WALL 8 #define HITTING UP LEFT CORNER 16 #define HITTING UP RIGHT CORNER 32 #define HITTING DOWN LEFT CORNER 64 #define HITTING DOWN RIGHT CORNER 128

// devierd eneny defines #define HOPPARE ANIMATION 0 #define ROLL RIGHT 0 #define ROLL LEFT 1

/////////////////////////////////////////////////////////////////////////////// // OBJECT DEFINES /////////////////////////////////////////////////////////////

55 /////////////////////////////////////////////////////////////////////////////// E.1 Terrain

// TERRAIN CLASS ////////////////////////////////////////////////////////////// typedef class Terrain:public Bob { p r o t e c t e d : int T e r r a i n Attributes; p u b l i c : // used to identify what type of original terrain it was cloned from // so the filename can be saved in the ∗ . ban f i l e int Type Index ;

double t x , t y ; double t xv , t yv ; // used to make the ForeGround and BackGround move faster or slower // than the player double SpeedFactor ;

void Set Type ( int t y p e a r g ) ; void Set SpeedFactor( double SpeedFactor arg ) ; void Set Pos ( int x arg , int y arg ) ; int Move( void ); void Move( int X, int Y);

Terrain ( int X, int Y, int Width , int Height , int Num frames , int Attr , int Mem flags ,LPDIRECTDRAWSURFACE ∗ destination s u r f a c e ) ; ˜ Terrain ( void ); Terrain(Terrain ∗ t e r r a i n s r c ) ; } ∗ T e r r a i n p t r ; E.2 Character

// CHARACTER CLASS //////////////////////////////////////////////////////////// // ska senare ¨arvas ner till en underklass f¨or spelare och en f¨or varje fiende typedef class Character:public Bob { // this is where the physics engine is implemented p r o t e c t e d : // attrubutes int Sty ,Fys,Smi,Int ,Psy,Kar,Sto; // s k i l l s //jag l¨agger till mer sen! // used to know what direction the player is faceing int D i r e c t i o n ; // used to know what the player is doing int State ; // pointer to the ground in the sublevel T e r r a i n p t r ∗∗Ground ; // the size of the map in the sublevel int ∗ T e r r a i n S i z e ; // the reference T e r r a i n ptr Referencepoint; void Move Level ( int x , int y ) ; // only used by the player inline bool Ground C o l l i s i o n ( void );

int A n t a l H a n d e l s e r i S u b l e v e l ; T e r r a i n p t r ∗ S u b l e v e l E v e n t s ;

// These values are used for the physics

56 int mass ; f l o a t area ; f l o a t Cd ; f l o a t w a l k f o r c e ;

p u b l i c : S u b l e v e l p t r sublev ;

void Move( int dx , int dy ) ;

Character ( int X, int Y, int Width , int Height , int Num frames , int Attr , int Mem flags ,LPDIRECTDRAWSURFACE ∗ destination s u r f a c e ) ; virtual ˜Character( void ); Character() :Bob() {} // used for cloneing of enemies int Collision(Terrain p t r Block ) ; inline bool Collision v 1 5 ( T e r r a i n p t r Block ) ; // returnvalue depends on where the character is int On Ground ( void ); void Set Ground(Terrain p t r ∗ Global Ground [ ] , int s i z e [ ] ) ; void S e t Referencepoint(Terrain ptr Reference);

void S e t S u b l e v e l Events(Terrain p t r ∗ h a n d e l s e a r g , int a n t a l handelser);

} ∗ C h a r a c t e r p t r ; E.3 Enemy

// ENEMY CLASS //////////////////////////////////////////////////////////////// typedef class Enemy:public Character { // this is the enemy class p r o t e c t e d : p u b l i c : Enemy( int X, int Y, int Width , int Height , int Num frames , int Attr , int Mem flags ,LPDIRECTDRAWSURFACE ∗ destination s u r f a c e ) ; Enemy() : Character() {} // used for cloneing of enemies virtual ˜Enemy( void ); v i r t u a l void I n i t ( void ); v i r t u a l void Enemy Move ( void ); v i r t u a l void AI( void ); // motsvarar input i player v i r t u a l void Logic ( void ); } ∗Enemy ptr ; typedef class Rullare:public Enemy { p r o t e c t e d : inline bool Reached Right Edge ( void ); inline bool Reached Left Edge ( void ); p u b l i c : R u l l a r e (LPDIRECTDRAWSURFACE ∗ destination s u r f a c e ) ; Rullare(Rullare ∗ R u l l a r e s r c ) ; R u l l a r e (Enemy ∗ Enemy src ) ; Rullare () :Enemy() {} virtual ˜Rullare( void ); v i r t u a l void AI( void ); } ∗ R u l l a r e p t r ; typedef class Hoppare:public Enemy { p r o t e c t e d : p u b l i c :

57 Hoppare (LPDIRECTDRAWSURFACE ∗ destination s u r f a c e ) ; Hoppare(Hoppare ∗ Hoppare src ) ; Hoppare (Enemy ∗ Enemy src ) ; Hoppare() :Enemy() {} virtual ˜Hoppare( void ); v i r t u a l void AI( void ); } ∗ Hoppare ptr ; E.4 Player

// PLAYER CLASS /////////////////////////////////////////////////////////////// typedef class Player:public Character { // this is the Player class p r o t e c t e d : void I n i t ( void ); // used fore the movement of enemies when the player is moving Enemy ptr ∗ S u b l e v e l F i e n d e r ; int A n t a l F i e n d e r i S u b l e v e l ; p u b l i c : Player ( int X, int Y, int Width , int Height , int Num frames , int Attr , int Mem flags ,LPDIRECTDRAWSURFACE ∗ destination s u r f a c e ) ; virtual ˜Player( void ); void Input ( void ); void Logic ( void ); void Player Move ( void ); void Set Enemies(Enemy ptr ∗ Fiende arg , int a n t a l f i e n d e r ) ; void Move Level ( int x , int y ) ; } ∗ P l a y e r p t r ; E.5 Sublevel

// SUBLEVEL CLASS ///////////////////////////////////////////////////////////// typedef class Sublevel { p r o t e c t e d : // Terrain in dynamic arrays T e r r a i n p t r ∗Ground [ 3 ] ;

// the original terrain that will be used to clone all other terrain T e r r a i n ptr Original Ground [NUM ORIGINAL GROUND ] ;

// the player doll. It is the referensepoint to all othet objekts in // the map it is not the starting possition of the player // the starting possition will be set by the game T e r r a i n p t r p l a y e r d o l l ;

// the size of the map int T e r r a i n S i z e [ 3 ] ;

// ponter to the same data in Level Enemy ptr ∗ L e v e l F i e n d e r ; // enemies local to the Sublevel Enemy ptr ∗ S u b l e v e l F i e n d e r ; int a n t a l s u b l e v e l f i e n d e r ; // the original enemies that will be used to clone all other terrain Enemy ptr Original Enemies [NUM ORIGINAL ENEMYS ] ;

// events on the map T e r r a i n ptr Original E v e n t s [NUM EVENT TYPES ] ; T e r r a i n p t r ∗ S u b l e v e l E v e n t s ;

58 int a n t a l s u b l e v e l h a n d e l s e r ;

int Level To Play ;

// pointer to the same data in game P l a y e r p t r Player ONE;

// SUBLEVEL METODS ////////////////////////////////////////////////////////////

void Load Terrain Graphics ( void ); void Load Map Data ( char filename []) ;

void Move( int x , int y ) ;

void Draw( void );

p u b l i c : S u b l e v e l ( char l e v e l filename [] ,Player p t r P l a y e r s o u r c e ) ; ˜ S u b l e v e l ( void ); int Playing ( void );

} ∗ S u b l e v e l p t r ; E.6 Level

// LEVEL CLASS //////////////////////////////////////////////////////////////// typedef c l a s s Level { p r o t e c t e d :

// the number of maps in level int maps ; // the sublevel that the player is playing on int Level To Play ; // the curent map that the player i on int Current Map ;

// the maps or different rooms in level S u b l e v e l ptr karta[2];

// the list of the enemies in the level. if you leave a room the // enemies are still there when you come back Enemy ptr Fiender; // pointer to the same data in game P l a y e r p t r Player ONE;

p u b l i c : Level(Player p t r G l o b a l P l a y e r ) ; ˜ Level ( void ); // the main event loop for the level void P l a y i n g L e v e l ( void );

} ∗ L e v e l p t r ; E.7 Game

// GAME CLASS ///////////////////////////////////////////////////////////////// c l a s s Game { p r o t e c t e d :

59 // the player data. Global P l a y e r p t r Player ONE;

// the Levels in the game L e v e l p t r L e v e l 1 ;

// Animations

// GAME FUNKTIONS /////////////////////////////////////////////////////////////

p u b l i c :

int Game Init ( void ∗parms=NULL) ; int Game Shutdown ( void ∗parms=NULL) ; int Game Main ( void ∗parms=NULL) ;

} ;

#endif // game h

60 F mapeditor.h

/∗======; ∗ ∗ Copyright (C) 2004 Martin Persson. All Rights Reserved. ∗ ∗ File: game.h ∗ Content: Main Game include file ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/

// watch for multiple inclusions #ifndef game h #define game h

// INCLUDES /////////////////////////////////////////////////////////////////// #include ”bob . h”

// DEFINES ////////////////////////////////////////////////////////////////////

#define TITLE ” Martins Spelmotor ” // Title of the window // terrain layer type defines to keep track of what you are doing #define BACKGROUND 0 #define GROUND 1 #define FOREGROUND 2 #define NO BLOCK SELECTED −1 #define PLAYER SELECTED −2

// only used for the ground layer of terrain to indicate that pixel scan // should be used insted of the ordinary Bob::Collision #define TERRAIN TYPE NON SQUARE 1

#define NUM ORIGINAL GROUND 6 #define NUM ENEMY TYPES 2 #define NUM EVENT TYPES 1

#define GROUND TYPE 1 // #define ENEMY TYPE 2 // used for selection on the objects on the map #define EVENT TYPE 3 //

// GLOBALS ////////////////////////////////////////////////////////////////////

// PROTOTYPES /////////////////////////////////////////////////////////////////

// TERRAIN CLASS ////////////////////////////////////////////////////////////// typedef class Terrain:public Bob { p r o t e c t e d : int T e r r a i n Attributes; p u b l i c : // Used to identify what type of original terrain it was cloned from // so the filename can be saved in the ∗ . ban f i l e int Type Index ;

double t x , t y ; double t xv , t yv ; // Used to make the ForeGround and BackGround move faster or slower // than the player double SpeedFactor ;

61 int Move( void ); void Move( int X, int Y);

Terrain ( int X, int Y, int Width , int Height , int Num frames , int Attr , int Mem flags ,LPDIRECTDRAWSURFACE ∗ destination s u r f a c e ) ; ˜ Terrain ( void ); Terrain(Terrain ∗ t e r r a i n s r c ) ; } ∗ T e r r a i n p t r ;

// MAP EDITOR CLASS /////////////////////////////////////////////////////////// // editor class typedef c l a s s Map Editor { p r o t e c t e d : // Used to point at the global DirectInput mouse Bob ptr mouse ;

// This array might be converted to a linked list later on T e r r a i n p t r ∗Ground [ 3 ] ;

// The original terrain that will be used to clone all other terrain T e r r a i n ptr Original Ground [NUM ORIGINAL GROUND ] ;

// The player doll. It is the reference point to all othet objects // in the map. It is not the starting position of the player. // The starting possition will be set by the game T e r r a i n p t r p l a y e r doll , toolbox d o l l ;

// The size of the map int T e r r a i n S i z e [ 3 ] ;

// The enemies used to clone the enemies shown on the map T e r r a i n p t r O r g i n a l Fiender [NUM ENEMY TYPES] ;

T e r r a i n p t r ∗ Fiender ;

// The evets used to clone the events on the map T e r r a i n ptr Original E v e n t s [NUM EVENT TYPES ] ; T e r r a i n p t r ∗ Events ;

int Antal Fiender ; int Current Enemy type ; int Current Enemy ;

int C u r r e n t T e r r a i n B l o c k ;

int Current Layer ; int C u r r e n t O r i g i n a l B l o c k ;

int Current Event ; int Current Event Type ; int Antal Handelser ;

bool show ring ;

int objekttype ;

// metods

// Adds an enemy to the map void New Enemy( int Enemytype) ;

62 // Removes an enemy from the map void Delete Enemy ( int index ) ; // Adds an event to the map void New Event ( int index ) ; // Removes an event from the map void Delete Event ( int index ) ; // Returns true if the block is clicked bool Terrain C l i c k Left(Terrain p t r block ) ; bool Terrain C l i c k Right(Terrain p t r block ) ; // Metod that adds an object to the map void New Terrain ( int o r i g i n a l t e r r a i n i n d e x , int layertype); // Metod that removes an object in the map void D e l e t e T e r r a i n ( int intex , int layertype); // Saves the map to a ∗ . ban f i l e void Save map ( char filemane []) ; // Loads a valid ∗ .ban file into the memory void Load map ( char Filemane[]) ; // Moves a terrainblock void Move Terrain Block ( int index , int l a y e rt y p e , int x d i s t a n c e , int y d i s t a n c e ) ;

// Structuring of Editing() void M o u s e E d i t i n g s t u f f ( void ); void K e y b o a r d E d i t i n g s t u f f ( void );

void Move Map( int x , int y ) ; void Move Map Objekt(Terrain p t r objekt , int x , int y ) ;

p u b l i c : // the construktor Map Editor ( Bob ptr global mouse ) ; // the destruktor ˜ Map Editor ( void ); // to be used in the main event loop void Editing ( void ); // metod that draws all terrain blocks and enemys and events void Draw( void );

} ∗ Map Editor ptr ;

// game console c l a s s Game { p r o t e c t e d : // GAME OBJEKTS ///////////////////////////////////////////////////////////////

Map Editor ptr editorn;

p u b l i c : // the mouse Bob ptr mouse ; // public because the editor needs it

// GAME FUNKTIONS ///////////////////////////////////////////////////////////// int Game Init ( void ∗parms=NULL) ; int Game Shutdown ( void ∗parms=NULL) ; int Game Main ( void ∗parms=NULL) ; } ;

#endif // game h

63 G Screenshot

Figure G.1 shows what the test game looks like. The arrows are velocity vectors

Figure G.1: A Screen Shot of an Example Game and aren’t actually shown during gameplay.

64



© 2022 Docslib.org