Sunday, June 30, 2013

Code Snippet : Angle Facings

So, simple enough concept:  "I have an entity facing a certain direction.  I want to turn him to face a target direction.  I want him to turn on the shortest angle possible".

Despite this being what I consider a simple and common problem, I struggled greatly to find somewhere that adequately described the solution.  So here's how I handled it!

Things to note:  
-Angles are in degrees (Most math libraries use radians, but I find degrees easier to assign initial values to, so we'll assume all Math functions we use take and return degrees)

-0 degrees is straight right, and the range of angles is 180 (counter clockwise) -> -180 (clockwise)

First of all, you'll need a helpful function called WrapAngle.  Monogame has this by default in the MathHelper class, but in essence it does the following:

public float WrapAngle(float angle)
{
   while (angle > 180)
   {
      angle -= 360;
   }
   while (angle < -180)
   {
      angle += 360;
   }
   return angle;
}



Alright, so whenever we modify an angle, we need to feed it through WrapAngle.

Next step, is to get our compared value.  facingAngle is your current facing, and targetAngle is . . . well, the angle you're turning towards.

float compareAngle = WrapAngle(targetAngle - facingAngle);

We now use this, along with the turningSpeed of the entity to update the facing position.  We do a quick check to make sure this direction is actually the shortest.

facingAngle = facingAngle + Math.Min(turningSpeed, Math.Max(-turningSpeed, compareAngle));

Aaaaand done!  Put this in your update loop, and your entity will always turn to a given angle, taking the shortest

Snake : An issue of control

So, take a programmer who wants to make games.  He has to smart small.  A good idea would be to do a remake project of a classic game, in the language/framework he would like to become familiar with.

So, which language?  Having some experience with XNA, I researched the no-longer supported framework and found out about Monogame (http://www.monogame.net/).  A framework that takes all the simplifying goodies of XNA and makes it ridiculously portable?  Yes please!

So, which classic game should I remake?  Well I was in a pet store the other day looking at snakes, and you know what?  Snakes are pretty awesome.  So snake it is!

So we've got a framework, and we've got a game.  I want to make sure to keep it simple, but at the same time I'd like to do a little innovation on the game idea.  Let's start with the most obvious issue you deal with when making a multi-platform title and that's dealing with the issue of different controls.

Now, Monogame does a brilliant job of wrapping similar input modes together.  Programming wise, a gamepad on any device can be treated the same, a touchscreen on any device can be treated the same, etc.  However, we still need to deal with the fact that some devices might only have a gamepad, while some might only have a mouse or touchscreen.  So, we need to think of a control scheme that allows tactile, intuitive input across the following devices:

Keyboard, Mouse, Touchscreen, Gamepad.

With the original snake, Keyboard and Gamepad are fairly simple control inputs.  Up, down, left, right, we're set.  However, the issue comes when you introduce Mouse and Touchscreen.  We could have it so tapping somewhere on the screen, either above, below, left of or right of the snake will cause him to go in that direction.  Though effective, this doesn't feel like it will give you much control, and seems to remove a level of immersion.  That and feels like a poor-mans control port.  We could draw the arrow keys on screen and allow the player to click/tap them, but this seems to carry the same problem as the last idea.  I want my game to feel like it was designed to work naturally with all levels of input, and that seems rather difficult to do with the current way the snake moves.  Luckily enough, I was planning on redesigning how the snake moves anyway.

Rather than having the old-school up, down, left, right movement, I'd like to have more control of my snake. The body parts will still follow the head, but the head will now have a 360 degree 'forward' variable, as well as maximum move and turn speeds.  The snake will be able to curve and wrap around the map, giving the player a more unique control experience, as well as adding other gameplay elements I will discuss later.  So, let's revisit our control schemes:

Mouse/Touch:  Clicking somewhere on the screen will set that as the snake's destination.  The snake will turn and move to take the shortest path possible to reach it, and then circle around it.  For a higher level of control, you can click and drag just in front of the snake, and he will follow your cursor.  I really like this outcome, it really lets you feel like you're in control of the snake and it's fun to have him follow your finger.

Gamepad:  Now that our snake has 360 degrees of movement, we can take advantage of thumb pads.  When pressed in a direction we'll set a 'target angle' for the snake and the snake will move until he's facing that direction and then keep moving straight.  This will give the player the feel of curving around the level/objects and should give a good level of control.

Keyboard:  Oddly enough, is now the least intuitive of controls.  Having only four directions of movement, it should function like a restricted gamepad control.  Tap in a direction, and it'll set the target angle as that direction.  Though functional, this removes a lot of the 'looping' and control found in the other input methods, some of which will be important to some gameplay elements.  Normally I'd be upset about this, but honestly, every device that has a keyboard should also have either mouse or touch, so we should be in the clear.

So, we've got our control worked out, and after performing some Monogame Magic, we come up with this:

So the first thing you might notice is that programmer art is terrible.  That's true!  I'm working on that.  The second thing you might notice is that the snake is wrapping over himself!  Why is he doing that! Doesn't the snake know that he's so ravenous he'll eat his own tail?  Well, that's something we'll address in the next post, which will be dedicated mostly to gameplay.