Un poco de programar videojuegos

Las matemáticas no sirven para nada y tal…


Trigonometry for Game Programming: Part 1/2



Does the thought of doing mathematics give you cold sweats? Are you ready to give up on your career as a budding game developer because the math just doesn’t make any sense to you?

Don’t fret – math can be fun, and this cool 2-part game tutorial will back up that claim!

Here’s a little secret: as an app developer, you don’t really need to know a lot of math. If you can add or multiply two numbers together, you’re already halfway there. Most of the computations that we do in our professional lives don’t go much beyond basic arithmetic.

That said, for making games it is useful to have a few more math skills in your toolbox. You don’t need to become as smart as Archimedes or Einstein, but a basic understanding of trigonometry, combined with some common sense, will take you a long way.

In this tutorial, you will learn about some important trigonometric functions and how you can use them in your games. Then you’ll get some practice applying the theories by developing a simple spaces shooter iPhone game that requires a lot of trigonometry, using the Cocos2D game framework.

Don’t worry if you’ve never used Cocos2D before or are going to use a different framework for your game – the mathematics we’ll cover in this tutorial will apply to your engine no matter what. And you don’t need any prior experience, as I’ll walk through the process step-by-step.

If you supply the common sense, this tutorial will get you up to speed on the trig, so let’s get started!

Getting Started: It’s All About Triangles

It sounds like a mouthful, but trigonometry simply means calculations with triangles (that’s where the tricomes from).

You may not have realized it until now, but games are full of triangles. For example, imagine you have a spaceship game, and you want to calculate the distance between these ships:

Distance between ships

You have X and Y position of each ship, but how can you find the length of that line?

Well, you can simply draw a line from the center point of each ship to form a triangle like this:

Then, since you know the X and Y coordinates of each ship, you can compute the length of each of the new lines. Now that you know the lengths of two sides of the triangle, you can use some Trigonometry to compute the length of the diagonal line – the distance between the ships.

Note that one of the corners of this triangle has an angle of 90 degrees. This is also known as a right triangle, and that’s the sort of triangle you’ll be dealing with in this tutorial.

Any time you can express something in your game as a triangle with a 90-degree right angle – such as the spatial relationship between the two sprites in the picture – you can use trigonometric functions to do calculations on them.

So in summary, Trigonometry is the mathematics that you use to calculate the lengths of the sides of these triangles, as well as the angles between those sides. And that comes in handy more often that you might think.

For example, in this space ship game you might want to:

  • Have one ship shoot a laser in the direction of the other ship
  • Have one ship start moving in the direction of another ship to chase
  • Play a warning sound effect if an enemy ship is getting too close

All of this and more you can do with the power of Trigonometry!

Your Arsenal of Functions

First, let’s get the theory out of the way. Don’t worry, I’ll keep it short so you can get to the fun coding bits as quickly as possible.

These are the parts that make up a right triangle:

In the picture above, the slanted side is called the hypotenuse. It always sits across from the corner with the 90-degree angle (also called a right angle), and it is always the longest of the three sides.

The two remaining sides are called the adjacent and the opposite, as seen from one particular corner of the triangle, the bottom-left corner in this case.

If you look at the triangle from the other corner (top-right), then the adjacent and opposite change places:

Alpha (α) and beta (β) are the names of the two other angles. You can call these angles anything you want (as long as it sounds Greek!) but usually alpha is the angle in the corner of interest and beta is the angle in the opposing corner. In other words, you label your opposite and adjacent sides with respect to alpha.

The cool thing is that if you only know two of these things, trig allows you to find out all the others using the sine, cosine and tangent functions. For example, if you know an angle and the length of one of the sides, then the sine, cosine and tangent functions can tell you the length of the other sides:

Think of the sin, cos, and tan functions as “black boxes” – you plug in numbers and get back results. They are pre-written functions you can call from almost any programming language.

Know Angle and Length, Need Sides

Let’s consider an example. Say you know the alpha angle between the ships is 45 degrees, and the length between the ships (the hypotenuse) is 10 points long. You can then plug these values into the formula:

sin(45) = opposite / 10

To solve this for the hypotenuse, you shift things around a bit:

opposite = sin(45) * 10

If you call the built-in sin function, you’ll find the sine of 45 degrees is 0.707 (rounded off), and filling that in that gives you the result:

opposite = 0.707 * 10 = 7.07

There is a handy mnemonic for remembering what these functions do that you may remember from high school: SOH-CAH-TOA (where SOH stands for Sine is Opposite over Hypotenuse, and so on), or if you need something more catchy: Some Old Hippy / Caught Another Hippy / Tripping On Acid. (That hippy was probably a mathematician who did a little too much trig.) :]

Know 2 Sides, Need Angle

The above formulas are useful when you already know an angle, but that is not always the case – sometimes it is the angle you are looking for. Then you need to know the lengths of at least two of the sides and plug these into the inverse functions:

Inverse trig functions

  • angle = arcsin(opposite/hypotenuse)
  • angle = arccos(adjacent/hypotenuse)
  • angle = arctan(opposite/adjacent)

In other words, if sin(a) = b, then it is also true that arcsin(b) = a. Of these inverse functions, you will use the arc tangent (arctan) the most in practice. Sometimes these functions are also notated as sin-1, cos-1, and tan-1, so don’t let that fool you.

Is any of this sinking in or sounding familiar? Good, but you’re not done yet with the theory lesson – there is still more that you can calculate with triangles.

Know 2 Sides, Need Remaining Side

Sometimes you may know the length of two of the sides and need to know the length of the third, like in the example at the beginning of this tutorial where you wanted to find the distance between the two space ships.

This is where Trigonometry’s Pythagorean Theorem comes to the rescue. Even if you forgot everything else about math, this is probably the one formula you do remember:

a2 + b2 = c2

Or, put in terms of the triangle that you saw earlier:

opposite2 + adjacent2 = hypotenuse2

If you know any two of these sides, then calculating the third is simply a matter of filling in the formula and taking the square root. This is a very common thing to do in games and you’ll be seeing it several times in this tutorial.

Note: Want to drill this formula into your head while having a great laugh at the same time? Search YouTube for “Pythagoras song” – it’s an inspiration for many!

Have Angle, Need Other Angle

Lastly, the angles. If you know one of the non-right angles from the triangle, then figuring out the other ones is a piece of cake. In a triangle, all angles always add up to a total of 180 degrees. Because this is a right triangle, you already know that one of the angles is 90 degrees. That leaves:

alpha + beta + 90 = 180

Or simply:

alpha + beta = 90

The remaining two angles must add up to 90 degrees. So if you know alpha, you also know beta, and vice-versa.

And those are all the formulas you need to know! Which one to use in practice depends on the pieces that you already have. Usually you either have the angle and the length of at least one of the sides, or you don’t have the angle but you do have two of the sides.

Enough theory. Let’s put this stuff into practice.

To Skip, or Not to Skip?

In the next few sections, you will be setting up a basic Cocos2D project with a space ship that can move around the screen using the accelerometer. This won’t involve any trigonometry (yet), so if you already know Cocos2D and feel like this guy:

"F that!" guy

Then feel free to skip ahead to the Begin the Trigonometry! section below – I have a starter project waiting for you there.

But if you’re the type who likes to code everything from scratch, keep reading! :]

Getting Started

To get started, download the latest version of the Cocos2D v2.1 branch. At the time of writing, this is the “unstable” version cocos2d-iphone-2.1-rc1.

After Cocos2D is done downloading and unzipping, you want to install the project templates. Open a Terminal window to the directory where you downloaded Cocos2D and enter the following command:

./install-templates.sh -f

You should see “Installing cocos2d templates” and a bunch of messages. Now you’re ready to work with Cocos2D.

Fire up Xcode and create a new application from the “cocos2d iOS” template you just installed.

Name the project TrigBlaster and set the device family to iPhone. Build and run the template as-is. If all works OK, you should see the following:

You are going to use ARC in this project, but Cocos2D projects have it disabled by default. Luckily, enabling ARC is really easy. Just go to Edit\Refactor\Convert to Objective-C ARC. Expand the drop-down and select only the last four files (main.m, AppDelegate.m, HelloWorldLayer.m, and IntroLayer.m), then click Check and finish the steps in the wizard.

Note: When you convert a project to ARC or make other large changes, Xcode will prompt you to enable snapshots for the current project. A snapshot saves the state of the entire project as if you copied and pasted the project into another directory. You can learn more about snapshots over here. For the purposes of this tutorial, select disable.

Next download the resources for this tutorial. This file contains the images for the sprites and the sound effects. Unzip it and drag the Images and Sounds folders into Xcode to add them to the project. In the import dialog, make sure Copy items into destination group’s folder is checked.

Import Resources into Project

Great, the preliminaries are over and done with – now let’s get coding for real.

Steering with Accelerometers

Because this is a simple game, you will be doing all your work inside a single class: the HelloWorldLayer. Right now, this layer contains a bunch of stuff that you don’t need.

Replace the contents of HelloWorldLayer.h with:

#import "cocos2d.h"
@interface HelloWorldLayer : CCLayerColor
+ (CCScene *)scene;

This game doesn’t use GameKit, so you got rid of that. You also changed HelloWorldLayer from a plain CCLayerto a CCLayerColor so that you can have a background color other than just black.

There is also a bunch of code in the .m file that you don’t need for this game. Replace HelloWorldLayer.m with:

#import "HelloWorldLayer.h"
#import "SimpleAudioEngine.h"
@implementation HelloWorldLayer
+ (CCScene *)scene
    CCScene *scene = [CCScene node];
    HelloWorldLayer *layer = [HelloWorldLayer node];
    [scene addChild:layer];
    return scene;
- (id)init
    if ((self = [super initWithColor:ccc4(94, 63, 107, 255)]))
    return self;

The scene method is unchanged from the template, but init now calls [super initWithColor] to set a purple background color on the layer.

Build and run, and you should see nothing but purple:

Let’s make things a bit more exciting by adding a spaceship to the scene. You will need some instance variables for this, so modify the @implementation line in HelloWorldLayer.m as follows:

@implementation HelloWorldLayer
    CGSize _winSize;
    CCSprite *_playerSprite;

The _winSize variable stores the dimensions of the screen, which is useful because you will be referring to that quite often. The _playerSprite variable holds the spaceship sprite.

Now change init to the following:

- (id)init
    if ((self = [super initWithColor:ccc4(94, 63, 107, 255)]))
        _winSize = [CCDirector sharedDirector].winSize;
        _playerSprite = [CCSprite spriteWithFile:@"Player.png"];
        _playerSprite.position = ccp(_winSize.width - 50.0f, 50.0f);
        [self addChild:_playerSprite];
    return self;

This is all pretty basic if you have worked with Cocos2D before. The player sprite is positioned in the bottom-right corner of the screen. Remember that with Cocos2D, it is the bottom of the screen that has y-coordinate 0, unlike in UIKit, where y = 0 points to the top of the screen.

Build and run to try it out, and you should see the following:

To move the spaceship, this game uses the iPhone’s built-in accelerometers. Unfortunately, the iOS Simulator cannot simulate the accelerometers. That means that from now on, you will need to run the app on your device to test it.

Note: If you are unsure how to put the app on your device, check out this extensive tutorial that explains how to obtain and install the certificates and provisioning profiles that allow Xcode to run apps on your device. It’s not as intimidating as it looks, but you do need to sign up for the paid Apple developer program.

To move the spaceship with the accelerometers, you’ll obviously be rocking your device from side to side. During testing I found that this sometimes caused the screen to autorotate from landscape right to landscape left, which is really annoying when you’re in the middle of a heated battle.

To prevent that from happening, go into the Target Settings screen and in the Summary tab under Supported Interface Orientations, de-select all options except for Landscape Right.

Using the accelerometers from code is pretty straightforward. You first ask Cocos2D to activate the accelerometers. Once enabled, it sends you periodic updates with the values of the three accelerometers that are built into the iPhone. You then use these values to change the speed of the spaceship.

First, add new instance variables to keep track of the accelerometer values. You only store the values for two of the accelerometers; the “Z” one isn’t used by this game.

@implementation HelloWorldLayer
    . . .
    UIAccelerationValue _accelerometerX;
    UIAccelerationValue _accelerometerY;

A good place to activate the accelerometers is inside init. Add the following line to it:

self.accelerometerEnabled = YES;

Finally, add the method that receives the accelerometer values:

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
    const double FilteringFactor = 0.75;
    _accelerometerX = acceleration.x * FilteringFactor + _accelerometerX * (1.0 - FilteringFactor);
    _accelerometerY = acceleration.y * FilteringFactor + _accelerometerY * (1.0 - FilteringFactor);

This bit of logic is necessary to filter – or “smoothen” – the data that you get back from the accelerometers so that it appears less jittery.

Note: An accelerometer records how much gravity currently pulls on it. Because the user is holding the iPhone in her hands, and hands are never completely steady, there are a lot of tiny fluctuations in this gravity value. We are not so much interested in these unsteady motions as in the larger changes in orientation that the user makes to the device. By applying this simple low-pass filter, you retain this orientation information but filter out the less important fluctuations.

Now that you have a stable measurement of the device’s orientation, how can you use this to make the player’s spaceship move?

Movement in games often works like this:

  1. Set the acceleration based on some form of user input, in this case from the accelerometer values.
  2. Add the new acceleration to the spaceship’s current speed. This makes the object speed up or slow down, depending on the direction of the acceleration.
  3. Add the new speed to the spaceship’s position to make it move.

Of course, you have a great mathematician to thank for these equations: Sir Isaac Newton!

You need some more instance variables to pull this off. There is no need to keep track of the player’s position because the CCSprite already does that for you, but acceleration and speed are your own responsibility.

Add these instance variables:

@implementation HelloWorldLayer
    . . .
    float _playerAccelX;
    float _playerAccelY;
    float _playerSpeedX;
    float _playerSpeedY;

It’s good to set some bounds on how fast the spaceship can travel or it would be pretty hard to maneuver. Infinite acceleration sounds like a good idea in theory but in practice it doesn’t work out so well (besides, even Einstein thinks there are limits to how fast you can go).

Add the following lines directly below the #import statement:

const float MaxPlayerAccel = 400.0f;
const float MaxPlayerSpeed = 200.0f;

This defines two constants, the maximum acceleration (400 points per second squared) and the maximum speed (200 points per second).

Now add the following bit of logic to the bottom of accelerometer:didAccelerate::

if (_accelerometerY > 0.05)
    _playerAccelX = -MaxPlayerAccel;
else if (_accelerometerY < -0.05)
    _playerAccelX = MaxPlayerAccel;
if (_accelerometerX < -0.05)
    _playerAccelY = -MaxPlayerAccel;
else if (_accelerometerX > 0.05)
    _playerAccelY = MaxPlayerAccel;

This is a basic technique for controlling a sprite using the accelerometers. When the device is tilted to the left, you give the player maximum acceleration to the left. Conversely, when the device is tilted to the right, you give the player maximum acceleration to the right. Likewise for the up and down directions.

Note: You’re using the _accelerometerY value for the x-direction. That’s as it should be. Remember that this game is in landscape, so the Y-accelerometer runs from left to right in this orientation, and the X-accelerometer from top to bottom.

You’re almost there. The last step is applying the _playerAccelX and Y values to the speed and position of the spaceship. You will do this in the game’s update method. This method is called 60 times per second, so it’s the natural place to perform all of the game logic.

Add updatePlayer to the class:

- (void)updatePlayer:(ccTime)dt
    // 1
    _playerSpeedX += _playerAccelX * dt;
    _playerSpeedY += _playerAccelY * dt;
    // 2
    _playerSpeedX = fmaxf(fminf(_playerSpeedX, MaxPlayerSpeed), -MaxPlayerSpeed);
    _playerSpeedY = fmaxf(fminf(_playerSpeedY, MaxPlayerSpeed), -MaxPlayerSpeed);
    // 3
    float newX = _playerSprite.position.x + _playerSpeedX*dt;
    float newY = _playerSprite.position.y + _playerSpeedY*dt;
    // 4
    newX = MIN(_winSize.width, MAX(newX, 0));
    newY = MIN(_winSize.height, MAX(newY, 0));
    _playerSprite.position = ccp(newX, newY);

If you’ve programmed games before (or studied physics), then this should look very familiar. Here’s how it works:

  1. Add the current acceleration to the speed.The acceleration is expressed in points per second (actually, per second squared, but don’t worry about that) but update: is performed a lot more often than once per second. To compensate for this difference, you multiply the acceleration by the elapsed or “delta” time, dt. Without this, the spaceship would move about sixty times faster than it should!
  2. Clamp the speed so that it doesn’t go faster than MaxPlayerSpeed if it is positive or -MaxPlayerSpeed if it is negative. You could write this using an if statement instead:
    if (_playerSpeedX < -MaxPlayerSpeed) 
        _playerSpeedX = -MaxPlayerSpeed;
    else if (_playerSpeedX > MaxPlayerSpeed) 
        _playerSpeedX = MaxPlayerSpeed;

    However, I like the succinctness of the one-line version. fminf() makes sure the speed doesn’t become larger than MaxPlayerSpeed because it always picks the smallest of the two, while fmaxf() makes sure the speed doesn’t drop below -MaxPlayerSpeed because it always picks the largest value. It’s a neat little trick.

  3. Add the current speed to the sprite’s position. Again, speed is measured in points per second, so you need to multiply it by the delta time to make it work correctly.
  4. Clamp the new position to the sides of the screen. You don’t want the player’s spaceship to go offscreen, never to be found again!

Finally, add the following line to init to make update active:

[self scheduleUpdate];

Then add update itself:

- (void)update:(ccTime)dt
    [self updatePlayer:dt];

That should do it. Build and run the game. You can now control the spaceship by tilting the device.

Moving the ship with the accelerometer

Begin the Trigonometry!

If you skipped ahead to this section, here is the starter project at this point. Build and run it on your device – you’ll see there’s a spaceship that you can move around with the accelerometer.

You haven’t seen any trigonometry yet, so let’s put some into action.

Note: If you’ve used Cocos2D before, you might know Cocos2D comes with handy built-in methods like ccpLength, ccpAngle, and more that are wrappers over the raw trigonometry functions for ease of use. In this tutorial, you will not be using these functions – instead you will be going low level and issuing the raw trigonometry calls yourself, for the learning experience. In an actual game, you might want to use the wrapper methods however.

It would be cool – and much less confusing to the player! – to rotate the spaceship in the direction it is currently moving rather than having it always pointing upward.

To rotate the spaceship, you need to know the angle to rotate it. But you don’t know what that is, so how can you figure that out?

Let’s think about what you do know. You do have the player’s speed, which consists of two components: a speed in the x-direction and a speed in the y-direction:

If you rearrange these a little, you can see that they form a triangle:

Here you know the lengths of the adjacent (_playerSpeedX) and the opposite (_playerSpeedY) sides.

So basically, you know 2 sides of a right triangle, so you are in the Know 2 Sides, Need Angle case mentioned in the beginning of this tutorial. That means you need to use one of the inverse functions: arcsin, arccos or arctan.

You know the opposite and adjacent sides, so you want to use the arctan function to find the angle to rotate the ship. Remember, that looks like the following:

angle = arctan(opposite / adjacent)

The Objective-C math library comes with the atan() function that computes the arc tangent, but it has one big issue: what if the x-speed is 0? In that case, the adjacent is 0 and dividing by 0 is mathematically undefined. Your app might crash or just behave weirdly when that happens.

Instead of using atan(), it is better to use the function atan2(), which takes two parameters and correctly handles the division-by-zero scenario without you having to worry about it:

angle = atan2(opposite, adjacent)

Important: The angle that atan2f() gives you is not the inner angle inside the triangle, but the angle that the hypotenuse makes with that 0-degree line:

This is another reason why atan2() is a lot more useful than plain, old atan().

So let’s give that a shot. Add the following two lines to the bottom of updatePlayer:

float angle = atan2f(_playerSpeedY, _playerSpeedX);
_playerSprite.rotation = angle;

Note that the arctan function you are using is actually called atan2f() instead of just atan2(). More about that in a moment. Also notice that the y-coordinate goes first. A common mistake is to write atan2f(x, y) but that’s the wrong way around. Remember the first parameter is the opposite, and in this case the Y coordinate is the opposite.

Build and run the app to try it out:

Non-rotating ship

Hmm, this doesn’t seem to be working quite right. What is wrong here?

Radians vs. Degrees

Normal human beings tend to think of angles as values between 0 and 360. Mathematicians, however, measure angles in radians, which are expressed in terms of π (the Greek letter Pi, which sounds like pie but doesn’t taste as good).

It’s not essential to understand, but if you’re curious, one radian is the angle you get when you travel the distance of the radius along the arc of the circle. You can do that 2π times (roughly 6.28 times) before you end up at the beginning of the circle again.

So while you may think of angles as values from 0 to 360, a mathematician sees values from 0 to 2π. And that’s where your problem lies. atan2f() returns a value in radians but Cocos2D’s sprite rotation property expects degrees. That’s why you only saw the sprite rotate a little: angles measured in radians are much smaller than angles measured in degrees.

Fortunately, it is easy to convert from one to the other. Change the line that sets _playerSprite.rotation to:

_playerSprite.rotation = CC_RADIANS_TO_DEGREES(angle);

The CC_RADIANS_TO_DEGREES macro is Cocos2D’s way of doing the conversion but you can easily write your own function or macro to do this. I don’t have these formulas memorized but they are easy enough to derive yourself when you realize than an angle of 360 degrees corresponds to 2π:

Angle in degrees / 360 degrees = Angle in radians / 2π radians

To go from radians to degrees, the formula becomes:

Angle in degrees = (Angle in radians / 2π) * 360

And the other way around, from degrees to radians:

Angle in radians = (Angle in degrees / 360) * 2π

I point this out because forgetting to convert between radians and degrees is probably the most common mistake programmers make when they are dealing with trigonometry! So if you don’t see the rotation you expected, make sure you’re not mixing up your degrees and radians…

So what the @#! is π? Pi is the ratio of the circumference of a circle to its diameter. In other words, if you measure the outside of any circle and divide it by its diameter (which is twice the radius), you get the number 3.141592… and that is what we call π. It takes 2π radians to go all the way around a circle, which is why 360 degrees corresponds to 2π. Pi is a very important concept in mathematics that shows up all the time, especially with anything that is cyclical.

By the way, not everyone likes π. Some people believe that it would have been better to choose the ratio of the circumference to the radius, instead of to the diameter. This number is called tau (τ) and is equal to 2π, thus simplifying many of the calculations. You can read more about tau at tauday.com.

Anyway, back to the game. Build and run to see some glorious rotation in action.

Rotating ship, but opposite

Whoops, something is still not right. The spaceship certainly rotates but it seems to be pointing in the direction opposite to where it’s flying!

Here’s what’s happening: the sprite for the spaceship points straight up, which corresponds to the default rotation value of 0 degrees. But in mathematics, an angle of 0 degrees (or radians) doesn’t point upward, but to the right:

And that’s not the only problem: in Cocos2D, rotation happens in a clockwise direction, but in mathematics it goes counterclockwise.

To overcome these differences, change the line to:

_playerSprite.rotation = 90.0f - CC_RADIANS_TO_DEGREES(angle);

This adds 90 degrees to make the sprite point to the right at an angle of 0 degrees, so that it lines up with the way atan2f() does things. Then it adds the negative angle – in other words, subtracts the angle – in order to rotate the proper way around.

Build and run once more to try it out. You’ll finally have a spaceship that has its head on straight!

Spaceship flying with correct rotation

Bouncing Off the Walls

You have a spaceship that you can move using the accelerometers and you’re using trig to make sure it points in the direction it’s flying. That’s a good start.

Unfortunately, having the spaceship get stuck on the edges of the screen isn’t very satisfying. You’re going to fix that by making it bounce off the screen borders instead.

First, comment these lines from updatePlayer:

//newX = MIN(_winSize.width, MAX(newX, 0));
//newY = MIN(_winSize.height, MAX(newY, 0));

Then add the following code to updatePlayer, just after the commented lines:

BOOL collidedWithVerticalBorder = NO;
BOOL collidedWithHorizontalBorder = NO;
if (newX < 0.0f)
    newX = 0.0f;
    collidedWithVerticalBorder = YES;
else if (newX > _winSize.width)
    newX = _winSize.width;
    collidedWithVerticalBorder = YES;
if (newY < 0.0f)
    newY = 0.0f;
    collidedWithHorizontalBorder = YES;
else if (newY > _winSize.height)
    newY = _winSize.height;
    collidedWithHorizontalBorder = YES;

This checks whether the spaceship hit any of the screen borders and if so, sets a BOOL variable to YES. But what to do after such a collision takes place? To make the spaceship bounce off the border, you can simply reverse its speed and acceleration.

First, define a constant at the top of the file, above the @implementation line:

const float BorderCollisionDamping = 0.4f;

Add the following lines in updatePlayer, directly below the code you last added there:

if (collidedWithVerticalBorder)
    _playerAccelX = -_playerAccelX * BorderCollisionDamping;
    _playerSpeedX = -_playerSpeedX * BorderCollisionDamping;
    _playerAccelY = _playerAccelY * BorderCollisionDamping;
    _playerSpeedY = _playerSpeedY * BorderCollisionDamping;
if (collidedWithHorizontalBorder)
    _playerAccelX = _playerAccelX * BorderCollisionDamping;
    _playerSpeedX = _playerSpeedX * BorderCollisionDamping;
    _playerAccelY = -_playerAccelY * BorderCollisionDamping;
    _playerSpeedY = -_playerSpeedY * BorderCollisionDamping;

If a collision registered, you flip the acceleration and speed values around. Notice that this also multiplies the acceleration and speed by a damping value, BorderCollisionDamping.

As usually happens in a collision, some of the movement energy is dissipated by the impact. In this case, you make the spaceship retain only 40% of its speed after bumping into the screen edges.

Try it out. Smash the spaceship into the border and see what happens. Who said spaceships can’t bounce?

Bouncing spaceship

For fun, play with the value of BorderCollisionDamping to see the effect of different values for this constant. If you make it larger than 1.0f, the spaceship actually gains energy from the collision.

Note: Now why is there an f behind those numbers in the code: 0.4f, 0.1f, 0.0f, and so on? And why did you use atan2f() instead of just atan2()? When you write games, you want to work with floating point numbers as much as possible because, unlike integers, they allow for digits behind the decimal point. This allows you to be much more precise.

There are two types of floating point numbers: floats and doubles (there is also a “long double”, but that’s the same as a double on the iPhone). Doubles are more precise than floats but they also take up more memory and are slower in practice. When you don’t put the f behind the number and just use 0.4, 0.1, 0.0, or when you use the version of a math function without the f suffix, you are working with doubles and not floats.

It doesn’t really matter if you use a double here and there. For example, the time value that CACurrentMediaTime() returns is a double. However, if you’re doing hundreds of thousands of calculations every frame, you will notice the difference. I did a quick test on a couple of my devices and the same calculations using doubles were 1.5 to 2 times slower. So it’s a good habit to stick to regular floats where you can.

You may have noticed a slight problem. Keep the spaceship aimed at the bottom of the screen so that it continues smashing into the border over and over, and you’ll see a constant flicker between the up and down angles.

Using the arc tangent to find the angle between a pair of x- and y-components works quite well, but only if those x and y values are fairly large. In this case, the damping factor has reduced the speed to almost zero. When you apply atan2f() to very small values, even a tiny change in these values can result in a big change in the resulting angle.

One way to fix this is to not change the angle when the speed is very slow. That sounds like an excellent reason to give a call to our old friend, Pythagoras.


Right now you don’t have such a thing as “the ship’s speed”. Instead, you have two speeds: one in the x-direction and one in the y-direction. But in order to draw any conclusions about “the ship’s speed” – is it too slow to actually rotate the ship? – you need to combine these x and y speed values into one single value:

Here you are in the Know 2 Sides, Need Remaining Side case discussed earlier.

As you can see, the true speed of the spaceship, that is, how many points it moves across the screen in a second, is the hypotenuse of the triangle that is formed by the speed in the x-direction and the speed in the y-direction. Put in terms of the Pythagorean formula:

true speed2 = _playerSpeedX2 + _playerSpeedY2

To find the actual value, you need to take the square root:

true speed = √(_playerSpeedX2 + _playerSpeedY2)

Add this code to updatePlayer. First remove this block of code:

float angle = atan2f(_playerSpeedY, _playerSpeedX);
_playerSprite.rotation = 90.0f - CC_RADIANS_TO_DEGREES(angle);

And replace it with this block of code:

float speed = sqrtf(_playerSpeedX*_playerSpeedX + _playerSpeedY*_playerSpeedY);
if (speed > 40.0f)
    float angle = atan2f(_playerSpeedY, _playerSpeedX);
    _playerSprite.rotation = 90.0f - CC_RADIANS_TO_DEGREES(angle);

Build and run. You’ll see the spaceship now acts a lot more stable at the edges of the screen. If you’re wondering where the value 40.0f came from, the answer is: experimentation. I put some NSLog() statements into the code to look at the speeds at which the craft typically hit the borders, and then I tweaked this value until it felt right.

Blending Angles for Smooth Rotation

Of course, fixing one thing always breaks something else. Try slowing down the spaceship until it has stopped, then flip the device so the spaceship has to turn around and fly the other way.

Previously, that happened with a nice animation where you actually saw the ship turning. But because you just added some code that prevents the ship from changing its angle at low speeds, the turn is now very abrupt. It’s only a small detail, but it is the details that make great products.

The fix is to not switch to the new angle immediately, but to gradually “blend” it with the previous angle over a series of successive frames. This re-introduces the turning animation and still prevents the ship from rotating when it is not moving fast enough.

Blending sounds fancy, but it’s actually quite easy to implement. It does require you to keep track of the spaceship’s angle between updates, so add a new instance variable for it in the implementation block in HelloWorldLayer.m:

@implementation HelloWorldLayer
    float _playerAngle;

Change the rotation code in updatePlayer from this:

float speed = sqrtf(_playerSpeedX*_playerSpeedX + _playerSpeedY*_playerSpeedY);
if (speed > 40.0f)
    float angle = atan2f(_playerSpeedY, _playerSpeedX);
    _playerSprite.rotation = 90.0f - CC_RADIANS_TO_DEGREES(angle);

To this:

float speed = sqrtf(_playerSpeedX*_playerSpeedX + _playerSpeedY*_playerSpeedY);
if (speed > 40.0f)
    float angle = atan2f(_playerSpeedY, _playerSpeedX);
    const float RotationBlendFactor = 0.2f;
    _playerAngle = angle * RotationBlendFactor + _playerAngle * (1.0f - RotationBlendFactor);
_playerSprite.rotation = 90.0f - CC_RADIANS_TO_DEGREES(_playerAngle);

The _playerAngle variable combines the new angle and its own previous value by multiplying them with a blend factor. In human-speak, this means the new angle only counts for 20% towards the actual rotation that you set on the spaceship. Of course, over time more and more of the new angle gets added so that eventually the spaceship does point in the proper direction.

Note that the line that sets the _playerSprite’s rotation property is now outside the if statement.

Build and run to verify that there is no longer an abrupt change from one rotation angle to another.

Now try flying in a circle a couple of times, both clockwise and counterclockwise. You’ll notice that at some point in the turn the spaceship suddenly spins in the opposite direction. It always happens at the same point in the circle. What’s going on?

Well, there is something you should know about atan2f(). It does not return an angle in the convenient range of 0 to 360 degrees, but a value between +π and –π radians, or between +180 and -180 degrees to us non-mathematicians:

That means if you’re turning counterclockwise, at some point the angle will jump from +180 degrees to -180 degrees; or the other way around if you’re turning clockwise. And that’s where the weird spinning effect happens.

The problem is that when the new angle jumps from 180 degrees to -180 degrees, _playerAngle is still positive because it is trailing behind a bit. When you blend these two together, the spaceship actually starts turning the other way around. It took me a while to figure out what was causing this!

To fix it, you need to recognize when the angle makes that jump and adjust _playerAngle accordingly. Add a new instance variable at the bottom of the HelloWorldLayer implementation block:

@implementation HelloWorldLayer
    float _lastAngle;

And change the rotation code one more time from this:

float speed = sqrtf(_playerSpeedX*_playerSpeedX + _playerSpeedY*_playerSpeedY);
if (speed > 40.0f)
    float angle = atan2f(_playerSpeedY, _playerSpeedX);
    const float RotationBlendFactor = 0.2f;
    _playerAngle = angle * RotationBlendFactor + _playerAngle * (1.0f - RotationBlendFactor);
_playerSprite.rotation = 90.0f - CC_RADIANS_TO_DEGREES(_playerAngle);

To this:

float speed = sqrtf(_playerSpeedX*_playerSpeedX + _playerSpeedY*_playerSpeedY);
if (speed > 40.0f)
    float angle = atan2f(_playerSpeedY, _playerSpeedX);
    // Did the angle flip from +Pi to -Pi, or -Pi to +Pi?
    if (_lastAngle < -3.0f && angle > 3.0f)
        _playerAngle += M_PI * 2.0f;
    else if (_lastAngle > 3.0f && angle < -3.0f)
        _playerAngle -= M_PI * 2.0f;
    _lastAngle = angle;
    const float RotationBlendFactor = 0.2f;
    _playerAngle = angle * RotationBlendFactor + _playerAngle * (1.0f - RotationBlendFactor);
_playerSprite.rotation = 90.0f - CC_RADIANS_TO_DEGREES(_playerAngle);

Build and run. That’ll fix things right up and you should have no more problems turning your spacecraft!

This may have seemed like an arcane little problem not worth so much time, but it’s good to be aware that atan2f() gives you angles from -180 degrees (or –π radians) to +180 degrees (or π radians). If you’re using arc tangent to calculate an angle and you get weird behavior like the spinning you saw here, then you might need to verify that your angles really are what you expect them to be.

Using Trig to Find Your Target

This is a great start – you have a spaceship moving along pretty smoothly! But so far the spaceship’s life is too easy and carefree. Let’s spice this up by adding an enemy: a big cannon!

Add two new instance variables in the implementation block in HelloWorldLayer.m:

@implementation HelloWorldLayer
    CCSprite *_cannonSprite;
    CCSprite *_turretSprite;

You’ll set these sprites up in init. Place this code before the creation of _playerSprite so that the spaceship always gets drawn “above” the cannon:

_cannonSprite = [CCSprite spriteWithFile:@"Cannon.png"];
_cannonSprite.position = ccp(_winSize.width/2.0f, _winSize.height/2.0f);
[self addChild:_cannonSprite];
_turretSprite = [CCSprite spriteWithFile:@"Turret.png"];
_turretSprite.position = ccp(_winSize.width/2.0f, _winSize.height/2.0f);
[self addChild:_turretSprite];

The cannon consists of two sprites: the fixed base and the turret that can rotate to take aim at the player. Build and run, and you should have a brand-new cannon sitting smack in the middle of the screen.

Now you’ll give the cannon a target to snipe at – I bet you know who!

Yep, its turret should point at the player at all times. To get this to work, you need to figure out the angle to rotate the turret so that it points toward the player.

Figuring this out will be very similar to how you figured out how to rotate the spaceship in order to point toward the direction it’s moving in. The difference is that this time, the triangle won’t be based on the speed of the spaceship. Instead it will be drawn between the center positions of the two sprites:

Again, you can use atan2f() to calculate this angle. Add the following method:

- (void)updateTurret:(ccTime)dt
	float deltaX = _playerSprite.position.x - _turretSprite.position.x;
	float deltaY = _playerSprite.position.y - _turretSprite.position.y;
	float angle = atan2f(deltaY, deltaX);
	_turretSprite.rotation = 90.0f - CC_RADIANS_TO_DEGREES(angle);

The deltaX and deltaY variables measure the distance between the player sprite and the turret sprite. You plug these values into atan2f() to get angle of rotation.

As before, you need to convert this angle to degrees and adjust for the differences between mathematics and Cocos2D. Remember that atan2() always gives you the angle between the hypotenuse and the 0-degree line. It is not the angle inside the triangle.

Don’t forget to call this new updateTurret: method from update, or nothing much will happen:

- (void)update:(ccTime)dt
    [self updatePlayer:dt];
    [self updateTurret:dt];

Build and run. The cannon is now always pointing at the spaceship. See how easy that was? That’s the power of trig for you!

Turret pointed towards player

Challenge: It is unlikely that a real cannon would be able to act so instantaneously – it would have to be able to predict exactly where the target was going. Instead, a real cannon would always be playing catch up.

You can accomplish this by “blending” the old angle with the new one, just like you did earlier. The smaller the blend factor, the more time the turret needs to catch up with the spaceship. See if you can implement this on your own.

Adding Health Bars… That Move!

Soon the player will be able to fire missiles at the cannon, and the cannon will be able to inflict damage on the player. To show the amount of hit points each object has remaining, you will add health bars to the scene using CCDrawNode, a new feature of Cocos2D v2.1.

First, you have to do some prep. Add a couple of new constants to the top of the file:

const int MaxHP = 100;
const float HealthBarWidth = 40.0f;
const float HealthBarHeight = 4.0f;

Also add a couple of new instance variables in the implementation block:

@implementation HelloWorldLayer
    int _playerHP;
    int _cannonHP;
    CCDrawNode *_playerHealthBar;
    CCDrawNode *_cannonHealthBar;

Add the following to the bottom of init to set up these new variables:

_playerHealthBar = [[CCDrawNode alloc] init];
_playerHealthBar.contentSize = CGSizeMake(HealthBarWidth, HealthBarHeight);
[self addChild:_playerHealthBar];
_cannonHealthBar = [[CCDrawNode alloc] init];
_cannonHealthBar.contentSize = CGSizeMake(HealthBarWidth, HealthBarHeight);
[self addChild:_cannonHealthBar];
_cannonHealthBar.position = ccp(
    _cannonSprite.position.x - HealthBarWidth/2.0f + 0.5f,
    _cannonSprite.position.y - _cannonSprite.contentSize.height/2.0f - 10.0f + 0.5f);
_playerHP = MaxHP;
_cannonHP = MaxHP;

The _playerHealthBar and _cannonHealthBar objects are instances of CCDrawNode, which is like a sprite except that you can draw arbitrary shapes into it. That is ideal for your health bars, which consist of a border and a filled rectangle.

Note that you placed the _cannonHealthBar sprite slightly below the cannon, but didn’t assign a position to the _playerHealthBar yet. That’s because the cannon never moves, so you can simply set the position of its health bar once and forget about it.

However, whenever the spaceship moves, you have to adjust the position of the _playerHealthBar as well. That happens in updatePlayer. Add the following lines to the bottom of that method:

_playerHealthBar.position = ccp(
    _playerSprite.position.x - HealthBarWidth/2.0f + 0.5f,
    _playerSprite.position.y - _playerSprite.contentSize.height/2.0f - 15.0f + 0.5f);

Now all that’s left is drawing the bars themselves. Add this new method to the bottom of the file:

- (void)drawHealthBar:(CCDrawNode *)node hp:(int)hp
    [node clear];
    CGPoint verts[4];
    verts[0] = ccp(0.0f, 0.0f);
    verts[1] = ccp(0.0f, HealthBarHeight - 1.0f);
    verts[2] = ccp(HealthBarWidth - 1.0f, HealthBarHeight - 1.0f);
    verts[3] = ccp(HealthBarWidth - 1.0f, 0.0f);
    ccColor4F clearColor = ccc4f(0.0f, 0.0f, 0.0f, 0.0f);
    ccColor4F fillColor = ccc4f(113.0f/255.0f, 202.0f/255.0f, 53.0f/255.0f, 1.0f);
    ccColor4F borderColor = ccc4f(35.0f/255.0f, 28.0f/255.0f, 40.0f/255.0f, 1.0f);
    [node drawPolyWithVerts:verts count:4 fillColor:clearColor borderWidth:1.0f borderColor:borderColor];
    verts[0].x += 0.5f;
    verts[0].y += 0.5f;
    verts[1].x += 0.5f;
    verts[1].y -= 0.5f;
    verts[2].x = (HealthBarWidth - 2.0f)*hp/MaxHP + 0.5f;
    verts[2].y -= 0.5f;
    verts[3].x = verts[2].x;
    verts[3].y += 0.5f;
    [node drawPolyWithVerts:verts count:4 fillColor:fillColor borderWidth:0.0f borderColor:clearColor];

This sets up an array of points for the corners of the rectangle that you’ll be drawing, then draws it twice: once for the border, which always has the same size, and once for the amount of health, which changes depending on the number of remaining hit points.

Of course, you need to call this method, once for the player and once for the cannon. Add these two lines to update:

[self drawHealthBar:_playerHealthBar hp:_playerHP];
[self drawHealthBar:_cannonHealthBar hp:_cannonHP];

Build and run. Now both the player and the enemy have health bars:

Using Trig for Collision Detection

Right now, the spaceship can fly directly over the cannon without consequence. It would be more fun if it didn’t have it so easy and instead suffered damage for colliding with the cannon. This is where this tutorial enters the sphere of collision detection (don’t miss that pun).

At this point, a lot of game devs think, “I need a physics engine!” and reach for Box2D. While it’s certainly true that you can use Box2D for this, it’s not that hard to do collision detection yourself, especially when you can use circles.

Detecting whether two circles intersect is a piece of cake: all you have to do is look at the distance between them (*cough* Pythagoras) and see if it is smaller than the radius of both circles.

Add two new constants to the top of HelloWorldLayer.m:

const float CannonCollisionRadius = 20.0f;
const float PlayerCollisionRadius = 10.0f;

These are the sizes of the collision circles around the cannon and the player. Looking at the sprite, you’ll see that the radius of the cannon is slightly larger at 25 points, but it’s nice to have a bit of wiggle room. You don’t want your games to be too unforgiving or players will think it is unfair.

The fact that the spaceship isn’t circular at all shouldn’t deter you. Often a circle is a good enough approximation of the shape of your sprite, and it has the big advantage that it makes it easy to do the necessary calculations. In this case, the body of the ship is roughly 20 points in diameter (remember, the diameter is twice the radius).

Add a new method that does the collision detection:

- (void)checkCollisionOfPlayerWithCannon
    float deltaX = _playerSprite.position.x - _turretSprite.position.x;
    float deltaY = _playerSprite.position.y - _turretSprite.position.y;
    float distance = sqrtf(deltaX*deltaX + deltaY*deltaY);
    if (distance <= CannonCollisionRadius + PlayerCollisionRadius)
        [[SimpleAudioEngine sharedEngine] playEffect:@"Collision.wav"];

You’ve seen how this works before: first you calculate the distance between the x-positions of the two sprites, then the y-distance. With these two values, you can calculate the hypotenuse, which is the true distance between these sprites. If that distance is smaller than the collision circles, a sound effect is played.

In update, add a call to this new method, above the calls to drawHealthBar:

[self checkCollisionOfPlayerWithCannon];

Also add this line to init to pre-load the sound effect:

[[SimpleAudioEngine sharedEngine] preloadEffect:@"Collision.wav"];

Give it a whirl and drive the spaceship into the cannon.

Ship colliding with turret

Notice that the sound effect is a little odd. It’s because while the spaceship flies over the cannon, the game registers repeated collisions, one after another. There isn’t just one collision, there are many, and it plays the sound effect for every one of them.

Collision detection is only the first step. The second step is collision response. Not only do you want to play a sound effect, but you also want the spaceship to bounce off the cannon.

Add these lines inside the if statement in checkCollisionOfPlayerWithCannon:

const float CannonCollisionDamping = 0.8f;
_playerAccelX = -_playerAccelX * CannonCollisionDamping;
_playerSpeedX = -_playerSpeedX * CannonCollisionDamping;
_playerAccelY = -_playerAccelY * CannonCollisionDamping;
_playerSpeedY = -_playerSpeedY * CannonCollisionDamping;

This is similar to what you did for making the spaceship bounce off the screen borders. Build and run to see how it works.

Bouncing spaceship

It works pretty well when the spaceship is going fast when it hits the cannon. But if it’s moving too slow, then even after reversing the speed, the ship stays within the collision radius and never makes its way out of it. So this solution has some problems.

Instead of bouncing the ship off the cannon by reversing its existing speed, you will simply expel the ship with a fixed speed so that it always moves outside of the collision area, no matter how fast or slow it was flying when it hit the cannon.

This requires you to add a new constant at the top of HelloWorldLayer.m:

const float CannonCollisionSpeed = 200.0f;

Remove those lines you just added in checkCollisionOfPlayerWithCannon and replace them with the following:

float angle = atan2f(deltaY, deltaX);
_playerSpeedX = cosf(angle) * CannonCollisionSpeed;
_playerSpeedY = sinf(angle) * CannonCollisionSpeed;
_playerAccelX = 0.0f;
_playerAccelY = 0.0f;
_playerHP = MAX(0, _playerHP - 20);
_cannonHP = MAX(0, _cannonHP - 5);

That is the speed you want the spaceship to have after it collides with the cannon. You need to calculate how much of that speed goes in the x-direction and how much in the y-direction, based on the angle of impact:

You can calculate the angle using arctan because you know the current speed of the player. To calculate how fast the player bounces off the cannon in the x- and y-directions, you already have two pieces of information: the angle that you just calculated, and the new speed, CannonCollisionSpeed, which is the hypotenuse of the triangle.

If you look back at the theory section, you will see that you can calculate the new x-component of the speed using the cosine function and the y-component using the sine function:

  • new x-speed = cos(angle) * hypotenuse
  • new y-speed = sin(angle) * hypotenuse

And that’s exactly what you’re doing in the code above. Build and run, and you’ll see the spaceship now bounces properly off the cannon and loses some hit points in the process.

Adding Some Spin

For an additional effect, you can add spin to the spaceship after a collision. This is additional rotation that doesn’t influence the flight direction. It just makes the effect of the collision more profound (and the pilot dizzy). Add a new instance variable in the implementation block:

@implementation HelloWorldLayer
    float _playerSpin;

In checkCollisionOfPlayerWithCannon, add the following line inside the collision detection block:

if (distance <= CannonCollisionRadius + PlayerCollisionRadius)
    _playerSpin = 180.0f * 3.0f;

This sets the amount of spin to a circle and a half, which I think looks pretty good. Now at the bottom of updatePlayer, add the following code to add spin to the rotation:

_playerSprite.rotation += _playerSpin;
if (_playerSpin > 0.0f)
    _playerSpin -= 2.0f * 360.0f * dt;
    if (_playerSpin < 0.0f)
        _playerSpin = 0.0f;

The amount of spin quickly decreases over time – I chose a speed of 720 degrees per second. Once the spin has reached 0, it stops.

Build and run and set that ship spinning!

Where to Go from Here?

Here is the full example project from the tutorial up to this point.

Triangles are everywhere! You’ve seen how you can use this fact to breathe life into your sprites with the various trigonometric functions.

You have to admit, it wasn’t that hard to follow along, was it? Math doesn’t have to be boring if you can apply it to fun projects, such as making games.

But there’s more to come: in Part 2 of this Trigonometry for Game Programming series, you’ll add missiles to the game, learn more about sine and cosine, and see some other useful ways to put the power of trig to work in your games.

In the meantime, drop by the forums to share how it’s going for you so far! Or if you really can’t wait until part 2, why not brush up on some more Cocos2D with some of our other tutorials. Alternatively, if you want to start diving into more game development why not take a look at the games starter kits available on this site.

Credits: The graphics for this game are based on a free sprite set by Kenney Vleugels. The sound effects are based on samples from freesound.org.

Matthijs Hollemans

This is a post by iOS Tutorial Team member Matthijs Hollemans, an experienced iOS developer and designer. You can find him on Google+ and Twitter.”




Casi todas las grandes compañías tienen sus estereotipos. Ya sea escribir nombres en vasos (Starbucks), etiquetar todo (Instagram) o perder cosas (servicios postales), todas las compañías los tienen. El artista conceptual e ilustrador de Kazajstan, Leonid Khan, ha dibujado 12 divertidas ilustraciones para Bright Side mostrando cómo serían las entrevistas de trabajo en las compañías famosas basándose en sus estereotipos. ¿Cuál os parece más real?



entrevista culturainquieta



entrevista1 culturainquieta



entrevista4 culturainquieta



entrevista6 culturainquieta



entrevista7 culturainquieta



entrevista8 culturainquieta



entrevista9 culturainquieta



entrevista10 culturainquieta



entrevista11 culturainquieta



entrevista12 culturainquieta



entrevista13 culturainquieta

via brightside



Así es como los lobbies han arruinado tu alimentación


¿Crees que debes reducir grasas y hacer más ejercicio para adelgazar? Quizá te interese saber que eso es un mito de la industria para no señalar a los verdaderos culpables
Foto: Margaret Chan - OMS

Actualmente muere más gente por obesidad que por hambre. Un tercio de la población mundial sufre, como mínimo, sobrepeso (se considera sobrepeso contar con un IMC > 25). Ningún gobierno del mundo ha conseguido reducir esta lacra en las últimas 3 décadas y, según McKinsey, en el 2030 a la mitad de la población mundial le sobrarán kilos. La obesidad es, de hecho, uno de los principales costes de nuestros sistemas sanitarios y no para de aumentar. Da igual que hablemos de países desarrollados o emergentes, estamos ante una epidemia silenciosa y global. ¿Qué está pasando?

Puede que el primer culpable en nuestra mente sea el sedentarismo pero, paradójicamente, hacemos más deporte y vamos más al gimnasio que nunca. Puede que el segundo teórico culpable sea la ingesta excesiva de grasa, al fin y al cabo cuando miramos nuestros michelines es lo que vemos, y si está ahí será porque antes la hemos comido. O quizá culpemos al exceso de calorías en nuestra dieta diaria: si comemos más calorías de las que necesitamos la diferencia se acumula en grasa, o eso dicen las creencias populares.

Yo también lo creía. Creía que el sobrepeso y la obesidad eran por no cuidarse lo suficiente, y que, cuando alguien afirmaba seguir una dieta relativamente saludable y ganar peso de igual forma, simplemente no estaba diciendo toda la verdad. Como a mí no me pasaba, creía simplemente que otros no hacían lo suficiente. Pero me equivocaba, como así pude comprobar tras meses y meses leyendo estudios científicos sobre nutrición. Mi conclusión actual es que casi todo lo que creemos saber sobre cómo alimentarnos no es correcto y, además, sí existen unos culpables claros en la epidemia de la obesidad.


Puede parecer extraño tratar un tema así en una sección de economía, pero el hecho es que me siento en la obligación de contar lo aprendido, aun siendo una ‘verdad incómoda’. Además, no podríamos estar ante un tema más económico pues, si las cosas son como son es, seguramente, por la fuerte presión que han ejercido los lobbies de la industria alimentaria en las últimas décadas. Si a eso le añadimos a gobernantes que han preferido velar por ciertos intereses privadosen lugar de por la salud pública, y científicos que venden su voz a cambio de considerables sumas de dinero, ya tenemos el guion de esta historia.

Lo que la evidencia científica independiente parece decir en los últimos años es que el gran problema son el azúcar y las harinas refinadas. Cuando tomamos una dosis de azúcar añadido (o de sucrosa, o fructosa, o glucosa, o dextroxa, o lactosa, o maltosa, o jarabe de maíz, o maltodextrina… o alguno de los cientos de nombres que existen para que no sepas lo que estás tomando cuando compras un producto procesado) o de harina blanca refinada (productos procesados, pan, arroz, pasta y cereales no integrales) lo que provocamos en realidad en el cuerpo es una reacción en forma de insulina, derivada del alto índice glucémico y alta carga glucémicade estos alimentos.

Cuando obtenemos energía por medio de las proteínas y las grasas no se produce este efecto, obteniendo una liberación más progresiva y que, por tanto, compensamos con nuestra actividad diaria. Lo mismo ocurre con los hidratos de carbono con bajo IG. Sin embargo, en el caso de los azúcares y las harinas refinadas, el proceso es tan rápido que el efecto es una transformación rápida en grasa abdominal (con el incremento de riesgo para nuestra salud que eso conlleva: enfermedades cardiovasculares, diabetes e incluso cáncer).


Por ello, aunque parezca contraintuitivo, tendremos menos grasa tomándola directamente que ingiriendo azúcar o harinas refinadas. De hecho, solo las grasas ‘trans’ son claramente negativas, no existiendo evidencias en las demás (o incluso considerándose positivas, recordemos por ejemplo el aceite de oliva).

Existen polémicas sobre innumerables cuestiones: sobre los productos integrales, sobre los lácteos, sobre la carne roja, sobre los edulcorantes, sobre tomar más o menos hidratos de carbono… Sin embargo, por lo que respecta a nuestros ‘amigos blancos’, cada estudio o libro publicado en los últimos meses no financiado por la industria es claro: el azúcar blanco y las harinas refinadas son un culpable claro de la epidemia de la obesidad. Si la evidencia parece tan rotunda, ¿por qué los gobiernos no toman cartas en el asunto? ¿Por qué no se modifican los patrones recomendados de las ‘dietas saludables’? ¿Por qué la población no sabe cómo cuidar su alimentación?

Voy a contar una breve historia que quizá ayude a entenderlo. A partir de los años 50, en Estados Unidos empezaron a publicarse estudios señalando al azúcar como un elemento nocivo para la salud, algo que inquietó a la industria: su reducción en la dieta diaria podría perjudicar sus beneficios. Por ello se ofrecieron a ‘colaborar’. Por ejemplo cuando el azúcar se señaló como culpable de la caries, la industria ‘colaboró’ con el Insituto Nacional para la Investigación Dental, quién aceptó el 78% de sus propuestas y abandonó toda intención de limitar el azúcar.

Cuando las evidencias se hicieron aun más fuertes, y los estudios comenzaron a relacionar la ingesta con la obesidad, los lobbies ‘promocionaron’ su propia teoría: el culpable de la obesidad no era tanto el azúcar como las grasas saturadas. Hasta hoy, y eso que no existe evidencia en contra de las grasas saturadas. Así, los gobiernos aceptaron la hipótesis y se estableció que lo correcto era reducir las calorías de los alimentos y reducir sus grasas, aun a costa de aumentar el azúcar añadido. Algo que perdura hoy en día, puesto que detrás de cada alimento ‘bajo en grasa’, existe en realidad uno ‘alto en azúcar’ (o cualquier otro sinónimo), nada recomendable para bajar de peso, por cierto.


Cuando las evidencias se hicieron aun más sólidas, la industria comenzó a contar con personajes más renombrados, contratando a científicos de Harvard para velar por sus intereses. Tal era la influencia de sus lobbies que rápidamente se expandió la idea por todo el mundo: si quieres adelgazar come menos grasa y haz deporte. Y algo parecido se puede decir del trigo, promocionado por departamentos gubernamentales como el Departamento de Agricultura de Estados Unidos, quien de la noche a la mañana se convirtió en un oráculo de la nutrición, a pesar de que su función era la promoción de los productos. La pirámide alimenticia no fue un acto de educación sobre la población, fue un acto de marketing para favorecer la industria autóctona.

Si crees que estamos ante hechos aislados, recomendaría una mayor lectura de la prensa diaria. El pasado mes se descubrió que tanto Coca-Cola como Pepsi pagaron a 96 organizaciones sanitarias estadounidenses para silenciar sus críticas sobre el azúcar. Cada vez que alguien abre la boca criticando, las multinacionales hacen presión para hacerlo cambiar de parecer, dándose situaciones tan rocambolescas como ver a la Asociación Americana contra la Diabetes luchando por eliminar un posible impuesto sobre el azúcar. Más criticable aún que las prácticas de la industria, copiadas de las empleadas tabaqueras, es la facilidad con la que se venden los gobiernos y organismos públicos.

Si alguien, a pesar de todas las evidencias existentes, cree que se trata de una conspiración, quizá debería de escuchar a Margaret Chan, Directora General de la Organización Mundial de la Salud. El organismo, que durante años ha suavizado sus posturas al respecto (y recibido millones de euros), afirma ahora (traducción de Juan Revenga) lo siguiente:

[…] En la actualidad las campañas de promoción de estilos de vida saludables y la adopción de conductas para alcanzarlos se encuentran con la oposición de fuerzas que distan mucho de ser “amables”. Más bien, todo lo contrario.

El esfuerzo público dirigido a prevenir las enfermedades no transmisibles [tras hacer una especial alusión a la obesidad, la diabetes y el cáncer] se enfrenta a intereses comerciales de poderosos agentes económicos. En mi opinión, este es uno de los mayores retos a los que se enfrentan las campañas de promoción de la salud.

Tal y como pone de manifiesto la publicación que resume esta conferencia [ver al completo en este enlace] no solo se trata del problema observado en otro tiempo con las grandes tabacaleras (Big Tobacco). Ahora, la Salud Pública tiene que lidiar también con otras industrias en los mismos términos que entonces; se trata de la “Big Food”, “Big Soda” y “Big Alcohol”. Son estas industrias las que en este momento temen una regulación de sus productos por parte de las administraciones sanitarias y las que están recurriendo a las mismas tácticas que antaño puso en práctica la industria tabacalera.

El pasado reciente aporta pruebas suficientes para documentar que estas tácticas por parte de la industria alimentaria ya se han puesto en marcha. Entre ellas, se incluyen la creación de empresas dentro del mismo grupo con una “cara amable”, la creación de grupos de presión [lobby], el realizar promesas de autorregulación, el interponer demandas y el financiar estudios de investigación que lo que consiguen es tergiversar la evidencia y confundir al ciudadano.

Además, este tipo de tácticas también incluye la realización de donaciones, regalos y contribuciones relacionados con causas nobles, o bien vistas por parte de la comunidad, de forma que estas industrias terminan siendo percibidas como corporaciones respetables tanto a los ojos de la ciudadanía como ante los de la clase política. Entre sus estrategias destacan también el hacer descansar la responsabilidad de una mala salud en cada persona, individualmente; así como pretender hacer creer que las acciones de los gobiernos por regular estas cuestiones no son otra cosa sino una forma más de interferir en la libertad personal de cada cual y su derecho a elegir libremente.

La oposición ejercida es de una magnitud formidable. Ya que un amplio poder en los mercados se traduce en poco tiempo en poder político, son pocos los gobiernos que han priorizado las cuestiones de salud frente a los grandes negocios. Tal y como hemos aprendido de experiencias anteriores, como con la del tabaco, cuando una corporación poderosa se lo propone, puede vender casi cualquier cosa a la población.

Déjenme recordarles una cosa. Ni un solo país del mundo ha conseguido darle la vuelta a la epidemia de obesidad en todos los grupos de edad. Esta realidad no es consecuencia de una falta de voluntad individual. Es consecuencia de la ausencia de voluntad política a la hora de meter mano en este gran negocio.

Estoy profundamente preocupada por dos actuales tendencias:

La primera implica la posibilidad de que la industria y las administraciones lleguen a acuerdos “comerciales” fruto de las denuncias de la primera sobre las segundas. En la actualidad, algunos de los gobiernos que han establecido medidas para proteger la salud de sus ciudadanos están siendo llevados a los tribunales por parte de la industria. Y esto es peligroso.

La segunda se refiere al interés que pone la industria para moldear las políticas de Salud Pública, en especial aquellas medidas que afectan a sus productos. Si una industria está involucrada en la formulación de políticas de Salud Pública, tengan la seguridad de que aquellas medidas más eficaces serán o bien minimizadas o bien apartadas en su totalidad. Esta tendencia también está bien documentada y es así mismo peligrosa.


Yo no soy nutricionista, ni médico. No sé de alimentación más que lo que he leído en meses tratando de aprender al respecto. Pueden creerme, o no. Pueden tomar en cuenta los consejos y reducir azúcar y harinas refinadas (las grasas trans también estarían bien), o no. Pero sí sé como actúan muchas empresas, y la conducta de Coca-Cola o Pepsi, o de otros que venden cereales nada saludables, encaja perfectamente con la de empresas que ven como su negocio podría menguar si la población descubre la verdad.

El azúcar o la harina blanca son adictivos, saben bien y son baratos, la industria no está preparada para prescindir de ellos (sus esperanzas a futuro están puestas en los controvertidos edulcorantes). Sin embargo lo más probable es que sean uno de los elementos más perjudiciales que tenemos en nuestra alimentación actual. Lo más probable es que esa tripa que tienes sea su culpa, no de la falta de ejercicio, no del exceso de grasas. Por supuesto que el deporte es sano, y no hay que caer en dietas extremistas, pero va siendo hora de poner las cosas en su sitio y señalar a los verdaderos culpables. ¿Los ciudadanos? No, las mentiras interesadas que nos han contado.

Y si la Filosofía desaparece del Bachillerato, ¿qué?

La semana pasada alguien colgó en la la sala de profesores de mi centro una carta (la enésima) sobre lo importante que es la Filosofía, que nos salva a todos de no ser unos borregos, y su desaparición (falso) del bachillerato.

No sé quien ha sido pero me imagino que será el mismo que hace unos años colgó un artículo sobre esquiroles antes de una huelga general para insultarnos en la cara a la mitad del claustro.

Huelga decir que es una gran falta de respeto lo que hace este compañero ya que en un centro educativo todos los profesores tenemos nuestra propia ideología y, en contra de lo muchos piensan, muchos no somos ni rojos ni progres, ni, por supuesto, creemos que la Filosofía es la salvadora de nada ni de nadie y que hay muchas otras asignaturas en las que los alumnos aprenden a “pensar” mucho más.

Como dice el artículo que pongo a continuación, estos profesores solo pretenden salvar su acomodado puesto de trabajo, los más privilegiados de cualquier centro de secundaria. Un “quéhaydelomío” de libro.


“Y si la Filosofía desaparece del Bachillerato, ¿qué?

Pensamiento crítico

Lo mejor será que empiece negando la posibilidad de que se cumpla lo que plantea el título. Es sencillamente imposible que la Filosofía desaparezca del Bachillerato. Y es imposible de la misma manera que es imposible que la UE expulse de su seno a una hipotética Cataluña independiente.

Seguramente algunos ya habrán visto el truco en esta extraña equiparación, sólo con reparar en el título. La imposibilidad en los dos casos no deriva de una posición de fuerza ni de una situación inmutable, sino justamente de la inexistencia de eso de lo cual se plantea la desaparición. La Filosofía no desaparecerá del Bachillerato porque hace tiempo que no está, y Cataluña no sería expulsada de la UE porque no pertenece a ella.

Lo de Cataluña no es discutible, por mucho que se empeñen Romeva, Mas y el resto de osados galos. Si finalmente se consuma la ilegalidad que han ido explicitando este último año largo, es de esperar que el cielo caiga sobre sus cabezas. Y sobre la del resto de los alegres compatriotas que consciente o inconscientemente les han seguido -o empujado- hasta el abismo.

Ahora bien, ¿en qué sentido decimos que la Filosofía no existe en el Bachillerato? Al fin y al cabo, ha sido hasta ahora una asignatura obligatoria en los dos cursos de los que se compone. En todo caso, habría que preocuparse por la eliminación de la obligatoriedad en el segundo año, como han apuntado tantos escritores, profesoreso incluso alumnos en los últimos meses. Es sorprendente este súbito amor no ya por el conocimiento, sino por la Filosofía, que se ha despertado desde que Wert introdujo esta cuestión en su reforma de la Ley de Educación.

Pero no es este despertar lo que voy a tratar ahora. Al fin y al cabo, es posible que ese amor siempre haya estado ahí, escondido. Lo que voy a tratar, porque me parece preocupante, es la idealización desde la que se contempla la Filosofía. O, mejor dicho, la asignatura de Filosofía. Esa idealización se observa perfectamente en uno de los argumentos que más se han esgrimido para criticar la pérdida de la obligatoriedad en Bachillerato, y es el siguiente: “Si se elimina Historia de la Filosofía del Bachillerato, estaremos condenando a los alumnos a una existencia borreguil, puesto que perderán la capacidad de desarrollar un pensamiento crítico.”

Serán “esclavos del sistema”, dicho de otro modo.

Esto, por no extendernos demasiado, es una estupidez. Y si lo dice un profesor de Filosofía, además, una idiotez.

Dos pruebas.

La primera: hasta ahora hemos tenido varias promociones de alumnos con dos cursos de Filosofía obligatorios. La última de ellas la “generación más preparada de la Historia”, expresión a la que es ya imposible acercarse sin malicia. No creo que nadie se atreva a afirmar que todos ellos han desarrollado un mínimo de pensamiento crítico. Quiero decir, es de suponer que el mismo Romeva cursó dos años de Filosofía. Más aún, todos aquellos que aplauden las mentiras y piden otra ración, todos aquellos que hablan de sentimientos colectivos y convierten en afrenta cualquier opinión disidente, todos ellos, han cursado dos años de Filosofía. Pero podemos ir aún más cerca. Concretamente, a las asambleas del 15M. Muchos de los autores de las propuestas psicodélicas que pudieron verse durante esos días no sólo cursaron dos años de Filosofía en Bachillerato, sino que incluso prosiguieron sus estudios sobre la materia en la universidad. Algunos, incluso, eran profesores de Filosofía. Por lo tanto, parece que la mera presencia de la Filosofía en el Bachillerato no es un antídoto eficaz contra el borreguismo.

La segunda, más que una prueba, es una cuestión de léxico. Y una apelación al principio de realidad. Es decir, una reivindicación de la propia esencia de la Filosofía, que no es otra que el abandono del pensamiento mágico. Valga el oxímoron. La Filosofía en ese sentido no es más que hablar con propiedad, llamar a las cosas por su nombre. Empezando, claro, por la propia Filosofía.

La Filosofía, en Bachillerato, es una asignatura. Y hay que situarla en un contexto determinado. Los alumnos, los profesores y el sistema de enseñanza son la parte fundamental de ese contexto. Y todas las asignaturas son afectadas -determinadas- por ese contexto concreto. Así, la asignatura de Filosofía de hoy en día poco tiene que ver con la que podía haber hace treinta o cuarenta años.

Comenzando por la Historia de la Filosofía, que es la que en principio está en riesgo de desaparecer, debemos aceptar que ni es Historia, ni es Filosofía. Son apenas cinco o seis cuestiones sobre cinco autores, sin conexión entre ellas. Seguramente hay profesores -y alumnos- que aprovechan al máximo la asignatura, pero el caso es que es perfectamente posible acabar el curso sin haber entendido nada. Diría incluso que es lo más frecuente. Al fin y al cabo, la economía del centro y la de los estudiantes coinciden en ese sentido: maximizar el resultado, minimizar el coste. Lo que se traduce en el aprendizaje de cinco autores. En realidad son diez, como todos sabemos, pero en el examen siempre se ofrece la posibilidad de elegir uno de un par de autores que comparten la misma época. Platón o Aristóteles, San Agustín o Santo Tomás, Descartes o Kant, Marx o Nietzsche, Ortega o Wittgenstein. La clave está en la disyuntiva.

Por simplificar, un alumno de 2º de Bachillerato puede estudiar a Aristóteles sin haber visto más que un par de pinceladas de Platón. Y de hecho, puede sacar buena nota en la prueba de Selectividad. Porque como ya hemos dicho, de lo que se trata es de conseguir una buena nota, y para eso basta con memorizar algunas respuestas tipo.

Es cierto que hay una parte del examen para la que no basta ese aprendizaje memorístico. Es el comentario crítico. O como quiera que se llame ahora. Disertación, creo. Casi un tercio de la nota, trescientas palabras como máximo. Aquí es donde, dicen, tienen que lucirse. El problema es que no tienen la base necesaria para hacerlo. Es un obsceno ejercicio de voluntarismo. No hay tiempo para trabajarlo en clase, y depende de dos cuestiones que son ajenas a la asignatura: el conocimiento material y el conocimiento formal. Es decir, referencias externas y madurez expresiva. Sin eso, poco se puede hacer.

Pretender que los alumnos sean capaces de hacer una disertación filosófica sin esos conocimientos es como pretender hacer una tortilla sin huevos. Se le puede llamar Filosofía a lo primero y tortilla a lo segundo, pero no lo son.

La Filosofía de Bachillerato, por tanto, no es lo que dirige a los alumnos hacia la madurez, al contrario de lo que apuntaba Montano hace poco.

Queda por tanto la Filosofía de 1º. Ahí podríamos situar la aportación específica de la Filosofía en el curriculum educativo. No hay examen final y hay más flexibilidad para adaptar la asignatura. No sé hasta qué punto es bueno, pero ésa es otra cuestión. De cualquier manera, no es suficiente por sí mismo. Todo profesor sabe que es muy difícil generar pensamiento crítico. A no ser que digamos que el pensamiento crítico es lo mismo que la opinión. Entonces sí. Hay opiniones a patadas. Sobre cualquier tema. Todos los alumnos tienen una, o incluso varias, sobre la misma cuestión. Y ahí radica el engaño. La Filosofía ha servido para perpetuar el imperio de la doxa contra el que ya advirtieron Platón y Aristóteles. En la ESO y en el Bachillerato se ha instalado la creencia de que los alumnos tienen que opinar sobre todo, y enseguida además. Seguramente esa creencia tiene la misma fuente pedagógica que el diabólico “Que lean lo que sea, pero que lean”. Y así, en lugar de aprovechar esos años para borrar todas las opiniones, para quedarnos sólo con los análisis y los hechos, para alertar contra los sesgos y la tiranía de los afectos y para, en definitiva, colocar a la razón en el lugar que le corresponde, se ha ido construyendo una ampliación de la educación infantil, en la que lo importante es lo superficial. Ése es el contexto, del cual nada escapa. Ni los profesores, ni los alumnos, ni las asignaturas.

Así que, en contra de lo que han expuesto muchos otros compañeros de profesión, no creo que la Filosofía corra el peligro de desaparecer del Bachillerato, porque a esto que tenemos ahora sólo se le puede llamar Filosofía por inercia. Y difícilmente puede ser ese generador de madurez y pensamiento crítico que muchos, con buena intención, le suponen. Precisamente el insistir en esa idealización no es sino una prueba más de lo que estamos diciendo. Cualquier alumno de Bachillerato debería ser capaz de hacer un análisis similar. Y no digamos un profesor de Filosofía.

Lo que sí está en peligro de desaparecer, justamente, es esto mismo. La profesión de profesor de Filosofía en Bachillerato. Y es desde luego un asunto importante, fundamentalmente para quienes nos dedicamos a ello. Extender esa visión mágica sobre nuestra labor probablemente nos granjeará muchas simpatías, y puede que incluso sirva para convencer al resto de la sociedad de que es imperativo que siga ocupando el espacio que hasta ahora ha ocupado en la enseñanza. Bien es verdad que no lo tendremos demasiado difícil, puesto que ya nos hemos ocupado de prepararles para que consuman con gusto ese pensamiento débil.

Imagino que los tiros seguirán yendo por ahí. Lo sentimental, el énfasis y la indignación. Justo lo contrario de lo que se supone que es la Filosofía.


En este blog han escrito una réplica a lo que publiqué aquí hace unos días. Si a alguien le interesa, puede leer tanto la réplica como mi respuesta a esa réplica. El tono es desagradable porque el autor de la réplica lo lleva a lo personal, así que advertidos quedan los lectores.”

“Cuidado con lo que deseas en Internet”: la siniestra historia del señor Montgomery

A woman´s eye. Wikimedia Commons


Cada año surgen miles de nuevas parejas en Internet, unas estadísticas que se multiplican con el paso del tiempo. Muchas de estas relaciones han acabado perdurando, otras han servido como simple encuentro sexual. Luego están aquellas que han acabado mal. Por último, está la historia de Tommy y Jessi.

Se calcula que el 75% de los estadounidenses solteros ha utilizado la red al menos una vez para ligar. En otros países como España las estadísticas del INE indican que al menos la mitad de los solteros y solteras de menos de 20 años suele utilizar la red una vez al mes con la esperanza de encontrar una relación.

A estas cifras hay que sumarle otras más perturbadoras. Por ejemplo, y siguiendo la senda de los chats de citas y similares, se calcula que el 81% de los miembros de estos portales miente en sus perfiles, ya sea con la edad, su peso, altura, foto, o en el peor de los casos, con todo.

Resulta tan sencillo como escalofriante hacerse pasar por otra persona en Internet. Una industria, la de las citas online, a la que no parece afectarle este tipo de “trastornos” inherente en muchas personas. En el año 2007 generaba 700 millones de dólares y que para el 2012 ya rozaba los dos mil millones de dólares.

Si tuviésemos que establecer un tiempo para definir el momento previo al boom de este tipo de apps, sin duda sería antes del 2007. Por aquellas fechas estábamos en los inicios de la gigantesca industria que hoy habita en la red, esa que frecuentemente nos recuerda lo importante que es mantener una contraseña segura.

Antes del 2007 cualquier chat valía para comenzar un ligero flirteo bajo el manto y la seguridad del anonimato que ofrecía un nick elegido por el usuario. Pogo fue una de esas webs. Aunque nunca ha dejado de ser una página de juegos online, muchos usuarios la utilizaban por aquel entonces para lanzar sus mensajes algo más atrevidos a otros usuarios, lo que en ocasiones acababa en encuentros reales fuera del espacio digital.

Así fue como se conocieron la primavera del 2005 los usuarios Talhotblondy MarineSniper.

Esta fue su escalofriante historia.

Cuando Tommy encontró a Jessi

Thomas Montgomery. ABC News

Cada día y durante los últimos 12 años Thomas Montgomery se había levantado a la misma hora de la mañana para acudir a la fábrica de perforación en la que trabajaba en Clarence, una pequeña ciudad en el norte de Nueva York. Un hombre aplicado, a menudo de los últimos en salir del trabajo, que cuando terminaba su jornada acudía rápido a casa para pasear al perro y llevar a sus dos hijas a natación.

A Montgomery se le conocía en la ciudad como un tipo agradable, un buen hombre, buen padre y un marido decente para su esposa Cindy, con la que llevaba 16 años casado. De entre las aficiones que tenía en su tiempo libre destacaba una: su pasión por las partidas cada viernes al Texas Hold ‘Em en la web Pogo.com.

Thomas tenía por aquellas fechas 45 años, un ex marine con bigote rojizo, algo obeso y poco pelo. Quizá por ello un día se miró a sí mismo y no le gustó lo que veía. Quizá por ello también un día decidió que no quería ser esa persona. Sería un marine como en sus tiempos de joven, un marine de 18 años llamado Tommy. Además también sería cinturón negro de kárate, un tipo atlético con una cicatriz de bala en el hombro izquierdo que le daría al personaje un aura de héroe.

Estos pensamientos los convirtió en realidad (digital). Thomas, envalentonado, entró en Pogo y se registró como ese joven vigoroso. Y fue al poco tiempo de crearse esa nueva identidad cuando Thomas Montgomery conoció a Talhotblond, una joven de 17 años natural de Virginia cuyo verdadero nombre era Jessica, cómo luego le revelaría la joven.

Ashley Madison. Getty

Jessica en muy poco tiempo pasó a ser “Jessi” en el chat privado que comenzaron a seguir ambos. Conforme pasaba el tiempo Thomas iba creando un perfil de película. Un joven cuya madre había muerto cuando él era pequeño, un chico problemático que se alistó en el ejército como única salida y que estaba listo para ir a combatir a Irak.

Los cuentos de Tommy acerca de su difícil vida atrajeron a la joven. Tommy era un alma herida y Jessi le proporcionó consuelo, a menudo le decía lo orgullosa que estaba de él a pesar de los errores. La intimidad entre ambos iba creciendo hasta tal punto, que un día Tommy le aseguró a Jessi que pensaba suicidarse en Irak, a lo que ella respondió que le debía prometer que volvería sano y salvo por ella.

Como recordaría años después el señor Thomas “pensaba que jamás nos íbamos a encontrar, así que simplemente estaba jugando con ella”. Pero en muy poco tiempo comenzaron con el flirteo que acabaría en romance. Jessi comenzó a enviarle fotos sugerentes y provocativas a Tommy. Cuando el joven estaba ausente por los entrenamientos en el ejército Jessi hablaba con Tom Jr., el padre de Tommy, en esencia otro personaje que había creado Montgomery para darle “mayor autenticidad”.

Tras las primeras fotos sugerentes de Jessi esta le pidió a Tommy algunas de él. Montgomery entonces le envió fotos antiguas de cuando estaba en el ejército, imágenes que encontraba y que hacían honor a su nick MarineSniper, un nombre creado como recuerdo nostálgico de los seis años que pasó en el ejército cuando era joven. Un espacio en el tiempo en el que se graduó como experto francotirador.

Pogo.com actualmente

La relación online fue subiendo de tono en muy poco tiempo, los mensajes de chat en su ordenador recuperados posteriormente mostraban una relación que comenzaba a devorar al hombre de familia, un flirteo que consumía el interior de Montgomery. Como él mismo le dijo al tribunal: “se hizo más real para mí que la vida real”.

El sentimiento parecía ser mutuo. Jessi y Tommy comenzaron a intercambiar regalos, luego comenzaron las primeras llamadas telefónicas, las primeras cartas de amor… “Te quiero por siempre jamás, Tommy”, le escribía Jessi. “Nunca me he sentido así”, respondía Montgomery.

Aquello ya no era un flirteo. “Había sexo virtual entre ella y Tommy”, comentó al tribunal Montgomery. En este punto, mientras que el hombre aseguraba sentirse “sucio” por el sexo virtual, también decía que estaba profundamente enamorado como para poder cortar los lazos con ella.

Por aquellas fechas, el hombre de familia al que sus allegados tenían por una persona decente estaba a punto de perder el contacto con la realidad. De hecho, al poco tiempo cruzó el umbral escribiéndose una nota a sí mismo donde se decía:

El 2 de enero de 2006 Tom Montgomery (de 46 años de edad) deja de existir y es reemplazado por un marine de 18 años de edad, con cicatrices de batalla … Se está trasladando a Virginia para estar con el amor de su vida.

Jessi se había enamorado de Tommy, y Montgomery de Jessi, o al menos, bajo la idea de sí mismo como Tommy. Pero los fotos de Jessi provocaron la primera explosión importante en la pareja. Montgomery se convenció de que esas fotos también se las había enviado a otros admiradores en la red y la acusó de traicionarlo. Para disculparse, Jessi le envió una carta y una cadena de plata con las iniciales T&J. Tommy la perdonó pero Montgomery, en el papel del padre Tom Jr., no lo hizo en un primer momento.

Como podemos apreciar, Montgomery estaba muy cerca de cruzar esa fina línea que separa a la locura de la razón.

Unos meses más tarde la relación explotaría por todos lados.

Cuando Cindy encuentra a Jessi

La familia de Montgomery. Talhotblond

En la navidad del 2005, unos ocho meses después de conocerse online, Tommy le propone matrimonio y Jessi acepta. Montgomery estaba consumido por esa relación virtual, mientras trabajaba no dejaba de hablar de ella y le decía a sus compañeros que planeaba dejar a su esposa y trasladarse a vivir a Virginia.

Mientras, Cindy, la mujer de Montgomery, seguía sin saber nada de la doble (casi triple si contamos a Tom Jr.) vida de su marido. Sabía que algo había cambiado en el hombre, quién desde que llegaba a casa del trabajo no salía de Internet en los últimos meses.

Pero en marzo del 2006 todo cambió. Una de las hijas de Montgomery estaba utilizando el ordenador de su padre mientras este trabajaba, cuando de repente salta un mensaje instantáneo de Jessi que la joven pudo leer. La hija acudió rápidamente a su madre y está encontró de golpe el chat abierto con las conversaciones íntimas entre su marido y Jessi. Cindy registró el cuarto y las pertenencias de su marido y encontró cartas de amor entre ambos y unas bragas rojas que le había enviado Jessi.

¿Qué hizo Cindy? Le envió a Jessi una foto de su familia junto al siguiente mensaje:

Permítame presentarles a estas personas. El hombre del centro es Tom, MI MARIDO desde 1989. Por cierto, Tom tiene 46 años. De lo que estoy sacando en claro de tus cartas es que estás más cerca de la edad de mi hija que de la mía. ¿Tienes más de 18 años?

Cindy había descubierto algo todavía más perturbador. La ropa interior había sido enviada al “padre” de Tommy durante unas fechas en las que se suponía que Tommy estaba en el ejército (realmente fueron fechas en navidad donde Montgomery no tuvo mucho tiempo para chatear con la joven). Cindy le dejó a su marido una nota al lado de su ordenador para que la viera cuando llegara del trabajo. Una nota que decía:

No puedo creer que estés viviendo esta extraña fantasía, pero aún peor, como padre e hijo. Si quieres separarte podemos hacerlo… pero seguir mintiéndome a mí y a tus hijas mientras ella envía “regalos” para tu supuesto hijo es totalmente inaceptable.

La pareja siguió viviendo los meses siguiente en la misma casa, aunque Montgomery pasó a vivir en el sótano. Mientras, Jessi no sabía a quién creer. ¿Tommy no existía o era Cindy la que se había inventado esa historia para separarlos?

Montgomery (izquierda y centro) y Barret (derecha). Tapology

Así fue como la joven encontró a un amigo que Montgomery había mencionado en alguna ocasión y que también frecuentaba Pogo bajo el nick Beefcake1572. Se trataba de Brian Barret, un estudiante de 22 años que trabajaba a media jornada en la empresa de Montgomery y solía jugar al póker con él. Barret le confirmó a Jessi sus peores temores y la joven quedó devastada.

El joven Barret comenzó a intimar con Jessi, primero consolándola, más tarde como algo más. Sus conversaciones se volvieron más íntimas y comenzaron a hacer público en los chats online quién era realmente Tommy. Montgomery quedó como un mentiroso, un depredador sexual de 46 años mientras ambos se burlaban de él. En cuestión de días su vida estaba destruida y el hombre llegó a plantearse el suicidio.

Montgomery comenzó una escalada de violencia verbal, le llegó a decir a Jessi que “Brian pagaría en sangre” lo que estaba haciendo. El hombre estaba devastado y había tocado fondo… cuando de repente le llega un nuevo mensaje de Jessi. La chica estaba desgarrada, loca y desesperada por volver a ese amor con un hombre que sabía que no existía. Parecía como si la nueva situación le provocara. De alguna forma, Montgomery era todo lo que quedaba de Tommy. Así comenzaron a chatear de nuevo:

Jessi: Me gustaba estar con Tommy, ¿lo echas de menos?

Tommy: Más de lo que jamás podrás imaginarte. Mi corazón me duele de escuchar que me llamas “tu Tommy”. Ojalá pudiera ser ese joven marine de 18 años para ti.

Jessi: Lo sé Tom.

Así fue como ambos volvieron a estar en contacto. Como decía Barbara Schoeder en el documental Talhotblond que contaba esta turbia relación:

En su mente, este fue el mayor premio. Él había sido aceptado con sus 47 años y esa joven lo seguía queriendo. Era como una droga, era adicto a ella y no podía quitársela de la cabeza.

Meses después Montgomery contaría que jamás hubo nada sexual entre ellos después de que Jessi descubriera su edad, pero el registro de los mensajes posteriores contaban una historia diferente:

Marinesniper: Deseo que estuvieras desnuda.

Talhotblond: ¿qué harías?

Marinesniper: mirarte fijamente.

Talhotblond: ¿eso es todo?

Marinesniper: no. Podría hacer magia.

Talhotblond: mmmmmm… hazme el amor Tommy.

Pero a pesar de estas promesas, Jessi continuó su romance con Barret. Sus conversaciones con él reflejaban los típicos problemas de adolescentes: se quejaban de sus padres, hablaban de los preparativos del baile, hablaban de sus primeros trabajos…

La joven parecía dividida entre los dos hombres. Cuando Barret la quería visitar durante sus vacaciones, ella le decía que no estaría. A Montgomery le decía que quería romper con Barret. El hombre la creyó hasta tal punto, que por primera vez en 15 años se dedicó a un duro entrenamiento corriendo 7 kilómetros diarios y pasando horas en el gimnasio… hasta que al final del verano del 2006 descubrió que Jessi y Barret seguían manteniendo la relación.

Cuando Tommy encontró a Barret

Montgomery, Jessi y Barret. DailyMail

Montgomery insultó gravemente a la joven y está rompió todos los lazos con el hombre. Habían terminado para siempre y para colmo Barret hizo público que iba a conocer a Jessi en persona.

Así, el 13 de septiembre del 2006, Tommy escribe a Jessi a la 1:33 en el chat que aún guardaba. Un mensaje donde la insulta y la amenaza. Ella le responde que la deje en paz. Montgomery responde pero ella no vuelve a escribirle. Al día siguiente Montgomery vuelve a intentar entrar en contacto con la joven insultándola. Ella seguía sin responder.

A la mañana siguiente, el 15 de septiembre, Montgomery llama a la joven gritándole, lleno de rabia como recordaría Jessi. La joven colgó el teléfono. Más tarde, sobre las 22:00, Barret salía tarde de su jornada en la fábrica y se dirige a su coche. El joven abre la puerta y se acomoda en el asiento. En ese instante tres disparos perforan la ventanilla lateral del conductor y Barret cae fulminado. Tres disparos mortales que le alcanzaron en el cuello y en la parte superior del brazo.

Unas horas después Montgomery estaba delante de su ordenador tratando de chatear con Barret. Se trataba de una serie de mensajes donde le insistía a hablar con él. En entrevistas posteriores los detectives ya tenían a Montgomery como un posible culpable del asesinato. Poco después un compañero de trabajo les daba una pista crucial. Dos semanas antes Montgomery le había preguntado por la hora que solía terminar de trabajar Barret.

Montgomery. DailyMail

Cuando los detectives examinaron las llamadas de Barret encontraron el número de Jessi. Después de hablar con ella y en cuestión de minutos ataron cabos y tuvieron la certeza de la existencia de ese extraño triángulo amoroso que había ocurrido en Internet. Montgomery seguía desaparecido y la chica corría un grave peligro. El teniente Ron Kenyon que llevaba el caso llama una vez más a la joven y le dice que no abra la puerta a nadie bajo ningún concepto, que van a enviar a una patrulla de Virginia a su dirección lo más rápido posible. Como diría en el juicio:

Eran más o menos las tres de la mañana y nuestra primera y máxima preocupación era llegar hasta Jessi y asegurarnos de que seguía con vida.

Pero cuando la policía llegó a la dirección ofrecida por la joven se encontraron con una sorpresa. Allí sólo estaba Mary Shieler, una mujer obesa de 45 años y pelo corto en una casa blanca destartalada. La mujer le contó al oficial que era la madre de Jessi y que la adolescente no estaba en casa y no tenía manera de encontrarla.

El oficial llamó a Kenyon y este no podía creérselo, le dijo al oficial que insistiera, que había hablado con la joven hacía escasas horas y debía estar allí. Cuanto más presionó el oficial, más nerviosa se mostró Mary, quién finalmente dijo la verdad. Mary era la mujer con la que había hablado Kenyon por teléfono. Mart era la mujer por la que había muerto Barret. Y sí, Mary también fue la mujer por la que Montgomery había matado.

Mary era Jessi y Talhotblond y había usado la identidad de su hija para seducir a dos hombres hasta el fatal desenlace. La mujer se había dedicado a enviar las fotos de su hija, quién nunca tuvo conocimiento de la vida cibernética de su madre.

Poco después Montgomery fue detenido, acusado y finalmente declarado culpable del asesinato de Brian Barret. Le cayeron 20 años.

Por su parte, los fiscales buscaron la forma de acusar a Mary Shieler de algo, lo que fuera, cualquier cosa. Pero finalmente concluyeron que la mujer había caminado por una fina línea moral y ética, aunque sin cruzar la frontera de lo legal.

Con todo, Mary Shieler no salió indemne. Su esposo se divorció de ella tras enterarse de toda la trama.

Su hija jamás volvió a dirigirle la palabra.



18 de noviembre de 2016
Cuando en una columna anterior he dicho que con las elecciones de EEUU se ha caído un “entramado progre” no sé si me he llegado a explicar bien. Lo que llamo entramado progre no es un mundo propiedad de los progres, sino la plutocracia (o el “establecimiento” como dicen en el programa de Bayly) que ellos han sustentado.

Después de la II Guerra Mundial fueron poco a poco creciendo en Francia ciertos movimientos ideológicos contrarios a las ideologías identitarias. Estos movimientos se basaban en tres principios: feminismo, multiculturalismo y pacifismo. Pronto todo esto acabó confluyendo en el fracasado Mayo del 68 y a partir de ahí pasó a las cátedras universitarias, desde las que se fue enviando gente hacia la educación y los medios de comunicación. El capitalismo no generó estos movimientos, pero pronto entendió que le convenía aprovecharlos en su beneficio. Tanto los judíos que se habían refugiado en los EEUU como la antigua burguesía que aún quedaba en Europa entendieron muy rápidamente lo siguiente:

Feminismo = mano de obra barata.

Multiculturalismo = mano de obra más barata.

Pacifismo = procurar que no nos hostien por los dos puntos anteriores.

Entonces, antes ya de que cayese el famoso muro de Berlín se había entendido que el ideario progre cumplía dos funciones: bloqueaba a la izquierda marxista (porque ocupaba su lugar) y generaba una repulsión hacia los movimientos vitalistas identitarios (a los que temían aún más). Todo el capitalismo siguió por ese camino y vio que, cuanta más moralina progre inyectaba en la sociedad, más se llenaban sus bolsillos y más se vaciaban los de los obreros. Era una cuadratura del círculo muy bien diseñada. Los problemas de insostenibilidad, de límite de la deuda o de invierno demográfico por baja natalidad, les daban igual.

Los progres han estado imbuidos de su propia doctrina como los primeros cristianos. Se han metido en la mente sus dogmas de un modo irreversible y su visión de la realidad es básicamente una distorsión. Sus ideas políticas se han expresado a través de la socialdemocracia, que es un diseño de Keynes basado en dar dinero a la clase obrera y apuntar la factura a la deuda pública para que la pague la generación siguiente. Y esa generación siguiente somos nosotros. Mientras tanto, ha habido barra libre para engordar obscenamente los beneficios de la banca y las grandes corporaciones.

Como toda la socialdemocracia, y por extensión todo el mundo progre, están basados en la deuda pública y en la manipulación mediática, es evidente que no van a poder continuar. Trump gana las elecciones porque Obama ha llevado a EEUU ya por encima del 100% del PIB de deuda (aparte de la expansión monetaria). Todos los periódicos, casi sin excepción, apoyaron a Hillary. Y nadie les hizo caso.

España está en la misma situación y los demás países europeos no andan muy lejos. No vamos a poder vivir bien dejando la factura por pagar a la generación siguiente, como tampoco vamos a poder mantener las paguitas y subsidios subiendo más los impuestos porque ya estamos en un nivel confiscatorio. Es un sistema que ha caído igual como la Unión Soviética. De hecho, la URSS duró 74 años. La chapuza de Keynes ha durado aún menos.

La gente de EEUU y Europa está empezando a entender que, en un mercado de oferta y demanda como el mercado de trabajo, un aporte ilimitado de mano de obra implica una caída de su precio. Además, el 53% de las mujeres blancas votó a Trump, lo que desmonta la idea de feminismo y “empoderamiento” a base de meter al marido en un calabozo y fichar en una fábrica a las ocho de la mañana. Hay la sensación (y esto lo decía también Hillary) de que no se va a vivir mejor recogiendo las migajas del enriquecimiento del 1%.

Como bien dice Roberto Centeno, hay unas “élites depredadoras” que se han apropiado de todo el crecimiento de las últimas décadas. Esto no hubiese sido posible con la antigua izquierda marxista, ni con el nazismo/fascismo/falangismo. Esto ha sido posible sólo en el mundo progre, en el mundo de la autoinhibición, de los complejos y de poner la otra mejilla, en la sociedad de las feministas, los gays y los medios alineados. Las continuas cortinas de humo en forma de moralizaciones y sermones han impedido que veamos la simple realidad: tenemos mucho menos dinero y no hay ningún motivo objetivo para que esto sea así.

Pero Trump sí que ha sabido encontrar el problema verdadero, que se llama establishment, y cortar el círculo de paguitas, limosnas y deuda pública. Ahora lo que habrá será una regulación para que las empresas compitan por la mano de obra, y no al contrario. Los obreros ya no van a poner la mano al Papá Estado, ahora tendrán más empleos, cobrarán más y el viento soplará a su favor.

El nombramiento de Steve Bannon como una especie de hombre fuerte mediático/cultural del gobierno Trump, con una influencia muy transversal, me dice que sí que hay una intención clara de hacer un cambio cultural. No va a ser Trump como el cándido de Rajoy, que aún tiene a las feministas campando a sus anchas en TVE. Trump sabe de qué modo la plutocracia controla los medios, y quiere ponerle fin a eso. Bannon será el encargado de diseñar una estrategia mediática a gran escala para desmantelar el ideario progre. Esto es una gran noticia.

Poco a poco, vamos a ver cómo los medios de línea editorial progre van a ir reduciendo su tamaño, algunos incluso cerrando, mientras que otros en la línea de Breitbart crecen y se hacen fuertes. En las universidades, encontrarán la forma de arrinconar a los profesores politizados. En la educación, se tomarán medidas para evitar el adoctrinamiento ideológico. En Hollywood, se verán más Klint Eastwood y John Wayne que Miley Cyrus y Kim Kardashian. Así como Trump supo apretar las tuercas en los estados pendulares para ganar las elecciones, ahora las sabrá apretar en la cultura para que la corriente social vaya a su favor.

Todo esto se filtrará muy pronto a Europa y España quedará como una isla en su ignorancia. Rajoy no está haciendo nada por un cambio cultural. Sólo maneja para mantenerse en el sillón a duras penas y no entiende la importancia de la cultura. Los progres siguen a sus anchas, sin plumas y cacareando. Sólo con la irrupción de un partido completamente nuevo (porque Rajoy yo pienso que se marchará cuando se muera, como Franco) podríamos empezar a revertir la situación. Pero también puede este pueblo español necio y ladrón tomar el camino contrario, ir en la dirección de Venezuela a través de Podemos y acabar a puñetazos por dos cebollas mientras se le echa la culpa al “austericidio”, al imperialismo yankee y al heteropatriarcado. Hay que hacer ahora un esfuerzo de divulgación y seguir con atención lo que ocurre fuera.

16:26:37 ———————  EPUB