< Day Day Up > |
Converting Units Between SystemsConverting between different systems of units is a little more complicated than staying within metrics. That's why I suggest estimating distances in meters and estimating speeds in kilometers per hour. Unfortunately, if you grew up in the United States, it's a lot more natural to estimate quantities in English units, such as speeds in miles per hour. In game programming, you'll mostly be dealing with length and time quantities, so we'll focus on those. There will be times when you'll need to convert within the English system, and there will be times when you'll need to convert between the English and metric systems. In either case, the process is the same. When you are converting units, it is very important to keep your work organized. The premise behind this procedure is that when you multiply a number by 1, it stays the same. So if you start with the quantity you want to convert and multiply it by 1 several times, it will not change the quantity. Remember that any fraction whose numerator is equal to the denominator equals 1. The fraction equals 1. The fraction (60 seconds/1 minute) equals 1. All you want to do is multiply the original quantity by a bunch of conversion factors (or ratios), all of which are fractions equal to 1, fractions whose numerator is equal to the denominator. An example of a conversion factor is (60min/1hr). We all know that 60 minutes equals 1 hour, so that fraction equals 1. It is also a conversion factor, because it shows an equality between two different units. You can use that particular conversion factor to convert from hours to minutes. For example, to convert 3 hours to minutes, just multiply by (60min/1hr): Take a close look at the conversion factor (60min/1hr). If it were flipped, it would still be a conversion factor, but it would convert minutes to hours instead. Whenever you're not sure which way to flip, use the units as a guide. When you multiply, you want the old units to cancel out and the new units to stay. Always treat the original quantity as a number over 1 so that you know which way to flip the conversion factor for the units to line up and cancel the way you want. Table 7.1 lists all the conversion factors you should need.
When coding the solutions to these problems, it's a wise idea to make a few constants that can be referenced quickly in code. For example: #define KM_TO_MILES 1.609 #define KM_TO_METERS 1000 #define DAYS_TO_WEEK 7 #define HOURS_TO_DAY 24 #define HOURS_TO_MIN 60 #define MIN_TO_SEC 60 These values are easy enough to determine from looking at Table 7.1 or other sources. Using a constant can make the actual calculation of the values in the game a little easier to read. We also gain the benefit of making wholesale changes throughout the application should one of these values need to be changed. On Earth that might be unlikely, but then again many games don't take place on Earth. A single day on Saturn is a little more than 10.5 Earth hours. The best way to solidify this concept is to work through a few examples. Let's start with a simple time conversion. Example 7.3: Time ConversionHow many seconds are in 2 weeks? Solution
As mentioned earlier, quite often you'll estimate quantities in English units but then program in metric units. Let's look at an example of that process. Here's a quick function that will take a number of days and convert it to seconds. See if you can make your own derivatives of this function to approximate time conversion: float convertDaysToSeconds(float days) { float seconds; seconds = days*HOURS_TO_DAY*HOURS_TO_MIN*MIN_TO_SEC; return seconds; } Take note of how the constants are used here to make the code clean. This is a good technique for making code easy to read. Example 7.4: Distance ConversionSuppose you estimate that the character in your game has run 5 miles. Unfortunately, your team has decided to program in metric units. How many meters has he run? Solution
Coding this out is also pretty straightforward: float convertMilesToMeters(float miles) { float meters; meters = miles*KM_TO_MILES*KM_TO_METERS; return meters; } NOTE Most books use "mi" for miles and "m" for meters when labeling units. This book follows the same standard. When dealing with quantities that have a fraction in the unit, this process becomes slightly more complicated. For example, speeds can be measured in miles per hour (mi/hr). Many errors are made when dealing with the hours on the bottom of the fraction. One way to avoid errors is to write a quantity such as 55mi/hr as 55mi/1hr instead. This might help you keep the conversion factors lined up the way you want. Example 7.5 demonstrates this process. Example 7.5: Speed ConversionSuppose you estimate that the car in your racing game is currently going 180mi/hr. Your team has decided to program in metric units. What is its speed in m/s? Solution
This conversion can also be coded out in a pretty straightforward manner: float convertSpeed(float miles) { float meters; meters = (miles*KM_TO_MILES*KM_TO_METERS)/(HOURS_TO_MIN*MIN_TO_SEC); return meters; } The last complication arises when you have a unit that is squared. For example, acceleration always has a unit of length divided by a unit of time squared, such as m/s2. Remember that s2 is s*s, not just seconds by itself. This means that when you convert, both seconds need to be converted. Let's look at an example to demonstrate this process. Example 7.6: Acceleration ConversionSuppose you estimate that the car in your racing game is currently accelerating at a rate of 20,000mi/hr2. Unfortunately, your team has decided to program in metric units. What is the acceleration in m/s2? Solution
No matter what type of units you need to convert, the process is always the same: You multiply the original quantity by a series of fractions equal to 1 (conversion factors) that eventually bring you to the desired units. Be careful when doing this by hand. Try to keep the fractions lined up so that you don't accidentally divide when you meant to multiply. Also, keep in mind what units you're trying to reach. It's easy to start stacking conversion factors and forget where you were originally going with them. Most importantly, when you're working on a development team, always remember to establish a common set of units before you start programming anything. Conflicting units can lead to disastrous results—just ask NASA! Let's take a look at how to code this conversion. Here is a function that will convert acceleration from MPH2 to m/s2: float convertAccelMilesToMeters(float miles){ float accelMeters; accelMeters = (miles*KM_TO_MILES*KM_TO_METERS) / (HOURS_TO_MIN*MIN_TO_SEC*HOURS_TO_MIN*MIN_TO_SEC); return accelMeters; } Note again the usage of defines in this formula. When the more commonly used conversions are known they are usually computed ahead. For example, instead of converting hours to minutes, then minutes to seconds, we could have just made the quicker jump from hours to seconds. The example is provided here to map with the previous explanation more than to identify the fastest way to handle the problem. Programming physics in a game that responds quickly is a big challenge that needs to reduce the processing as much as possible. Look for such opportunities in your own code. Self-Assessment
|
< Day Day Up > |