Here is a condensed step-by-step view into how to create a blue ladybug in Adobe Illustrator CS5.
|Modified on by TomBanks|
The first impression a user has of their race is the most important. It's vital that players are able to see all of the information in order to interpret the game around them. However, too much information can easily overwhelm a new player and make them lose interest. With Coderally, we've taken several steps to ensure users have the best visual experience possible when they play a race.
Three Second Pause
When a race starts, there is a three second pause before the races begins playing. This pause allows the user to see the track, their cars, and get a brief feel for the game environment without feeling like they are jumping off a virtual cliff. This pause isn't just an empty delay that might annoy users - it shows a traffic light countdown to green and keeps their focus on the center of the race.
Some of the tracks are large. They have lots of turns, and can go off-screen, especially on smaller screens or mobile devices. Coderally will pan and follow the player's car, but it's important to be aware of the rest of the track, especially if you aren't sure where the other players are. A minimap offers a visual way to show where other cars are on the race, without needing to display the entire track.
Name Tags & Lap Indicators
It's easy to lose track of which car is yours when watching a fast paced race or violent collision. Name tags that show which car is yours and which are other players provide an easy way to tell cars apart.
Lap indicators allow players to know when the last lap starts, and whether any cars have finished the race. In the upper right corner, it displays a yellow light when any car starts their final lap. It displays a red light when any car finishes the race.
Code Rally features race track environments rendered in a simplistic style with cut-out images and multiple layers of color.
The image sample below showcases the different layers of colors and textures of the Sky Track environment.
How were these graphics created?
The visuals implemented in Code Rally are created using Adobe Photoshop and Illustrator. Adobe Photoshop is a pixel based software and Adobe Illustrator is a vector based software which creates smoother, flatter looking graphics. A distinctive characteristic regarding vector images is that they can be scaled up or down to any size and maintain the same quality. To incorporate vector based art into Photoshop and to maintain the flexibility in scaling, the artwork has to be converted into a smart object. The next time you take a look at the game, see if you can identify which graphics were created in Photoshop and which ones in Illustrator.
All the environment (background) graphics start off as a standard 1024x768 pixel artboard. The backgrounds are made up of a mixture of Photoshop tools and real photographs which are edited and enhanced to blend in seamlessly. Some of the photographs used are mostly of textures found in nature, for example rock, sand or grass which are then adjusted and scaled down to the appropriate size. All the environments have a fairly neutral, toned down color palette overall which enables the viewer to focus more on the vehicles, objects or specimens racing along the track. More contrast and a range of vibrant colors are added to the vehicles in the game as they are smaller elements within the environment.
Stay tuned for my next entry, where I will show you how to create one of these vehicles!
In order to develop your own artificial intelligence to control your vehicle, we developed an event-based system in the game engine. Throughout a race, the engine will throw out certain events at vehicles, and the AIs will call their corresponding method to respond to that event. The AI classes use an API that controls your vehicle, with access to how much you are accelerating and where you want your car to turn. In future releases, we hope to add more events, and more control over your car. For example, it would be cool to have access to special speed boosts and weapons your car may contain. Below is a simple explanation of the current Race Events and API Calls you will look at when programming your vehicle.
The following methods are in the AI interface that you will have to implement to get your car running.
You will use the following API calls to manipulate your vehicle. The list is separated into calls that will give you information, and methods you will use to control your car. More will be added to this list over time.
During our initial brainstorming sessions we acknowledged the need to spend some time exploring the physics-related aspects of the game. However, looking back, I think it's fair to say that we underestimated the complexity of the required computations. Naively thinking that our faint recollection of various formulas from old physics classes would suffice, we charged forward and planned to tackle all physics-related requirements as they arose. This resulted in quite a few learning experiences and code refactoring sessions as the overall complexity gradually rose over time. In the end we decided to integrate a robust, third party physics engine into the game. But before arriving at this final conclusion we implemented a number of our own home-brewed solutions.
In this post I will describe our original method for collision detection (such as between two cars). Although we are now using a powerful physics engine to handle much of this work for us, the engine itself also uses this method (among others) underneath the hood. My intention is to perhaps offer some guidance to anyone wishing to implement their own game physics or to just give a quick look at some of the inner-workings of what you see in the game.
At the core of our method of collision detection is the Separating Axis Theorem (Wikipedia link). The theorem simply states that if two convex objects are not intersecting, then there exists an axis for which the projections of the two objects do not overlap. Note that if you wish to test a concave object you must first break it down to multiple convex objects and individually test each one. SAT is an efficient, generic algorithm for detecting overlap between two entities and its ability to execute relatively quickly makes it often ideal for collision detection in games.
To picture this concept of "overlapping projections", take a look at the image below. In diagram a you see two squares which are clearly not intersecting. If you were to project their respective images onto the horizontal axis as pictured, their projections would not intersect either. As soon as you have found an axis in which these projections do not overlap, you can assert that the objects do not intersect. Conversely, the two squares are clearly intersecting in diagram b. For every possible axis, the projections of the two objects will also overlap, allowing you to assert that the objects themselves are overlapping. For any two polygons, the only axes you must test against are the normals of each edge. To obtain the normal of a vector you simply swap the coordinates and negate one (ie. [5,3] becomes [-3,5]).
Unlike the previous image, objects being tested for collision won't usually be simple, un-rotated squares. You might be dealing with a complex polygon with many vertices. You may be wondering then, what the best way to programatically project these polygons onto an axis is. The answer, luckily, isn't very difficult. You would simply loop over all of a polygon's vertices, perform a dot product between the vertex and the normalized axis to be projected on, and store the minimum and maximum result. Remember that there is a difference between a vector's normal and a normalized vector! In simple pseudocode, this would look similar to the following:
We now know enough to be able to assemble a simple function for determining whether or not two objects are intersecting. But in our racing game, we needed more than simply knowing if two cars are colliding. We also wanted to prevent them from simply driving right over the top of each other. For this reason it is beneficial to calculate the Minimum Translation Vector - a vector which tells us the shortest path to push the two objects apart to keep them from intersecting. Your final collision detection code might look similar to the following pseudocode:
Don't forget that the array of axes in the above code would have to consist of both objects' axes needing testing.
This was a very simplistic overview of the algorithm we employed for collision detection in our beginning stages of development. Before using it yourself, you would likely want to spend some time making the algorithm more efficient (such as by not testing parallel axes) and adding additional functionality to handle curved features or to properly handle the case in which one object is completely engulfed by the other.
Collision detection is just one facet of our physics-related computations. Things seem to get exponentially more complex when you begin to account for resultant forces due to a collision, cancelling out a car's lateral movement due to traction, applying the appropriate amount of torque to turn a car just the right amount, etc. In future blog posts we will discuss our move to the JBox2D physics engine, how much easier this made our lives, and all the cool physics stuff we've been able to put into the game.