Tag Archives: Asteroid Outpost

Asteroid Outpost Update 2012-01-01

Over the holidays, I kept thinking about how nice it would be to call AO a game and not just an engine, as well as taking some hints from the author of Gratuitous Space Battles, specifically his article on how to stay motivated. One of his points is to write down a list of what you did each day, so here is the start of that tradition:

  • Added a mission select screen that gives the option to start the tutorial, or start a never-ending mission.
  • Added a little dot beside the selected menu item on the main menu and play a sound when you mouse over. It looks and sounds very cool.
  • Removed the default health of 100 and customized each Entity to have their own health value. This makes it possible to have fun in the never-ending mission.
  • Researched briefly how to change some of my hard-coded method names that I store in strings. I couldn’t find an easy way right away, so I left that for future refactoring.
  • Modified how the spaceships flock slightly. They should stay together a little bit more now. There is still a slight problem with their course, and I feel it’s due to floating point precision, but it could also be an error in my flocking math.
  • Replaced the two singletons I had with instance variables that get passed around because of a few articles I read on the subject, and the fact that I could see it hurting my code quality over time.

Back to AO

After over a month of playing games (BF3 & Skyrim) and screwing around, I am finally motivated to write a line or two of code for AO. I fixed a issue that caused my AI ships to suddenly stop in their tracks when they were on the same axis as their target. I hope this small change will motivate me to actually get AI waves working and be able to call Asteroid Outpost a game and not just a game engine.

In other news: a handful of people have started to show some interest in applications I have made! :D Exciting! A few weeks ago, a man commented about my Winamp Meta Data application and has since offered me money! How cool is that? Also, a few people have started to use (and report bugs for) TeeVee. Despite the bugs, I am excited that people have started using the application. I use it almost every day. And also, a friend from gamedev.stackexchange has taken an interest in my Sprite Library and may be adding new features to it. So… I’ve been a little high with all of the attention. Thanks guys.

Tutorial Scenario

I started my tutorial scenario over the weekend, and things are going great. I have the first couple steps of the tutorial done, and I the rest should fall into place rather quickly. An eventing system allows for a significant reduction in the coupling, the game knows nothing about the tutorial system. The tutorial system just hooks in to the event(s) of interest and moves the progress forward when certain conditions have been met. It’s great :D

Back to AO and my Sprite Maker

With a heavy heart, I left the Android project late last week. I have been extremely stressed out since the project started. The stress largely came from my experiences with other hobby projects, and comparing those failures to this budding project. I felt like I was nay-saying absolutely everything, and I was; Trying everything I could to get a smaller project, yet only rocking the boat more.

So… after a more than slightly bitter break-up, I am returning my attention to Asteroid Outpost (AO) and my Sprite Maker. I am trying to find small things to work on in AO while I get my teeth into my Sprite Maker.

Over the past week or so, I have decided to tackle the lag issue when slower computers host a multiplayer game. Kind of a funny cause: A long while back, for testing purposes, I disabled XNA’s frame rate limiter so that I could see how many frames per second my modern computer was pumping out. Turns out it’s usually between 500 and 700. In AO, the miners mine at a constant rate over time, so each update, they will generate 2 events and 2 packets: one to decrease the minerals of the asteroid, and one to increase the player’s minerals. After putting two and two together, I figured that XNA has probably tied the Draw and Update loops into one, causing 500 to 700 draws AND 500 to 700 updates per second, in turn causing 1000-1400 packets per second to be created for a single miner! That could cause some lag eh?

The obvious, simple solution is to turn the frame limiter back on, but that would only be a bandaid solution. The real solution is to change the miner’s logic from a constant rate to a burst rate, something like: take and give minerals only 4 times a second. This would reduce the number of packets to 8 packets per second for a single miner, regardless of the frame rate.

An other optimization I will be looking at, is to remove older versions of the same packet in the same outgoing batch. What I mean by that is if miner A is updated first and takes 10 minerals from the asteroid, and gives the player 10 minerals, then miner B is updated and takes 10 minerals from the same asteroid and gives the same player those minerals, there will be a lot of duplicate packets. I intentionally collect all of the outgoing packets for a single frame, then send them all at once at the end of the frame. Here is an example of what packets could be generated for the above example:

Packet 1: Asteroid 1 current minerals is now 250
Packet 2: Player 1 current minerals is now 110
Packet 3: Asteroid 1 current minerals is now 240
Packet 4: Player 1 current minerals is now 120

As you can see… if these packets are executed in order, packets 1 & 2 will be rendered completely useless, more recent information is available for the same entities in packets 3 & 4. I plan to resolve this with a hash-table (or dictionary) where the hash would represent the packet type and destination in such a way that previous, non-useful packets of the same type could be discovered and overwritten with new information before getting sent to the client(s), reducing the packet count yet again.

AO Released!

I just released a new version of Asteroid Outpost, revision 117. The old version on SourceForge desperately needed an upgrade. The main additions in the new version over the old one are:

  • Menus – A fancy schmancy menu system complete with cross-fading (make sure to check out the credits too)
  • Multi-player – A working multiplayer environment (just don’t try more than 2 players)
  • Lobby – A multiplayer lobby hosted on this very web host
  • New Graphics – Well… only new graphics for the Solar Station, but that’s the style I’m aiming for
  • A new unit – The laser tower. Sadly, it looks exactly like a power node, and will do nothing unless you press F8 (described below)
  • AI – Just the start, and only in single-player in Debug mode (requires building yourself). Press F8
  • Numerous other internal changes that make my life easier and more enjoyable

The game still isn’t playable, there’s no way to win or loose, there are bugs in places, very few units, and so on. I wanted to get the multiplayer done before I started working on new units in case I needed to change everything. It turns out, I don’t need to change everything, but I do need a system for getting new and improved graphics in the game without taking days to do each sprite. I have started a roadmap in Trac that will help me to stay on trac (get it?) and to better document the future steps I need to take instead of just documenting the bugs. Long story short, I will be working on my Sprite Maker for the time being.

Edit: I have abandoned Trac in favor of Trello for its simplicity and rapid use.

AO Release Imminent

I am in the final stretch, there are two bugs that I need to fix, then I will finally be releasing a new binary for Asteroid Outpost. Future binary (.exe) releases should occur more frequently. The development time for this update was largely due to changes in the core functionality that broke the end-user experience and took a long time to develop. Most of these kinds of changes are out of the way (I hope), and users can now use the interface as intended without core dumps. The changes I see in the immediate future will be more contained, and will allow for smaller and more frequent updates

AO Screens

A good friend and I got arguing about how easy or hard it was to design screens by hand (manual location & size). At first, I was saying that I didn’t mind designing by hand, but as my screens are getting more and more complicated, or I start to want more specific things out of my screens, it’s becoming more time consuming. The solution that we were toying with was to use the Windows Form Designer (available in Visual Studio) to design the screens, then copy the code into the game. As long as class names and properties look similar, it would be very little work to copy/paste. Now that I understand what he was trying to communicate, it’s actually quite nice. I did a proof of concept over the weekend, and it works great! I will be converting all of my menu screens over shortly. I make everything inside a windows form or panel whose size is some standard size that I will use throughout Asteroid Outpost (AO). Then in AO, I make a centred panel with the same dimensions, copy the code from the windows designer, paste it in AO and make a few small modifications (Point -> Vector2, etc), delete some unused portions, and then run it!

Asteroid Outpost Lobby Progress

I am currently working toward a match-making service and lobby system in AO where servers will be able to set some game settings and start a lobby, and then clients will be able to see a list of all the active servers and join one. The match-making part of this is done. I set up a pair of simple PHP pages and hooked those into a database, one to post a server and the other to request the server list. Right now, when you click “Host” in AO, it starts a “Server Beacon” thread that will post and re-post its server information on the web, it expires after 1 minute. The clients are able to download the server list, then request more information from each one (and incidentally also grab a ping), then display that information in a table I designed in XNA. That’s as far as it goes.

Next, I need to alter the existing TCP protocol I am using to put players in a lobby before starting the game. This lobby should display mostly read-only information to the client, but allow the server to change settings? I guess I’ll worry about that when I actually have game settings. For now, all I need is a player list and a “GO NOW” button that will start a count-down timer, initiate the game world, and sync all the clients before starting the game.

Since I’m getting closer to getting multiplayer set up and working from an end-user perspective, I’ve started to do some more thinking about the gameplay modes and what comes next. My initial plan for multiplayer is coop defence. My initial initial plan was 2 players, but I have since thought, why 2? I’m starting to think that 2-4 players feels like a good number, and absolutely nothing in the back end will need to change. The way I’m thinking of doing the AI waves is to provide both a theme and value. The theme would be something like “Lots of motherships” or “cloaking”, where the units in the wave would belong to the “theme” of the wave. On the same note, I don’t want waves to consist of only 1 unit type like a lot of tower defence games do, and I understand why they do it, but I don’t want that feel for this game. A “Value” would be assigned to each wave. I’m thinking that each AI unit will also have a value, the higher, the stronger or harder the unit is to defeat. When the waves are randomly generated, I will keep adding units to a wave until the value of the collection of units exceeds or matches the intended wave value. This will also make it easy to add a multiplier for multiplayer, or change the value for different difficulty levels. This brings up an other point, if there are 2 players in the game, the AI should be at least twice as strong, right? If it’s exactly twice as strong, I think it would be easy. If one player needs help, the other one will pitch in (if able). It will require lots of play testing, but my gut tells me that a 2.1 multiplier might work well. Any thoughts?

Networking!

After weeks of work, I finally got Asteroid Outpost to work over the network! There are a few bugs to work out, but Mike and I were able to mine the galaxy together, WOO! I was surprised how easy networking was with the right method. I have tried and failed a few times to get networking working before, so I was expecting many issues. This method was quite effortless, I’m using a combination of Reflection and Events, and I would highly recommend this approach to anyone who is designing a networking application and is able to use these tools. Now for an in-depth view at the implementation:

First off, a friend of mine blew my mind with how he handled inter-entity communication. Now that I’ve implemented it, it’s completely obvious: use Events to communicate status changes. Status changes can be things like: moving, health changing, power level changed, dying, etc. Each of these will have an event that fires and tells anyone who’s listening. An example would be in my AI: my AI locks on to a target entity and tries to kill it, duh. If you don’t use events, in every update you’d have to check that your target is still alive. With events, when you first lock-on to the target, you’d listen to the target’s dying event. When the dying event fires, you’d get a chance to respond by picking a new target. Convenient, right?

If you don’t know much about Reflection, either read a little from the link, or here’s a short summary: Reflection allows you to look up information about types, create new types, and invoke arbitrary methods on instances of types at run-time. You can create a type by name, call a method by name, get a list of events that some random object has, and many other useful things.

So secondly, I use reflection to call methods on the remote machine. I send some way to look-up a target object along with the name of the method to execute, then a list of all the parameters the method accepts. On the receiving end, I first look up the target object, typically by entity ID, the networking class, or the game instance. Once I know which object will be receiving the message, I reflectively look up the method I want to call using the method name we received, then invoke this method with the parameters that we also received. Calling a remote method becomes as simple as calling a local method.

Now… for the cool part, how I’ve integrated my event system with this network reflection system. Each of my events uses a different delegate, so each event uses a different set of parameters. In my case, each event has a single argument, and that argument extends from this nifty class:

public class ReflectiveEventArgs : EventArgs
{
    public ReflectiveEventArgs(IReflectionTarget target, String theRemoteMethodName,
                               object[] theRemoteMethodParameters)
    {
        Target = target;
        RemoteMethodName = theRemoteMethodName;
        RemoteMethodParameters = theRemoteMethodParameters;
    }
    public IReflectionTarget Target { get; private set; }
    public string RemoteMethodName { get; private set; }
    public object[] RemoteMethodParameters { get; private set; }
}

So each event contains all the information required to reproduce itself over the network using reflection. This generic class is never used directly, even though it could be, but it is even more powerful when you extend from it like this (class hierarchy simplified slightly):

public class EntityMovedEventArgs : ReflectiveEventArgs {
    public EntityMovedEventArgs(Entity theEntity, Vector2 theNewPosition)
        : base(theEntity, "SetCenter", new object[] { theNewPosition })
    {
        NewPosition = theNewPosition;
    }
    public Vector2 NewPosition { get; private set; }
}

This way, the entity just invokes its moved event like it normally would, but behind the scenes, it has actually encoded a way to travel over the network. The method SetCentre is part of any Entity that will be able to move, and it accepts a single parameter of type Vector2 (theNewPosition).

Now for some real fun. How does the network class know what to listen to? Sure, all entities will be able to move, but not all entities will have a power level or a mineral count or… something specific to your class. Reflection! Every time an entity is added to the game world, the network class is given a chance to listen to events. Some events will only want to travel from the server to the clients (eg. moving), and others will only want to travel from the client to the server (eg. request a building). I have handled this by using custom attributes. I plan to change my current implementation, but right now I have an attribute for every event. Using reflection, I can look up these attributes and tell the difference between server->client events and client->server events. The network class will only listen to the events that it deems appropriate based on whether you are a server or not.

After all of that, the network will be able to catch all events that you would like to send over the network, AND it has all of the information required to tell the receiver what to do when an event gets fired. That’s it! When your entity moves, the entity will fire an event telling anyone interested, the network picks that up, serializes the method call embedded in the event args, sends that across the network, deserializes the method call on the receiving end, then the receiver invokes the method using reflection, in this case, it will invoke SetCentre with the new location! It is nearly trivial to add new events too, simply make a new class that extends ReflectiveEventArgs, make an event that accepts this as a parameter, then invoke the event! Poof, the event has affected everyone on the network.

Before I release a new version on SourceForge, I want to have a human way to connect to network games. Right now, the binary will only connect to the localhost, so you have to change the code to connect to a friend. I have just finished writing a simple, and flexible match-making service in PHP that will service this game, and potentially other games I make in the future or games my friends make. I will be working to integrate this match-making service into Asteroid Outpost right away, and along with this, I will need a list control and a simple lobby system. Should be fun, :D