jump to navigation

OnLive and latency: the milliseconds chalenge June 18, 2010

Posted by Cesar in gaming me.
Tags: , , ,
add a comment

OnLive is finally here. The system launched yesterday and the team is being very cautious about it. They intend to do a gradual release, starting with fewer users and slowly opening up for everyone. But I don’t have any feedback on the service yet and it will be a while until we have solid numbers, so if you are reading and have something to say, write! I’m particularly interested in access farther away from the servers or in borderline connections (5MB according to OnLive’s FAQ).

Anyway, Gamasutra published a very good interview with Steve Perlman, OnLive’s CEO. And some of what he mentioned made me worry about the service, mostly about the issue everyone is worried about: latency. During the testing phase, Perlman said “99 percent haven’t had any lag complaints”. That is very positive. But in this article at PCWorld, Jared Newman states he experienced choppiness and lag during his tests. OnLive blamed the connection at the convention center.

However, if you put the interview and these first experiences together, you get to my main concern right now: OnLive works, but it takes such a toll on latency that you must be sure everything else works flawlessly.

First things first, OnLive’s main argument is very valid. That is: most of the latency is introduced in what they call the “last mile”. The distance from the server allegedly doesn’t matter much as long as the connection from the computer to ISP is good.

So they are already blaming someone else, right? “Our service is awesome, the problem is with the ISPs”. If you think about the network structure, it makes perfect sense. I hope the new age of remote computing forces ISPs to improve their networks and reduce overall latency. However, it is very easy to say something works in a structure that doesn’t exist. It is like making the most beautiful game ever, but that runs at 5 fps, and blaming GPU manufacturers (anyone thinking Crysis?).

But the other arguments I saw in the interview are worse. I never heard a casual gamer complaining about monitor latency, keyboard latency or mouse latency before. And those are the other reasons for big latency according to Perlman. Again: “Our service is awesome, maybe you just don’t have the right mouse”. Is it fair to blame the peripheral industry? Is it fair to say their service works and throw the problem over the fence? OnLive is the newcomer that should adapt to the current technology.

In my view, if mouse latency is a huge deal, that means it is just the last drop. I interpret that as: OnLive has an acceptable latency by itself, in vacuum, but take it to the atmosphere of the real world and the small latency caused by everything else adds up to an amount that makes the OnLive experience problematic.

Be that as it may, by Perlman’s speech it seems like all problems are solvable. So if you have a good connection to your ISP and small latency peripherals, OnLive should work and work well. And that’s a huge accomplishment. The problems shouldn’t stop gamers from testing the service. More than that, the choice to acquire OnLive and other remote solutions might in the long run force ISPs and peripheral manufacturers start making improvements. And if you have a good ISP at hand, OnLive still means you can run top notch games at high resolutions in low budget computers, which is amazing. I myself intend to try it as soon as possible. I want to play high res games on my laptop!

Just don’t come saying everything is fine and start pointing fingers. That’s just not right.

Side note: on January 29, I wrote a post mentioning OnLive on the iPad as a distant dream and somewhat of a joke. While it is still distant, other people thought of it (or maybe they read gaming me? lol) and it ended up in a proof of concept you can check here. Isn’t it cool?

See you space cowboys…

Brazil 2 x 1 Korea DPR June 16, 2010

Posted by Cesar in sporting me.
Tags: , , , , , ,

Brazilians celebrating the first goal

Of course, after all I’m Brazilian, in our office pool I bet Brazil 5 x 0 Korea DPR. But that’s the heart talking. The truth is the game was exactly how I expected it to be.

Brazil has a very strong counter attack, which Korea didn’t offer. And when the other team goes to the pitch with the sole goal of defending, with zero offensive pretensions, it is always hard to score. Very hard. In Brazil we are used to seeing this kind of team during the first stage of the Libertadores. Small teams, from countries with little to no football tradition, often go to Brazil with at most one attacker, who waits near the midfield, and 10 players try to make the time pass as uneventfully as possible.

I’ve been following the World Cup and yesterday’s game was the most obvious example of this attitude so far. In these situations, what usually defines the number of goals is how fast the first goal (if any) happens. The goal forces a posture change and spaces start to appear. Yesterday, the goal came too late, hence the small number of goals.

Once again it is funny to see the difference between the press in Canada and in Brazil. Here, the commentators were impressed with the Brazilian strategy, the strength of our side backs and the tactical discipline of the players. And they praised the Korean defense like there was no tomorrow. After the first half, they were very impressed that Korea DPR resisted the Brazilian pressure.

Then I check the Brazilian commentators online: everyone is pissed, complaining about the trouble the team had to pierce the Korean DPR fragile defensive system.

I think the truth is in the middle (as usual). At the end of the game, Brazil had 65% of the ball possession and had shot 26 times, as opposed to 10 shots by Korea. These are impressive numbers which show Brazil dominated the game from beginning to finish. What we need is to be a bit more efficient.

In time: Maicon had an amazing match. Supported by Gilberto Silva, who protected the right side when he was acting as a true winger, Maicon made all the difference and his goal was beautiful. On the other hand, Kaká continues to disappoint. I hope he has time to catch up, it would make all the difference.

See you space cowboys…

Last minute update: Spain vs. Switzerland just finished with a victory for the Swiss. It goes to prove my point: true, Switzerland is way better than Korea DPR, but it is very hard to play against a team whose only purpose is to defend. Switzerland has a strong defense and will cause trouble in the knockout stage.

Brazilians are not used to it June 15, 2010

Posted by Cesar in sporting me.
Tags: , , , , ,
1 comment so far

Brasil celebrating the Confederations Cup in 2009

Is it just me or is the World Cup the best competition in the world? I simply love it. I don’t know if it is because I’m away from Brazil, but the World Cup is driving me crazy (in a good way). Every game is interesting. Yes, even Japan vs. Cameroon.

Anyway, with the first Brazil match a few hours away, I thought it was time to write about it. I’m sure I’ll write again, but talking about the Brazilian team and the World Cup in general seems like the appropriate way to go for a first post on the subject.

One of the most interesting things about being away from Brazil during a World Cup is to learn how the rest of the world sees the Brazilian football team. I look at our midfield, with… erm… weird players like Felipe Melo, Elano and Gilberto Silva and it makes me very uneasy. Kaká aside, this is not a top notch midfield at all. I look at our attack and it bothers me too. Luis Fabiano and Robinho are not on par with other strikers from previous generations (Romário and Ronaldo just to name the most recent ones).

That’s in part Dunga’s fault. After the last World Cup’s fiasco, the captain of the 1994 campaign was called to give Brazil in 2010 what they lacked in 2006: heart. And he succeeded! But unfortunately, somewhere along the long 4 years towards South Africa, heart and defensive football got mixed together, and we ended up with a team that excels at protecting the goal but lacks creativity. The example I give to everyone when I talk about the subject is Ronaldinho. I don’t like him, in my opinion he never reached superstar level simply because he could never play well in the national team (ok, ok, there’s that one single game against England in 2002, but that’s all). But Dunga’s team is so defensive and unimaginative that I wish he was there. Even if it was to be an option coming from the bench.

However, despite all that, the rest of the world thinks Brasil has an amazing team. Everyone is afraid of Brazil, they think at any moment our team can decide a game and score goals with astonishing ease. And while I do envy Argentina’s attack and Spain’s midfield, I also believe we can win the World Cup.

But if it happens, it won’t be Brazil style, it will be Italy style. Strong defense and good counters go a long way on the second stage, as Italy proved in 2006. The truth is that we Brazilians are not used to having a good attack and a decent midfield. We are used to deadly strikers and amazing midfielders. That’s all. This year our football is different, but it is also very effective.

Oh man! You gotta love the World Cup! Writing made me super anxious! Today at 4:00 pm I’ll be in front of the TV, standing with my right hand on my chest, singing the national anthem. Júlio Cesar, Lúcio, Maicon, Kaká, everyone: make us proud! And good luck Brazil!!!!!

See you space cowboys…

Mario vs. Pacman June 11, 2010

Posted by Cesar in gaming me.
Tags: , , , ,
add a comment

According to Kotaku, this short animation is part of a Russian ad campaign promoting a potato chips brand. Sounds weird? The ads too. But they are awesome! Insanely hilarious! Each of the clips features a… erm… fierce competition between two famous characters, some of them from video games like the one above.

No point in saying anything else. Just watch. If you like it (if you don’t you are not nerdy enough), check the others. I highly recommend Leonidas vs. Chuck Norris and Skywalker vs. Neo.

See you space cowboys…

New game: Toy Story 3! June 9, 2010

Posted by Cesar in working me.
Tags: , , , ,

Toy Story 3

I’m proud to say that my latest project here at Other Ocean, Toy Story 3 for the Leapster Explorer,was recently announced!

The Leapster Explorer is a gaming platform from Leap Frog and has a heavy focus on kids and educational content. But don’t be fooled by the colorful look of the device. The Leapster Explorer has a very solid performance and the touch screen only adds to the fun. It was announced yesterday (I guess most kids don’t care about the iPhone 4) and is being very well received.

Toy Story 3 was a joy to develop. It follows a style similar to Mario Party, with board games and plenty of mini-games. Working with the game logic was fun and the development cycle had several interesting challenges. But the best part was dealing with the Toy Story 3 characters. Our team did so well with the animations! I had a lot of fun just watching things happen on the screen.

Congratulations to everyone involved, that was a job very well done.

See you space cowboys…

AI navigation in Left 4 Dead: Part II June 8, 2010

Posted by Cesar in working me.
Tags: , , , , , , , , ,
add a comment

After a long period of inactivity, it’s about time we continue our analysis on Michael Booth’s presentation about the AI in Left 4 Dead.

If you remember the last post on the subject, I tried to give a bit more depth to the reactive path following algorithm described in the slides. With that side implemented, we got a nice and fast path finding / following algorithm that offers a pretty optimized trajectory without looking artificial. But that’s just half the problem. The macro management half. Now we need to look at micro management and define how the bot moves when following the path.

The first step is simple obstacle avoidance. Our path finding algorithm deals with the static objects, the level itself. But it already introduces, with reactive path following, the concept of steering, which is very important and is used also in this stage. So now our bot must steer towards the next point in the path but also go around moving things that might be in the way: crates, other bots, whatever.

The most simple steering algorithm we can use is to select a direction and try to go around the object. Say the bot bumps into a box. The algorithm must try to pick a direction that leads to the closest way around it, left or right, and steer that way until the path towards the next goal becomes clear again. A simple way to attempt to select the closest way around the obstacle is to use the object center (for simplicity we’ll assume the center is the actual position of the object). All we do is apply a steering force in the opposite direction.

In the presentation, Booth mentions hull trace a lot and I’ll use it for obstacle avoidance too, so it is definitely worth describing. It is not clear if the algorithm uses a collision mesh or a simple box but, for simplicity, let’s consider that it uses an OOBB (Object Oriented Bounding Box). Let’s assume the OOBB fits the bot inside it and it has the same position and orientation as the bot. Hull trace is then an algorithm that projects that OOBB in a given direction and returns the first point of collision. Like a ray tracing algorithm, but with a box instead of a line. If we were using the bot’s collision mesh, we would do the same with the whole mesh instead of the OOBB.

The Hull trace algorithm can be a little complex because in order to make sure we get all collisions we need a sweep test (or a way to fake it, but I digress). It is performance intensive if we use a complex shape. However, with the OOBB the cost is minimal.

With that out of the way, here’s some C++ high level code for the obstacle avoidance algorithm:

// computes obstacle avoidance movement components
void Bot::ObstacleAvoidanceUpdate(f32 m_fDeltaTime)
	Entity* pEntity; // what it hit
	f32 fDistance; // how far it is
	Physics::HullTrace(m_vPosition, m_pHull, m_vSpeed, m_pWorld,
		pEntity, fDistance);

	// We only avoid close dynamic objects. If it is static and the path goes
	// there, it means the bot will climb
	if ((pEntity == NULL)
		|| pEntity->IsStatic()
		|| (fDistance > m_fMaxSteerDistance))

	Vector3 vObstaclePos = pEntity->GetPosition();
	Vector3 vSteeringDirection = (m_vPosition - vObstaclePos).Normalize();

		ComputeAvoidanceTranslation(vSteeringDirection, fDistance),
		ComputeAvoidanceSteering(vSteeringDirection, fDistance),

OK, with this our bots can now go around dynamic objects and other bots. Note that, as in the previous post, I made a call to RequestMovement(). Now that we have 2 systems making requests, the function shows its purpose: to select what to follow. I also chose, again, not to show exactly how to compute the parameters for RequestMovement(). These algorithms are somewhat empirical and usually involve tweaking constant values to get a good looking behavior.

Anyway, now there’s only one step left: climbing. In L4D, it is really cool how the bots climb walls and jump over ledges to reach the players. To do that, our navigation mesh, mentioned in the previous post, must also consider  reachable moving areas on higher ground. If we have that, all that is left is to figure out how to reach the higher points of the map.

This is what Booth talks about in the remaining slides related to navigation. Essentially, every time a bot gets close to a not so high level obstacle in the way to the next point in the navigation mesh, be that the level itself or a movable object, it is going to attempt to jump and climb.

Let’s get to the algorithm per se. Take a look at the image above, the figures are very helpful. Once we detect there’s an obstacle ahead that justifies climbing, the very first step is to check if there’s space above the bot’s head. If there isn’t, he can’t climb. To do that, we perform the infamous hull trace upwards. Once we know there is space above, we need to know if there’s some sort of space in front. So, starting from the bottom, we do a hull trace in the forward movement direction, but changing the y coordinate, so we look for a passage in several different heights. Once a path is found, all that is left is to precise the ledge of the passage way. That is done by performing the hull trace multiple times downwards, until we get what I will call a grabbing point.

At this stage, all the bot really has to do is move. By the height of the grabbing point we can define which animation set to use in order to climb the object.

This concludes this stage of the AI. Below is a high level algorithm with my interpretation of the algorithm that finds the climbing edge. Get ready, it is big:

bool ComputeClimbingEdge(Vector3& p_vEdge)
	Vector3 vSpeedDirection = m_vSpeed.Normalize();

	Entity* pEntity;
	f32 fGroundDistance;
	Physics::HullTrace(m_vPosition, m_pHull, vSpeedDirection,
		m_pWorld, pEntity, fGroundDistance);

	// We only climb static objects that are in proper range.
	// If the bot is steering to avoid the obstacle, we also
	// return
	if ((pEntity == NULL)
		|| !pEntity->IsStatic()
		|| (fGroundDistance > m_fTestClimbingDistance)
		|| (m_fSteering > m_fTestClimbingSteering)
		return false;

	//Climbing will start, now we need to find the edge

	// First the maximum height
	f32 fCeilingDistance;
	Entity* pCollidable;
	Physics::HullTrace(m_vPosition, m_pHull, m_pWorld->GetUpVector(),
		m_pWorld, pCollidable, fCeilingDistance);
	if (pCollidable == NULL)
		fCeilingDistance = m_fMaximumClimbingHeight;

	// now we look for the horizontal gap in the wall, starting from the bottom
	Vector3 vForwardTracePosition;
	for (f32 fTestHeight = 0;
		fTestHeight < fCeilingDistance;
		fTestHeight += m_fHullStep)
		f32 fForwardDistance;
		vForwardTracePosition = m_vPosition
			+ (m_pWorld->GetUpVector() * fTestHeight);
		Physics::HullTrace(vForwardTracePosition, m_pHull, m_vSpeed,
			m_pWorld, pCollidable, fForwardDistance);

		// the diameter of the hull is just a guess of a decent value
		if (fForwardDistance
			>= fGroundDistance + m_pHull->GetHorizontalDiameter())

	// move forward a bit so we trace from the top of the new level
	Vector3 vDownTracePosition = vForwardTracePosition
		+ vSpeedDirection
			* (fGroundDistance + m_pHull->GetHorizontalDiameter());
	// trace down to get the precise height;
	f32 fLevelDistance;
	Physics::HullTrace(vDownTracePosition, m_pHull, -m_pWorld->GetUpVector(),
		m_pWorld, pCollidable, fLevelDistance);

	// now we trace back
	// creating first final edge position candidate:
	p_vEdge = vDownTracePosition - m_pWorld->GetUpVector() * fLevelDistance;
	for (f32 fBackDistance = 0;
		fBackDistance <= fGroundDistance + m_pHull->GetHorizontalDiameter();
		fBackDistance += m_fHullPrecisionStep)
		Vector3 vTestEdgePosition = vDownTracePosition
			- (vSpeedDirection * fBackDistance);
		f32 fDownDistance;
		Physics::HullTrace(vTestEdgePosition, m_pHull, -m_pWorld->GetUpVector(),
			m_pWorld, pCollidable, fDownDistance);

		if (fDownDistance > (fLevelDistance + m_fSafetyLevelDelta))
			p_vEdge = vTestEdgePosition
				- (m_pWorld->GetUpVector() * fDownDistance);

	// we got a valid result in p_vEdge
	return true;

I should mention that some assumptions are made about the environment: we assume the passage is not too narrow and that it is at a regular height. I also assumed after the first check the HullTrace() method always hits a valid entity.

The Bot::ComputeClimbingEdge() function is called in the Bot::Update() function, together with the other ones previously defined. After everything is done, the system processes the several movement requests and actually moves the bot.

I think that closes the subject at least for now. I hope what I left unexplained is not to hard to figure out. But I’m tempted to post more on the subject so who knows? Maybe we’ll have another one in the series.

Ah, if you decide to implement it, don’t forget that everything that goes up must go down. The bot has to check for edges on the ground too in order to climb or jump back to the ground!

See you space cowboys…


%d bloggers like this: