2013/05/03

PA5 - Game Data Driven

I am using the Input Sequence Sample on Windows to rewrite the Input Manager of Omega Race X. I already deleted all of the redundant methods for the keyboard, now I am implementing the Move class and removing the redundancy on the Xbox buttons. Another Java/C# comparison: I love Java's "Buttons... sequence" for variable-argument lists over C#'s "params Buttons[] sequence". I first read the C# syntax as a variable-argument list of arrays. Also, you cannot use namespaces with "using OmegaRaceX.*" whereas Java can import packages by wildcard, "import java.util.*" (though this import would slow compilation). A final annoyance is that you cannot define an object in a case of a switch statement, and then define (not redefine, because the cases are separate paths) that same object in another case. Another plus to C# over Java is an exception-less catch clause such as "try { statement; } catch { }".

Anything that implements IDictionary cannot be serialized, which makes creating a config file a pain. After the Week 10 lecture I jumped to implementing the fifth example, which includes networking, so my game will be halfway networked when it is finally data driven. I added the standard OutputQueue, InputQueue, QueueHeader, and QueueType. At first, I had several class-specific structs such as ShipData, LaserData, and MineData as well, but since they all had the same variables I reduced them to a single ObjectStruct and placed it in the IO namespace. Laser and Mine were the first to successfully send across the queues. Then, I added ship turning to the queue but accidentally set the value of the OutputQueue to Position, not Velocity (a bit of confusion can arise from the usage of Laser and Mine, which set X and Y to Position and not Velocity). Once I fixed this, turning worked.

Now boost, that was a different story altogether. My first addition to the OutputQueue did not have drag (though I knew that I needed to add it) so the ships barely moved forward. And then I noticed onCollide()... I had been manually adding the ObjectData code to each Velocity call, but when I saw multiple sets to Velocity.Zero, I added velocityZero() and sendVelocity() methods to handle these. Finally, I realized that ObjectData could not be used for everything Ship, and then resorted to using ShipPosition, ShipVelocity, and ShipRotation.

On a final note, I cut down InputManager as much as possible (dat copypasta was disgusting). The keyboard only has three methods and the Gamepad only has 5 methods now.

04/27-05/03 Assignment Log

With Java as my most fluent language, I began writing Data Driven through the lens of a Java developer. In Java, switches on enums do not require each case to be prefixed by the name of that enum, for instance this:

switch (data.type) {
case FSM_Type.FSM_ADV:
Advance(data.input);
break;
case FSM_Type.FSM_SET:
Set(data.state);
break;
}

Instead of this in Java:

switch (data.type) {
case FSM_ADV:
Advance(data.input);
break;
case FSM_SET:
Set(data.state);
}

Also in Java switches: the last case does not need a break, it automatically knows that being the last case, it does not need a break. This is especially annoying in C# default cases:
switch (enum) {
...
default:
...
break;
}
Actually, now that I think about it, I hated leaving break statements off of default cases when I first learned Java. Maybe C# and I were meant to be.

Speaking of enums, you do not end the last element in an enum with a semicolon in C# like in Java (it can be ended with a comma, but that is optional). You also cannot have private enum constructors, or enum methods.

I keep forgetting to write string instead of String, Java habit. There does not seem to be a difference between primitives and objects in C# (update: there isn't). For instance, in Java if I wanted to change a byte to a String for a parameter passing, it would be "new Byte(b).toString()", whereas I can simply type b.toString() in C#. The same goes for ints. Also, every primitive is a struct in C#.

In Java you can place semicolons after method blocks, in C# you cannot. I also learned that a field with the get; set; blocks defined is actually called a property, and is treated differently by the CLR than a field.

I kind of miss my @Deprecated annotation from Java, whereas C# uses [Obsolete]. In addition, C# has no easy equivalent to @SuppressWarnings("unchecked"), you have to use #pragma in the actual method, and then turn it off later.