The Player's Ship: "The Wraith"The player's ship was hand-drawn. I was going to render it, but it had so much detail that I decided to just draw it and then use Paint Shop Pro to light it and make it look real. In addition, I only drew the Wraith facing north and then used PSP's built-in bitmap rotation to rotate the ship in 16 different angles. The artwork is shown in Figure 15.4. Figure 15.4. The artwork for the Wraith.The Wraith doesn't do much except fly around and shoot, but the friction algorithm is interesting. I wanted the Wraith to look like it was flying under gravity, so I wanted some form of friction when it turned. I implemented this with the standard techniques that you learned in previous chapters. The Wraith has a velocity vector that is modified when the player thrusts in any particular direction. The nice thing about this approach is that you don't have to worry about things like, "If the ship is going east at this speed and the player thrusts north, what should the ship do?" Instead, I let the vector math do it. Here's a portion of the control code for the Wraith: // test if player is moving if (keyboard_state[DIK_RIGHT]) { // rotate player to right if (++wraith.varsI[WRAITH_INDEX_DIR] > 15) wraith.varsI[WRAITH_INDEX_DIR] = 0; } // end if else if (keyboard_state[DIK_LEFT]) { // rotate player to left if (—wraith.varsI[WRAITH_INDEX_DIR] < 0) wraith.varsI[WRAITH_INDEX_DIR] = 15; } // end if // vertical/speed motion if (keyboard_state[DIK_UP]) { // move player forward xv = cos_look16[wraith.varsI[WRAITH_INDEX_DIR]]; yv = sin_look16[wraith.varsI[WRAITH_INDEX_DIR]]; // test to turn on engines if (!engines_on) DSound_Play(engines_id,DSBPLAY_LOOPING); // set engines to on engines_on = 1; Start_Particle(PARTICLE_TYPE_FADE, PARTICLE_COLOR_GREEN, 3, player_x+RAND_RANGE(-2,2), player_y+RAND_RANGE(-2,2), (-int(player_xv)>>3), (-int(player_yv)>>3)); } // end if else if (engines_on) { // reset the engine on flag and turn off sound engines_on = 0; // turn off the sound DSound_Stop_Sound(engines_id); } // end if // add velocity change to player's velocity player_xv+=xv; player_yv+=yv; // test for maximum velocity vel = Fast_Distance_2D(player_xv, player_yv); if (vel >= MAX_PLAYER_SPEED) { // recompute velocity vector by normalizing then rescaling player_xv = (MAX_PLAYER_SPEED-1)*player_xv/vel; player_yv = (MAX_PLAYER_SPEED-1)*player_yv/vel; } // end if // move player, note that these are in world coords player_x+=player_xv; player_y+=player_yv; NOTE About the name Wraith. A long time ago I saw a movie called The Wraith with Charlie Sheen. In the film, Charlie ended up in the trunk of his car, falling off a cliff at 32 ft/sec2. He died and came back as a wraith, which is an evil ghost that takes revenge on its killers. Anyway, he had this cool car, a prototype Dodge Interceptor, and the movie is where I got the name. I thought you should know. (Plus, guess who has the Dodge Interceptor?) Studying the code, you'll notice there is some code to keep the Wraith from going too fast. Basically, I continually check the length of the velocity vector against a MAX length. If it's too long, I shrink it. Another approach could have been to use a unit direction vector and a speed scalar, and then translate the ship each frame an amount equal to the unit vector scaled by the speed. Either way is about the same. Lastly, the Wraith has a shield and a vapor trail. The shield is nothing more than a bitmap that I overlay on the Wraith when something hits it, and the vapor trail is just particles that I emit out randomly when the thrusters are on. The thruster effect is achieved with two bitmaps for each direction of the Wraith: one with thrusters on and one with thrusters off. When the thrusters are on, I randomly select the on/off image and it looks like a Klingon impulse drive. |