storyline

introduction

approach

analysis


run the applet

see the code


CS 476 Homepage

Pursuit of a User Controlled Space Ship

through a field of moving asteroids


Created By:
Jared Winston
Nate Rauh

Storyline

A few short months ago a giant heap of planetary rock raced through the solar system. Drifting dangerously close to the planet Mars, it was caught by the gravity of the planet, creating an impact unlike any seen before. Solid rock debris the size of cities and mountains was hurled beyond the Martian orbit, some on a course of collision with planet Earth.

In light of imminent devastation, the people of Earth generously pooled their resources, working together to build the fastest and most maneuverable ship technology could provide, equipping it with a laser capable of pulverizing the roughest and toughest surfaces known to man, yet harmless to the hull of another ship--in accordance with the principles of nonviolence. This is your ship, and to save the Earth from the terror of incoming asteroids is your mission.

Meanwhile, an alliance of corporations, knowing they stood to profit greatly from the impending destruction of parts of the planet, invested in the development of a second ship, sending it forth with one goal... to stop you from destroying the asteroids. Your adversary is equipped with an impenetrable hull and state-of-the-art asteroid evasion technology. But even this super advanced technology can't predict the future to 100% accuracy. Moreover, time was short and there was no time for a laser. Yet this ship boasts armor so tough it will smash through anything on impact--your ship included. Avoid it at all costs.

Good luck Space Ship Pilot,
And may the Force be with you.

start Asteroids now


Introduction

Our project is based on the simple asteroids game, which implements a user controlled ship, a pursuer ship, and a field of asteroids. The pursuer ship calculates a path towards the user controlled ship--a moving goal! So it must continuously recalculate its path.

Like the typical asteroids game, the user controlled ship wins by destroying all the asteroids without running into any, while evading the pursuer ship. Firing range is limited to 1/4 the length of the screen. The ship is moved with thrusters, forward (UP arrow key) or backward (DOWN arrow key), taking into account proper Newtonian Mechanics, with the magnitude of thrust equal to 1 pixel. Rotations clockwise (RIGHT arrow key) or counterclockwise (LEFT arrow key) are allowed at PI/16 radians each.

The asteroid field consists of anywhere from 20 to 40 randomly positioned asteroids. Asteroids have anywhere from 4 to 9 edges. Very large asteroids split when fired at. Smaller asteroids shrink. Tiny asteroids disappear completely, as they no longer pose a threat to the Earth. Each asteroid has its own velocity. Currently, we allow asteroids to pass through each other.

The pursuer follows the user controlled ship on a path around the asteroids. Ideally, the pursuer would implement a full RRT planning algorithm, but on account of requiring fast computations, we use a variation of RRT, limited by depth and biased towards a moving goal.


Approach

The World
Our world is a 2 dimensional torus manifold.

When a ship or asteroid leaves one side of the screen, it reappears on the opposite side. We decide when an polygon has left the boundary of the screen by looking to see if its center point is outside the boundary of the screen.

The Asteroid Field The asteroid field class uses an array to keep track of all the asteroids at a given moment in time. We have defined procedures to allow us to see into the future in order to accurately predict future collisions with asteroids. This field also is updated if an asteroid is shrunk, split, or destroyed by a ship.

Collision Detection


collision

collision

collision

no collision

no collision

Collision Detection Optimization
We started our collision detection method using the ideas first presented in class with unions of hyperplanes of convex polygons. However, we also used the much faster method for collision detection. We look at the convex polygons as circles and use the radius of the circle to determine if the ship enters into the boundaries of another polygon's circle. If so, it could be in collision. If not, then collision detection is not necessary.

Firing into a Field of Asteroids
Shooting at asteroids requires yet another form of collision detection: checking for the intersection of a line (laser beam) with a polygon (asteroid). This involves finding the intersection of a line with each edge of a polygon. The laser beam is determined by the segment beginning at the center of the ship, extending through its front point, for a distance of 1/4 the length of the screen. Any asteroid edges intersecting this segment are possible collisions. Of these, only the intersection closest to the ship is counted, since the energy of a laser beam is absorbed when hitting an asteroid.

Predictability
Clearly, our problem contains a time element. Furthermore, it contains a random element. Future configurations are predictable, but only to the extent that unpredictable events--an asteroid being hit by a laser or any acceleration of the user controlled ship--do not occur. For this reason, we consider it practical only to path plan within a limited timeframe.

Limited Timeframe RRT
Okay. We made that name up ourselves. But it seems an accurate description of what we are trying to do. Such an RRT is similar to a standard RRT, except (1) there is a limit placed on tree depth, and (2) we will usually not reach the goal by a single RRT. Instead we join together multiple partial paths, dynamically generated as needed. Whenever a path continuation is needed, future positions of the asteroid field and goal are predicted given their current velocities. In planning, we then use the configuration at timeframe equal to the depth. The depth also serves to limit tree growth, as nodes at the maximum depth are never considered for extending.

Each RRT node contains a possible configuration of the pursuer ship at timeframe equal to the depth of that node. From the closest node to the target ship, we calculate a path back to the root, giving a sequence of the commands needed at each step to navigate the pursuer ship to that point. The RRT tree is recalculated only when necessary: when the asteroid field changes due to being fired at, or when we have followed nearly all the commands along the path towards the goal. The RRT is not recalculated when the user accelerates even though this changes the goal configuration. This is done to improve performance, since even though the goal will be slightly off within that depth limit, the pursuer will still avoid the obstacles.

Another optimization in planning is taking advantage of a low obstacle-space-to-free-space ratio. The RRT begins with a series of "extend"s directly to the goal, accounting for the quite common case when no asteroids are nearby for much of the path. This idea was taken from class.

When following the new path, we are careful not to follow it to completion. Even assuming our future predictions remain accurate, our depth limit does not allow us to take into account configurations at or beyond time = depth + 1. If we follow the path to completion, we may find ourselves stuck with collisions imminent no matter what we do. A limited path becomes less safe as we get closer to the depth limit. Therefore, we allot the four time frames at the end of each path to look-ahead only, starting a new path when we reach this point.

Predicting Future Positions
Rather than creating a tree that tries to connect the pursuer ship to the goal ship, we look for a future position of the goal ship. We do this in an attempt to cut off the pursued ship. Since we cannot always expect the pursued ship to travel in a straight line, we limit how far in time we can make predictions. And we predict future positions, of both asteroids and pursued ship, by simulating the next few timeframes.

The Physics of Extend
A space ship must obey the laws of physics--pursuer ship included. Extending towards a goal configuration means more than moving towards the goal when thrust and speed constraints are involved. First, the pursuer must be given a maximum speed, or else it would continue to accelerate as much as it likes towards the goal, making the game unplayable. Second, the pursuer needs a maximum thrust to prevent it from changing direction in an unreasonable way.

Given the fact the a ship often has a non-zero current velocity, we cannot simply apply thrust in the direction of the goal. Instead we must apply thrust so as to cause the ship to move in the direction of the goal, if possible. If this is not possible, we must apply a thrust that causes the ship to move at a lesser rate away from the goal.

The first observation is that for a goal configuration, the rotation of the ship does not matter--a collision at any angle is still a collision. Secondly, it is always best to apply the maximum thrust if this does not cause us to exceed the maximum speed. Thirdly, when applying the maximum thrust in combination with the current velocity vector, two resultant vectors are possible along the line through the current ship and goal. We must then choose whichever of these brings us closer to the goal.

But sometimes, v is larger than maximum thrust, and there is no resultant vector possible along the line from current position to goal. In this case, we apply maximum thrust along the perpendicular to the line from current position to goal, in order to bring the ship closer to achieving a velocity towards the goal.


The Applet

Note that you may need to click on the applet area once started to activate it for receiving keyboard input. Also, the applet can be very slow on networked unix machines in the lab. You may want to download it (including the game.html file) and run it on your own machine.

The Applet

Maneuvering the User-Controlled Ship

  • up arrow key: FORWARD
  • down arrow key: BACKWARD
  • right arrow key: CLOCKWISE
  • left arrow key: COUNTER-CLOCKWISE
  • space bar: FIRE

Cheating: For the sake of testing, you may turn invincibility on/off by pressing "i".


The Code

Our project is written in Java, using object oriented development. The code is logically separated into the following nine classes.

See readme.txt for information on how to compile and run. If your machine and browser are powerful enough, you will also be able to run our project off this web page. See the previous section for details.

Click here to see the entire contents of the folder containing the code

Reading the code you will likely notice (and be annoyed with) our lack of proper Java coding conventions, specifically, accessor functions. This was necessary for performance reasons.


Analysis

Why the Pursuer Ship Jitters
One of the problems we have is the appearance of the pursuer ship. It looks as if it jitters wildly in rotation. This is what it is supposed to do. What is happening is the pursuer ship is continually adjusting its velocity. To do this it must point in the direction of change of motion. Given the ability of a ship to apply rotations of any angle within a single timeframe, the pursuer ship may appear to rotate wildly, seemingly pointing in the wrong direction.

When no thrust is being applied, we make the pursuer ship point towards the goal. We did this because without adjustments of rotation after a thrust, the pursuer ship looks as if it is flying sideways. Thus we point it at the goal when thrust is zero. That way it points towards the goal as it flies towards it. This also may cause a lot of wild rotations if alternating frames have thrust/no thrust.

Pursuing the User Ship
All in all, the pursuer ship does its pursuing very well. Sometimes we've caught the pursuer ship "hanging out" behind asteroids, waiting for them to move out of the way. Sometimes it darts around and between them. Occasionally, it thinks it's trapped and smashes a few. And sometimes it just goes a little wacko. One thing for certain: it's not an easy thing to evade our pursuer.

Pursuing Asteroids
Our goal is to have the pursuer avoid asteroids at all costs. However, within the depth limit and time constraints this isn't always possible. Due to our reliance on the randomness of the RRT, it is possible for the randomly chosen points to all result in collisions. And from time to time this happens, especially at the start of a game when asteroids are large, plentiful, and the pursuer ship starts out in a corner of the screen. In fact, this situation is more likely to arise any time the pursuer is near an edge of the screen.

Why? Well, ships and asteroids move in a 2D torus manifold. But extend() uses planar coordinates so path planning occurs in planar space. This means that when randomly distributed goal configurations are used, we will usually extend away from the edge of the screen. So when the only free space is towards the edge of the screen, there is a good chance our RRT won't find that free space within its time constraints, and as a result, the pursuer ship smashes through a few asteroids.

Pursuing Nothing
Okay. Start up a game, turn on the invincibility cheat mode. Shoot down all the asteroids, but leave one so the game doesn't end. You'd think our pursuer would pretty much follow your every move. Especially since we've got that optimized RRT initially extending straight towards the goal. You'd think. Go ahead. Stop your ship or get it moving real slow. Now just what is that crazy pursuer ship doing? At times it goes on extended periods of drifting away from the goal! Doesn't that ship even care about conserving fuel? We can't figure it out either.

No Fair!
Our initialization function dictates that the initial configurations assigned to the pursuer and user ships cannot be in collision with asteroids. But there are no guarantees about subsequent time frames. Basically, you might never have a chance to move before being hit by an asteroid, and this is just plain no fair. Our solution if this happens... reload the applet.

Possible Improvements

  • Implement continuous collision detection so that objects do not "jump" over each other between timeframes.
  • Do collision detection between asteroids, having them smash together into a larger asteroid or bounce off each other, breaking into many smaller pieces. Results of such collisions would be unpredictable!
  • Recalculate the pursuer's path every time the user ship accelerates.
  • Predict the future goal configuration based on how far the user ship can fly and how long it takes to get there.
  • Perform extend in the 2D torus manifold instead of planar space.
  • Teach the pursuer to fire at the user ship (& maybe at asteroids too?)
  • Use C++ so you can use deeper LT-RRTs.
  • Wait 5 years and use deeper LT-RRTs in Java.
  • Heck, just forget the whole RRT thing and use intelligent asteroids that just speed up and get out of the way of the pursuer ship.
Now wouldn't that all be cool? Some of these improvements would make for a whole project all by themselves.