Monday, January 26, 2009

Moving in an RTS

In this post I will be discussing the theory behind the code in making a unit move from one location to another. This is not meant to be a complete tutorial, nor ground breaking. In fact, it won't even cover basic path finding. However, if you are having problems making a unit move between two points (namely, they move diagonally and then straight along) read on.

Such a seemingly simple thing, moving a unit between two points in a straight line (ignoring path finding as FK will not have path finding) However,I struggled with it for quite some time.

At first, I thought it would be really simple. See if the X co-ordinate of the object is bigger or smaller than the target X co-ordinate. Then, add/subtract the desired speed depending on whether the number is bigger or smaller (with bigger numbers being down and to the right). This works fine if the destination is as much above as it is to the right. However, if the target is not, the unit moves at 45 degrees toward the thing until either the X or Y co-ordinate are in line with the destrination (which ever is sooner) at which point, it moves horizontally/vertically. Apart from looking ridiculous, it is not the quickest way between the two points and so will be incredibly frustrating for the player. But then, if you are the target audience for this post, you knew this already.

[Note: Another problem that you may encounter is that as the unit reaches it's destination, it jumps around it. This is because it is unlikely the player will click on a pixel that your units movement speed goes in to exactly. As a result, you unit will switch between being to the left and to the right of the target. I will explain my solution to this at the end of the post]

I tried a couple of other things that, in hind sight, are long winded amd complicated; I won't bore you with the the details. They ended up working to a point, except when the unit had to move either vertically or horizontally, it would accelerate to near infinite speeds.

The solution I finally settled on, at first seemed too complicated (and for all I know, there might be a better one) It relies on creating a right angled triangle with the destination point, finding the accute angle and creating proportional x/y speeds that add up to make a total (limiting the maximum speed) (See diagram)



Using trigonometry (Soh Cah Toa!) we can find the angle using xDist and yDist (which can be calculated by subtracting the larger x/y co-ordinate from the smaller of the unit and it's destination)

Tan(Angle) = yDist/xDist

Or...

Angle = atan(yDist/xDist) //atan is the inverse of tan, called atan in most programming langauges.

In most programming languages, this will actually give you the answer in radians (a way of numbering angles where pi represents 180 degrees). However, for the sake of simplicity (no PI key on my keyboard!) I will use degrees. You can either convert Angle in to degrees (*180 and then divide by PI) or when I say 90, use PI/2.

Next, we work out how steep the hypotenuse (longest side of the trianlge) needs to be. By doing the angle/90 we can work out what proportions the 2 speeds need to be. If the angle is 90, then we know we want the whole speed to be vertical, whereas 0 needs to give the whole speed as horizontal.

The way I did this was first calculate the Y speed.

ySpeed = (Angle/90)*Speed //where speed is the distance in pixels that you want your unit to cover in one frame.

In this, if the angle is 45, (ie. as far up as it is across) then you get (1/2)*speed resulting in half of your total speed to vertical.

The xSpeed is then calculated by taking the angle from 90 and putting that over 90. In the end, you will get two angles that add up to 90. Therefore, when you put them over 90 as two seperate fractions, they will add up to 1. So, when the two fractions are times by the speed, the two fractions of speed will add up to speed.

The problem with this is it will only work when both values are increasing (ie, the unit is moving right and down) To get around this (and deal with a second problem which I mentioned earlier) when the destination is selected, define two boolean variables to store whether the target is left/right and up/down. Then, when your regular function to move the unit is called, if movingRight == true, if != true, then subtract the number and so on.

I realise that this is a little confusing, so here is a quick summary of what I mean

Summary: By finding out the angle that the destination is from the current position, you can find the preportion that the two speeds need to be.

The final issue is checking when a unit is arriving. By using your movingRight boolean variable, you can simply see whether the unit has passed the X co-ordinate. If movingRight==true then if curX >= targetX then it has arrived. Likewise, if movingRight != true, then curX <= targetX for it to have arrived. And you do not need to check y, as they should happen at the same time.

Here is my C#/XNA code if it is any help: (distASec is a Vector2 which stores the speed, curPosition is a Vector2 which has the units location and currentTarget is a Vector2 which is where the unit is heading. Vector2 is a XNA data type which stores X and Y co-ordinates(as floating point numbers, if your in to that sort of thing!).

if (currentPosition != newTarget)
{
Vector2 totDist;
float refAngle;
currentTarget = newTarget;

//Calcuates total distance and direction
if (currentPosition.position.X < movingright =" true;" x =" currentTarget.position.X">


}
else
{
movingRight = false;
totDist.X = currentPosition.position.X - currentTarget.position.X;


}

if (currentPosition.position.Y < movingdown =" true;" y =" currentTarget.position.Y">


}
else
{
movingDown = false;
totDist.Y = currentPosition.position.Y - currentTarget.position.Y;
}
refAngle = (((float)(Math.Atan((totDist.Y / totDist.X))))*180)/(float)Math.PI;


distASec.Y = (refAngle / 90)*speed;
distASec.X = ((90 - refAngle)/90)*speed;

}

Finally, to check if the unit has arrived.

if((movingRight && currentPosition.position.X >= currentTarget.position.X)(!movingRight && currentPosition.position.X <= currentTarget.position.X))
{

//Code to be excuted upon arrival

}

Sunday, January 25, 2009

An interesting premise?

Today I was doing some research for an annoying (read: rubbish) physics homework, why it is rubbish is another story! Basically, we had to research how theories of light had changed through time. However, it was quite interesting reading about ancient (BC times) theories of atoms.

The basic idea is that all things are made up of four atoms (indivisible things, not the modern scientific meaning of an atom, which is entirely divisible): Fire, Water, Earth and Air. Each of these has distinct shapes made up of triangles (not so indivisible then). Now obviously many games have used the idea of four elements before and it is largely just a different reality, usually one with fate, magic spells and goblins.

However, what I am suggesting is, supposing they were correct from a scientific point of view. From this base, work through the whole of Physics, Chemistry and Biology to create a world based on these scientific truths. And to make it a bit more interesting, define a few rules. First, each of these atoms have unique properties that exhibit themselves in whatever they are in. The higher the ratio of them within the molecule, the stronger the effect, but even with one, there would still be some effect. Second, where scientific questions are ones that have been raised before, you use another theory that has also been superseded by something else. For example, if you get to the question of light, take the aether to be correct.

The question is, would this create an interesting and believable alternate world to set your game in, or would it be minor differences that make no difference. Also, can interesting things come out as true, ie. can magic work?

Here are a few ideas I have come up with, I might try to expand this at some point, but working through 2500 years of science without the ability to experiment may take some time!

Earth (prthivı) -Mass: 2, Fluidity: 0, Gravity: 3, Repulsion: 5, Temperature: 3, Temperature Resistance: 5

Fire (tejas) - Mass: 0, Fluidity: 0, Gravity: 0, Repulsion: 0, Temperature: 5, Temperature Resistance: 3

Water (apas) - Mass: 1, Fluidity: 4, Gravity: 1, Repulsion: 1, Temperature: 2, Temperature Resistance: 4

Air (vayu) - Mass: 0, Fluidity: 5, Gravity: 0, Repulsion: 0, Temperature: 1, Temperature Resistance: 2

I'll quickly explain my thinking behind these labels. To find out an objects properties, you add up the figures of its containing elements and divide it by the total number of elements (except with mass, gravity and temperature). The mass of an object is how heavy to pick up. Fluidity is it's ability to stay together. If it's fluidity is greater than the repulsion of the thing surrounding it, then the excess fluidity is converted in to motion. For each point of gravity, the atom can attach to that number of atoms, (note, only requires one of the atoms to have it) Any left over draws objects near it (relative to the total size of the molecule) and a velocity equal to the amount left over. Temperature is the temperature of the object. If an object touches another object and the temperature is greater than the temperature resistance of the other object, the second object is annihilated.

I quite like base rules and working up from them. A once read a description in a game design book (Game Architecture and Design, Andrew Rollings) giving an example of emergent game play. In the example, the players are travelling somewhere (I think it is an MMO, but definitely doesn't exist yet). It is cold and they are going to freeze. All they have on them is something that burns at a very cold temperature. However, one of the players remembers that being in the centre of a flame raises the temperature by a few degrees. Still cold, but enough to keep them alive. This would be taking emergent rules to the extreme.

Sorry for the lack of posting, I have a couple of posts in the works. One on programming a unit to move from one location to another (surprisingly complicated) and the other on planning your project. FK, my current project, has had a couple of good weeks with solid progress being made. I hope to have a working province by the end of February, complete with animations and maybe even a building which actually creates the unit.

Saturday, January 3, 2009

The key to good game design

Sorry for not posting much, I have much to post about, but little time in which to do it (as all the time I am feeling constructive I spend on revision!) However, I saw a clever post of GameDev.net that I thought I'd share. You can read the full thread here, not that interesting though!

Anyway, here is the post, the poster describes what he thinks are key to good game design.

1) The game needs to be (or at least *seem*) fair.

2) The player's character/avatar needs to control well and respond in a predictable fashion (this ties into the game being fair).

3) The challenge of the game needs to match the player's skill level (note: no game is going to have the perfect challenge at all times, so this isn't going to always be true until adaptive difficulty is perfected).

4) The player's goals (both long-term and, more importantly, short-term) need to be obvious at all times.

5) The player needs to have clear feedback that allows the player to know at all times how well he is performing at the current task in the game. It's important to note that any negative feedback/punishment that is given to the player should be treated as information and not as mockery. A game with good design never concentrates too much on a player's mistakes. It's best to make the mistake obvious without badgering the player. Games like Bioshock that just automatically restart you without even having a death animation or text that essentially says, "Hey, even though it's completely obvious to you that you just died, I'm going to say it anyway... GAME OVER, LOSER!" have good game design in this respect.

6) The rewards and punishments need to be structured properly. I.e. the player shouldn't be given a huge reward for a trivial task, and the player shouldn't be punished too much for a small mistake (one example of bad design in this regard that I constantly encounter is in platform games where you're in a vertical level traveling upwards, make one bad jump, fall for what seems like 5 minutes, and then start at the very bottom of the level all over again).


Number 5 is quite clever and something I hadn't really thought of. Game Over screens are basically just rubbing something you already knew in your face.

I would add to number four that it also needs to be made clear to the player why they are failing (if they are). For example, in Gear of War 2 in that sequence on the back of the cargo truck type things - I didn't know why I kept failing (I wasn't shooting the mortar fire) It was an incredibly frustrating experience and definitely not fun.

The final thing I would add is that if puzzles/challenges use a new mechanic, should fit with everything that has gone before. Good games lay down the basic rules early and then just interpret them differently. If at the start, the player can't run, this should remain the case and not just be changed when it suits the puzzle.