martes, 25 de junio de 2013

On Art: Some Characters

Hi all!

I have the pleasure to introduce you some of the characters that will give life to my game-to-be. I don't want to spoil the story, so I cannot tell you what these characters are or the role they will play in the game, but at least you'll get a grasp on how the game might look like in the end, in terms of the characters at least.




Remember what you know up to now about the game. It will be a simple (simplicity is our friend when we are beginning), 2D platform game with these characters (among others). As I mentioned in this post, I strongly advocate that videogames should play a more important role in society, meaning that they should target beyond pure entertainment. But how do I plan to bring such 'added value'? Well, you'll have to wait!

Technically, these characters have been designed using Inkscape. This open-source application let you create vector graphics, and then you can turn them into pixel-based, raster graphics (e.g. converting to .png). There is a good comparison here between these two graphics styles, but let's say for the moment that for a first game, raster graphics (a.k.a bitmaps) are better as they are natively supported by any graphics library (such as SFML) and you need no additional coding to use them. These characters have been designed by Manuela, and I'm really thankful for having her to help me (I'm not that good at art design...).

So that's all for now. Hopefully I'll be able to show a short video soon with one of these characters walking and jumping.

See you!


viernes, 7 de junio de 2013

Fundamentals of Scrolling

Hi all!

After the last two posts on integration, I think that we can take a breath before finishing the hard physics stuff. So in this post I will talk about something that it is not that difficult to implement and is basic for any platform game (and many other games too): scrolling.

Most games, from the very beginning, have had some sort of scrolling. Scrolling consists of moving the scenario in such a way that your character is always visible, and usually, by the center of the screen. If this movement is on the horizontal axis, it is called 'horizontal scrolling', and if it takes place on the vertical axis, we would have 'vertical scrolling'. Most games use both of them.

Technically, however, it is more accurate to say that what we really move is the view along the level. That is, the idea is that we create a very big level (let's say 3000 x 3000 pixels) and then we set a view to our screen resolution, such as 1280 x 800 pixels. Then, we basically move this view (which you can think of as a rectangle) along the level in two dimensions, as depicted in Figure 1.

Figure 1.- View vs Screen Images. For scrolling, you move the view rectangle along the level rectangle

The way to achieve this in your game will obviously depend on the library or framework you are using. As I told you in this post, I will be using the SFML library, so the code explanations will be shown in C++ and using this library. However, the concept itself is the most important thing you should understand, and not any concrete technical implementation.

void LevelScreen::update(sf::Time elapsedTime) {

//We update all the objects in the screen
std::vector<Entity *>::iterator iter;
for(iter = gameObjects.begin(); iter != gameObjects.end(); iter++) {
        Entity *e = *iter;
        e->update(elapsedTime);
} 


//Now we update the view
//Horizontal scrolling
if (player->getPosition().getX() > SCREEN_WIDTH / 2) {
         view.move(player->getVelocity().getX() * elapsedTime.asSeconds(), 0);
}

//Vertical scrolling
if (player->getPosition().getY > SCREEN_HEIGHT / 2) {
        view.move(0, player->getVelocity().getY() * elapsedTime.asSeconds());
} 

}

Here, we basically update all the objects in the screen in the update method of the level (I'll give more details on the overall engine architecture in a following post). Then, we update the velocity of the view using the velocity of the player (the player variable holds a pointer to the player object). The update of the view will take place only if the player is located beyond the half of the screen in any dimension. Finally, in the draw method, we should set the view and draw the objects onto this view, as shown next:

void LevelScreen::draw(sf::RenderWindow &window) {

//Set the view to be used on the window (the window is where we draw the objects)
window.setView(view); 


//Draw the objects
std::vector<Entity *>::iterator iter;
for(iter = gameObjects.begin(); iter != gameObjects.end(); iter++) {
     Entity *e = *iter;
     e->draw(window);
}
}

This is the basic background you need in order to implement more advanced scrolling features, such as parallax scrolling. This technique will provide a higher feeling of realism with relatively little effort. I will explain how to implement it in the following post.

EDIT: you can go to the next post on parallax scrolling directly here. 

See you!

jueves, 23 de mayo de 2013

Integration: Our Best Friend (Part 2)

In the previous part of this post, we covered some mathematical foundations behind the concepts of position, velocity and acceleration. We explained that velocity is the derivative of position and that acceleration is the derivative of velocity. We also saw that derivatives represent rates of changes, and therefore, velocity is the rate of change in position and acceleration the rate of change in velocity. If velocity is constant (i.e. acceleration is 0), the rate of change in position is constant, and the position would change linearly. If on the other hand acceleration $>$ 0 (but constant), velocity would grow linearly and position would grow quadratically (i.e. forming a curve). Figure 1 shows different possibilities: stationary objects (no velocity), uniform motion (constant velocity) and motion with constants acceleration.

Figure 1 (source: http://cnx.org)

The problem that tries to solve an integrator is how to figure out (fast and efficiently) the velocity from the acceleration and the position from the velocity (i.e. doing the inverse of derivatives). And why? Because in most games, the acceleration on an object is the only information that we have.

Actually, this is not completely true. The information that we usually have is the force applied to an object (due to a collision or a hit, for example). However, as the Newton's second law states: 'The acceleration of a body is directly proportional to, and in the same direction as, the net force acting on the body, and inversely proportional to its mass'. Mathematically, this can be represented as follows:

$F = m \cdot a$     (1)

Therefore, knowing the direction and magnitude of an applied force, we can figure out the acceleration from (1):

$a = \frac{F}{m}$     (2)


At this point, we know the acceleration. We may find two different situations here, depending on whether we have constant acceleration or not. 


Constant acceleration

When we have constant acceleration, we can simply move our minds back to high school times and apply the famous equations that models how position changes when there is constant acceleration, that is:


                                              $p = p_{0} + v_{0} \cdot t + \frac{1}{2} \cdot a \cdot t^{2}$  (3)

Then, we could simply update velocity for the next iteration:

$v = v_{0} + a \cdot t$  (4)

Formulas (3) and (4) are also integration formulas, but they don't approximate: they provide the real position and velocity values. Here, in a couple of comments, they call this type of integration a ballistic or parabolic integrator, even though I haven't found any other references or entries for these names. 

In any case, the point is that if we know that acceleration is constant, we can and should use these formulas, because they provide accurate results. Euler's integrator, however, accumulates errors over the time and if the time step is big, this error grows faster. Euler's integration uses the following formulas:
$p = v \cdot t$ (5)
$v = a \cdot t$  (6)

Let's see how we could implement both integrators in C.  

  int dt = 1; //time step  
  int position = 0, velocity = 0, acceleration = 10;  
  printf("Using physics formulas\n");  
  for (i = 1; i <= limit; i++) {  
  printf("Time %d: ", i);  
  position += velocity * dt + acceleration*dt*dt/2;  
  velocity += acceleration*dt;  
  printf("Position %d, Velocity %d\n", position, velocity);  
  }  
  printf("--------------------------------\n");  
  velocity = 0, position = 0;  
  printf("Euler integration\n");  
  for (i = 1; i <= limit; i++) {  
  printf("Time %d: ", i);  
  position += velocity * dt;  
  velocity += acceleration * dt;  
  printf(" Position %d, Velocity %d\n", position, velocity);  
  }  
  
If we execute the previous code, and we change the number of iterations we can see that the higher the number of iterations, the higher the error is (that is, error is accumulating in Euler's integration). Also, if we reduce the time step (dt), we can see how the Euler's error decreases, whereas it would increase in case of a bigger time step. If you carefully see the formulas, all of this makes sense. Notice that the only difference between the 'accurate' integration and Euler integration is the position update. The former includes more information (basically an extra multiplication by 0.5 * dt^2). The smaller dt, the less significant is the difference with Euler's. Also note that velocity update is exactly the same in both methods.

As a conclusion, there is no problem with constant acceleration, as we can achieve exact results. This becomes a little trickier in non-constant acceleration situations.

Non-constant acceleration

Many physics engines have to deal with non-constant acceleration. For example, consider a force on an object that is proportional to the velocity of the object, that is:


$F = -v$    (7)

This could model the air friction, for example. In this case, and because we always assume constant mass, we deduce from (2) that if the velocity changes, the acceleration changes. In these cases, we find a differential equation:

$a = \frac{dv}{dt} = \frac{-v}{m}$      (8)

It's a ordinary differential equation (ODE) because the equation of the velocity has the derivative of the velocity in it. Analytically integrating (i.e. with paper and pen and with exact results) ODEs is tough, but integrating them numerically is pretty straightforward. We have already seen the formulas of Euler integration (5 and 6), but let's re-write them again, this time considering a time step called $h$ (instead of $t$), using the differential notation and considering explicitly the iterations with a subscript:

$p_{n+1} = p_{n} + h \cdot \frac{dp_{n}}{dx}$     (9)
$v_{n+1} = v_{n} + h \cdot \frac{dv_{n}}{dx}$  (10)

Most integration methods follow the same pattern. They evaluate the derivative (remember, the slope) of the variable we want to figure out, and they step forward in time by a fixed amount, h, on the tangent line with that slope. In the next step, they evaluate the derivative at the new position to get a new slope, taking another time step. Chris Hecker gives a very good, graphical explanation of this process here. 

Of course, Euler will have the same problems we discussed previously, but at least if we choose a sufficiently small time step (as we may find in 60 frames/second games, where the time step is approximately 0.017 seconds), results are not that bad. However,  in physics-intensive games, where you need high accuracy, or in order to avoid inaccuracy problems due to drops in frame rates, you'll need other better integration methods, and that's what I'll cover in the last post.

Concretely, I will explain Runge-Kuta order 4 and Verlet methods. I'll also explain how I dealt with all this for the game I'm working on and I'll provide a list of references that were useful to me while writing these posts. Some of them will give you more mathematical insight. 

See you!