- Details
- Category: Game Development
- By Stuart Mathews
- Parent Category: Code
- Hits: 3612
Since Traveling Europe, I've been focusing mainly on my side project. Specifically, I've been trying to implement a level editor for my prototype game engine:
{gallery}stories/game_editor_pics{/gallery}
I found this stuff such a pleasing distraction.
For a while, I've been creating new levels that are automatically generated. That is, the generation and placement of the level pickups have been random, and the level, which is basically a maze, is automatically created & configured each time. What I needed, was to be able to create a way to design levels more explicitly and creatively.
I decided that I'd start creating a level editor project which would read all the game's assets and use them to define the level and place game objects in the level. The idea is then to be able to save the configuration of the level design in the editor out to a file, like a level file, which would then be loaded into the game.
This is what a designed level gets serialized down to:
<?xml version="1.0" encoding="utf-8"?>
<level cols="10" rows="10" autoPopulatePickups="False">
<room number="0" top="True" right="True" bottom="False" left="True">
<object name="GoldPickup" type="Pickup" resourceId="19" assetPath="game/assets/coin_gold.png">
<property name="value" value="5" />
</object>
</room>
<room number="1" top="True" right="False" bottom="False" left="True">
<object name="GoldPickup" type="Pickup" resourceId="19" assetPath="game/assets/coin_gold.png">
<property name="value" value="5" />
</object>
</room>
...
As I also wanted an editor to place pickups etc, I needed to define the properties of the pickups like how many points each type of pickup would have and which asset should be used to draw the pickup etc. This allows me to configure the maze by simply clicking on the walls to hide/show them. Also, I can add arbitrary game objects (like pickups) and then configure their properties before adding them to the room. These will then be loaded when the level starts up in the game.
The assets that the game uses are defined in a resource file which specifies the metadata about the asset, like its path, the type of asset and other metadata. I use this file, just like the game does and that's how I can load and manipulate the same assets that the game has access to. This is what the resources.xml file looks like:
<?xml version="1.0" encoding="utf-8"?>
<!-- List of all asset in the game -->
<Asset uid="4" scene="0" name="medium.wav" type="fx" filename="Assets/medium.wav"></Asset>
<Asset uid="5" scene="0" name="low.wav" type="fx" filename="Assets/low.wav"></Asset>
<Asset uid="9" scene="3" name="p1.png" type="graphic" filename="Assets/Platformer/Base pack/Player/p1_walk/p1_walk.png" width="256" height="512">
<sprite>
<animation>
<keyframes>
<keyframe x="0" y="0" w="67" h="92"/>
<keyframe x="66" y="0" w="66" h="93"/>
<keyframe x="132" y="0" w="67" h="92"/>
<keyframe x="0" y="93" w="67" h="93"/>
<keyframe x="67" y="93" w="66" h="93"/>
<keyframe x="133" y="93" w="71" h="92"/>
<keyframe x="0" y="186" w="71" h="93"/>
<keyframe x="71" y="186" w="71" h="93"/>
<keyframe x="142" y="186" w="70" h="93"/>
<keyframe x="0" y="279" w="71" h="93"/>
<keyframe x="71" y="279" w="67" h="92"/>
</keyframes>
</animation>
</sprite>
</Asset>
<Asset uid="10" scene="3" name="p2.png" type="graphic" filename="Assets/Platformer/Base pack/Player/p2_walk/p2_walk.png" width="256" height="512">
<sprite>
<animation>
<keyframes>
<keyframe x="0" y="0" w="67" h="92"/>
<keyframe x="67" y="0" w="66" h="93"/>
<keyframe x="133" y="0" w="66" h="91"/>
<keyframe x="0" y="93" w="67" h="91"/>
<keyframe x="67" y="93" w="66" h="91"/>
<keyframe x="133" y="93" w="69" h="90"/>
<keyframe x="0" y="184" w="69" h="91"/>
<keyframe x="69" y="184" w="69" h="92"/>
<keyframe x="138" y="184" w="68" h="92"/>
<keyframe x="0" y="276" w="69" h="93"/>
<keyframe x="69" y="276" w="67" h="92"/>
</keyframes>
</animation>
</sprite>
</Asset>
</Assets>
It's taken me a while to get to this point because for a long time I've not actually been concerned with not having this ability, as my main concern was working on the actual game engine code. The thing that was taking a lot of my time, was getting the framerate to be consistent and to run at a constant framerate.
Also, now that I've got to a point where the game engine is basically functional, I can focus on introducing elements of a primitive game like characters, AI and stuff like that which really depends on the rest of the system is predictable and working well.
Also, one of the other main reasons why I needed a way to create levels explicitly like this, is so that I can get two network games to load the same level instead of both loading two different randomly generated levels!
The levels are XML and I'm enjoying the process of writing the level generation code in C# and then writing the corresponding level loading routines in C++. I used JSON to define the network protocol for the multi-player network functionality because it's a bit less verbose than XML, but as the XML is used to define the game settings and to specify the game's resources, I've just opted to use XML for defining the levels also.
So far, it works OK...
- Details
- Category: Game Development
- By Stuart Mathews
- Parent Category: Code
- Hits: 2089
I've been designing a game engine which I'm using to prototype various aspects of game development theory. So far it looks like this:
The idea is that each game will develop its own LevelManager, which will manage what a level is, including the creation of game objects and the subscription of the game to types of game events. The Level Manager will also produce its own polling function for detecting user input, this allows the Level manager to respond to input and perform game commands in response to those actions. The Game commands class is also per game and independent of the game engine. This would be where the main game commands/actions are programmed and represent a unified interface of all possible game commands. You should call this when the input is detected that corresponds to a game command. The level state and managed by the Level Manager.
The GameStructure is managed by the engine and will poll your input function and send events to objects that have subscribed to them. It will also send updates and draw events as part of the game loop. The Event manager is not controlled by the game but by the game engine and it will see that events get to your game objects. Your game objects subscribe and raise events directly with the event manager, but the game loop in the GameStructure is what directly asks the EventManager to call objects when events that they subscribe to have been raised by other objects (this put the events into the event manager).
Code is here: https://github.com/stumathews/cppgamelib
- Details
- Category: Game Development
- By Stuart Mathews
- Parent Category: Code
- Hits: 5984
Since being on holiday I've been making some progress on my game prototype. I've implemented the foundations for a multi-player experience. This has been quite interesting. Firstly, I tried to implement a simple client-server architecture using TCP sockets by implementing a GameServer (if you want to be the game server) or GameClients (for each player that doesn't).
The first implementation was slow due to the constant verification that TCP has to do to ensure that traffic arrives, in order and without packet loss. I tried to implement it instead without such guarantees using UDP and indeed this improved the performance drastically.
The basic design is a system where each client registers with the game server, akin to joining a lobby in a multi-player game and as each new player arrives in the lobby details about the player is captured, such as asking the client to tell the GameServer who he is (NickName). The game server stores reference to where the client is - if we're using TCP then this will be the socket that the client used to communicate with the server, if using UDP (which is faster, so preferred) then we store the client's source port on the game server (I use connected UDP). This way the game server can talk back to the client, something like this.
How it all works, is that if a client raises an event such as moving the player, this event is serialized and forwarded to the game server, who then in return distributes that same message to all the other game clients (with the exception of the original sender). In doing so the original sender's nickname is labelled as the target of the event so that when the message reaches the clients, they know who in the system that event is for, i.e it's for the player that moved, so each client can move that particular player in that particular way so that all players see the same player move on their screens. Equally, if the game server (who is also a player) moves, this event is serialized and sent to all players, again labelling the event as being from the game server player's nickname. Each system has an event queue that is added to by reading these events off the network when they are sent by the Game server - here is a simple design.
In general, the mechanism works well in terms of the coordination of notifying other players what one specific player did. I've yet to integrate it fully to actually see the player that moved, move the same way on all the other player's screens - but the messaging and the networking is all there - backed by UDP or TCP. Getting the architecture setup in this way is a milestone. Like most things that are well implemented, it takes time to move from each stage of the design because one needs to fully evaluate what the next stage needs/should be and, more importantly, that it will be useful and not a wasted effort of coding. In this way, designing and thinking is an important next step and when I reach a milestone like this, I like to take a break and think about how to move from this milestone to the next one. So that's where I am right now.
One thing that has become clear is that in order to fully create a multi-player game, where all participants move and respond on each players screen, requires level initialization so that we can dynamically initialize a level with as many players as having joined, and then tell all of them to use the same level initialization and level creation parameters when starting the level on their screens in the same way, i.e complete with all the positions of all the other players. So there needs to be some dynamic collaboration to say, 'hey, these are all the players and they are here and here in the level, go and create the level that way when the game starts'. This needs to be done on all clients so all clients look the same way so that messages targeted for players actually reach players because they have been added/created to the same level that all other players are playing. This is the next milestone.
But while I know what needs to be done, I've been travelling and working and well it's a great time to do other things while you're at a milestone and you don't need to finish anything yet as you've not started the next thing. So, I've been thinking about the general idea behind distributed networking and participant collaboration (because that is what a multiplayer system is really), and how it is generally an information collaboration system used for many types of problems. You could use it for collaborating on individual results that a client has come up with, in like a distributed computing scenario. I think this is where computer games technology is so interesting and useful for so many other things, particularly via network programming - as it allows you to design systems that can be used in other distributed scenarios like to create say a map-reduce environment or some other clustering environment where resources, results and information are shared across multiple participants just like in a multi-player game. The interesting thing is that it's not just about communicating across the network, its about communicating across the network to inform other people what you've done or what someone else has done, and in so many applications knowing what exactly someone has done in your network is useful because its the basis for collaboration or at least, of information sharing.
In many ways, I already knew this from my work creating the distributed broker but it never actually told everyone else what one person is doing, it never radiated the effects of one person to all others concerned, and it also never used UDP, so that is cool.
What are the applications or concerns for such a system?
- Too much information perhaps, not everyone wants to know about all other's information, but in games we definitely do, we want to know exactly what the other players are doing so that we can emulate that behaviour on all our screens. In fact, this would be useful in distributing real-time messages to multiply display boards, say at an airport or train terminal.
- With so much data flying around, security and integrity of that data are important, particularly if you need to be 100% sure that the information you've received is exactly as it was intended (it hasn't changed, ie its integrity is in check) and that it's absolutely from the person who sent it. So perhaps ensuring that the data transmitted is secure is important, generally. For a coordinated and distributed algorithm implemented a distributed game agents absolutely. For a network game, maybe a lack of security could compromise the integrity of the game (someone is changing the network data and messing things up)
- Latency would be an issue for games, if it takes ages to act on a piece of information, then the real-time nature of a game is compromised. If the system is not real-time, then this wouldn't matter - it gets it when it gets it. Could implement the TCP mechanism to improve the reliability in these types of systems. Possibly compression, encryption and hashing be used to improve both the security and latency by reducing the size of transmitted data, but how would it affect the performance?
- A system that reports all the activity of others could be useful for auditing purposes - ie replicating what has happened to multiple places that it guaranteed that what has happened can be verified.
- It could also be a useful way to distribute the same information to agents that use it differently like each one applies or uses the data differently, say uses a distinct algorithm and this way multiple 'tests' could be run in parallel, i.e each receiving agent can run use the received data at the same time and report back its results.
I can't think of any more uses but distributed computing is basically what we're talking about and that is a huge field. I'd like to probably think a little more about the security of distributed computing, particularly in networked games or how implementing it could affect the gaming experience. That's perhaps for another day.
More Articles …
Page 2 of 9