Tank Rampage’s tank is our pièce de resistance. It’s build up from 25 separate sprites and 27
joints. Its movements are fully simulated, including the tracks and
antenna.
The tank’s sprites |
The tank’s joints |
Barrel
The tanks barrel is attached to the
main body using a revolute joint. When the player touches the left side of the
screen (the aiming area), the tanks aims towards that point and fires when the
touch is ended.
Programmatically, this works as follows:
The screen is touch and a touch method in our
main gameplay layer class (BoomlyApp –reminiscent of the first name of our
game) is called;
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if (!gameEnded) { for( UITouch *touch in touches ) { CGPoint location = [touch locationInView: [touch view]]; location = [[CCDirector sharedDirector] convertToGL: location]; if (location.x>screenSize.width/2) { //tankPosRelativeToScreen CGPoint tankRelPos= ccp(0.2*screenSize.width,0.4*screenSize.height); float angle= -1*CC_RADIANS_TO_DEGREES(ccpToAngle(ccpSub(location, tankRelPos))); [tank changeAim:angle]; } else if(location.x>=screenSize.width/6){ [tank driveBackward]; } else { [tank driveForward]; } }}}
After checking whether the game has ended or not, the position of the
touch is checked. If the touch is located on the right half of the screen, the
angle from the tank’s body to the touch is calculated by subtracting the
locations to get the vector of the difference, then calculating the angle of
that vector. It is then converted to degrees and passed on to the TankClass as
an argument in the changeAim method.
If the touch is
moved, a different the ccTouchesMoved method is called. The contents of the method
is the exact same as the ccTouchesBegan method in Tank Rampage.
The changeAim
method serves as a setter for the float desiredAngle;
-(void)changeAim:(float)aim{ desiredAngle=-1*CC_DEGREES_TO_RADIANS(aim); }
The actual changing of the barrel’s rotation happens in the TankClass’
update method;
float deltaAngle = (desiredAngle - (-1* CC_DEGREES_TO_RADIANS( barrel.rotation))); // how much correction float normalizedAngle=deltaAngle; // make sure angle is between -pi and pi while (normalizedAngle>M_PI) { normalizedAngle=M_PI; } while (normalizedAngle<-m_pi data-blogger-escaped-barreljoint-="barreljoint-" data-blogger-escaped-complete="complete" data-blogger-escaped-correction="correction" data-blogger-escaped-desiredomega="normalizedAngle/dt;" data-blogger-escaped-float="float" data-blogger-escaped-in="in" data-blogger-escaped-normalizedangle="-M_PI;" data-blogger-escaped-one="one" data-blogger-escaped-the="the" data-blogger-escaped-timestep="timestep">SetMotorSpeed(desiredOmega);
As you can see, the amount of correction needed is calculated, which is
then normalized to a value between pi and –pi. It’s then calculated how fast
the barrel joint will need to turn in order for the change to happen in one
frame, and then the joint is turned with that speed. The barrel joint has a
high torque in order to be able to always change the angle.
The
code used to change the barrel rotation is very similar to the code used to
program the servos on a robot. This type of control is called FLVC (force
limited velocity constraint).
This article is part of a small 4-piece series on the tank of Tank Rampage. Next up: tank tracks! Please let me know if you want any more info on this subject, or perhaps a tutorial?
This article is part of a small 4-piece series on the tank of Tank Rampage. Next up: tank tracks! Please let me know if you want any more info on this subject, or perhaps a tutorial?
No comments:
Post a Comment