Friday, 11 January 2013

Tank Rampage's Tank 1 - Barrel


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?


No comments:

Post a Comment