为Pong设置CPU难度

时间:2014-06-12 14:43:49

标签: ios objective-c pong

第二次在这里希望有人能指导我朝着正确的方向前进。

我试图在iOS设备(iPhone / iPod / iPad)的应用程序中实现Pong游戏,它运行得很好,除了我无法击败CPU,更不用说了得分。这是实现.m代码:

#import "BTM_pongGame.h"
#import <QuartzCore/QuartzCore.h>

#define STEP_DURATION 0.05
#define RESET_BALL_ANIMATION_DURATION 0.5f
#define MARGIN_WHERE_BALL_IS_LEAVING 40
//#define CPU_SKILL 20

@interface BTM_pongGame ()

@end

@implementation BTM_pongGame


@synthesize cpuSkill, ballShape;

- (void)viewDidLoad
{
    [super viewDidLoad];

    cpuSkill = [BT_strings getJsonPropertyValue:self.screenData.jsonVars nameOfProperty:@"cpuSkill" defaultValue:@"20"];
    ballShape = [BT_strings getJsonPropertyValue:self.screenData.jsonVars nameOfProperty:@"ballShape" defaultValue:@"1"];

    if ([ballShape  isEqual: @"1"]) {

        self.ball.layer.cornerRadius = self.ball.frame.size.width / 2;

    } else {

        //self.ball.layer.cornerRadius = self.ball.frame.size.width / 2;

    }



}


- (void) wordsPerLineInfoShowAlert {

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Choose Game"
                                                    message:@"Multiplayer or Single Player? You decide! Choose below."
                                                   delegate:self
                                          cancelButtonTitle:@"Single Player"
                                          otherButtonTitles:@"Go Back",@"Multi Player", nil];

    [alert show];

}


- (void)alertView: (UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{



    NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
    if([title isEqualToString:@"Single Player"]) {

        [self resetPlayerScoreLabels];
[self updatePlayerScoreLabels];

          self.mode = kGameSinglePlayer;
        [self moveComputerPaddle];

        //Disable panning of computer paddle
        [self.playerOne.superview setGestureRecognizers:@[]];
    [self resetBoardForNewRound];

    } else if ([title isEqualToString:@"Multi Player"]) {

[self resetPlayerScoreLabels];
[self updatePlayerScoreLabels];

        self.mode = kGameMultiPlayer;


        [self resetBoardForNewRound];

    } else if ( [title isEqualToString:@"Go Back"]){


        [self navLeftTap];

    }

}







// thanks to MrsVanBeveren for coding the reset score stuff
 -(void)resetPlayerScoreLabels
{
    playerOneScore = 0;
    playerTwoScore = 0;
}




-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [self wordsPerLineInfoShowAlert];

    [self startGameTimer];
}

-(void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
    [_gameTimer invalidate];
}

-(void)quitPressed:(id)sender
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

-(void)startGameTimer
{
    [_gameTimer invalidate];
    _gameTimer = [NSTimer scheduledTimerWithTimeInterval:STEP_DURATION target:self selector:@selector(step:) userInfo:nil repeats:YES];
}

#pragma mark Game setup

/*
 * Some maths to calculate a new starting direction
 * By choosing mid left/right part of the unit circle
 *  we avoid getting straight up/down directions
 */
-(void)resetBallDirection
{
    float randomUnity = arc4random_uniform(100)/100.0;
    int horizontalDirection = (arc4random() % 2 ? 1 : -1);
    float angle = M_PI_4 + randomUnity * M_PI_2;
    float direction = horizontalDirection * angle;

    dirX = sin(direction);
    dirY = cos(direction);
}

-(void)resetBoardForNewRound
{
    speed = self.view.frame.size.width / 50.0;

    [self resetBallDirection];

    [_gameTimer invalidate];

    [UIView animateWithDuration:RESET_BALL_ANIMATION_DURATION animations:^{
        self.ball.center = CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0);
    } completion:^(BOOL finished){
        [self startGameTimer];
    }];

    [self enlargeAnimation:self.ball];

}

-(void)updatePlayerScoreLabels
{
    self.playerOneScoreLabel.text = [NSString stringWithFormat:@"%d",playerOneScore];
    self.playerTwoScoreLabel.text = [NSString stringWithFormat:@"%d",playerTwoScore];
}


#pragma mark Paddle handling
- (IBAction)paddlePanned:(UIPanGestureRecognizer*)recognizer {
    UIView *paddleWrapper = recognizer.view;
    UIView *paddle = [[paddleWrapper subviews] lastObject];
    switch([recognizer state]) {
        case UIGestureRecognizerStateBegan: {
            paddle.backgroundColor = UIColor.whiteColor;
        }
            break;

        case UIGestureRecognizerStateChanged: {

            CGPoint position = [recognizer locationInView:self.view];

            CGFloat haldPaddleHeight = paddleWrapper.frame.size.height / 2.0;

            CGPoint newCenter = paddleWrapper.center;
            newCenter.y = position.y;

            newCenter.y = MAX(haldPaddleHeight, newCenter.y);
            newCenter.y = MIN(self.view.bounds.size.height - haldPaddleHeight, newCenter.y);

            paddleWrapper.center = newCenter;

        }
            break;

        case UIGestureRecognizerStateEnded: {
            paddle.backgroundColor = UIColor.grayColor;
        }
            break;

        default:
            break;
    }
}

#pragma mark Game loop

/*
 * Game loop
 *  - Moves the ball and checks for obstacles
 */
- (void)step:(NSTimer*)timer
{
    speed += 0.05;
    [self checkForBallLevingSide];

    CGPoint newCenter = self.ball.center;
    CGFloat ballRadius = self.ball.frame.size.height / 2.0;

    newCenter.x += dirX * speed;
    newCenter.y += dirY * speed;

    CGFloat upperEdge = ballRadius;
    CGFloat bottomEdge = self.view.bounds.size.height - ballRadius;

    // Bounce ball of top/bottom walls
    if (newCenter.y <= upperEdge) {
        dirY = ABS(dirY);
        newCenter.y = upperEdge;
    } else if (newCenter.y >= bottomEdge) {
        dirY = -ABS(dirY);
        newCenter.y = bottomEdge;
    }

    [UIView animateWithDuration:STEP_DURATION animations:^{
        self.ball.center = newCenter;
    }];


}

-(BOOL)didBallHitPaddle:(UIView *)paddle withinLimit:(CGFloat)limit
{
    if (CGRectIntersectsRect(paddle.frame, self.ball.frame)){
        [self deflectBallFromPaddle:paddle];
        CGRect ballFrame = self.ball.frame;
        ballFrame.origin.x = limit;
        self.ball.frame = ballFrame;
        return YES;
    } else
        return NO;
}

-(void)checkForBallLevingSide
{

    float limitLeft = MARGIN_WHERE_BALL_IS_LEAVING;
    float limitRight = self.view.bounds.size.width - self.ball.frame.size.width - MARGIN_WHERE_BALL_IS_LEAVING;

    CGRect ballFrame = self.ball.frame;
    CGFloat ballX = ballFrame.origin.x;

    if (ballX < limitLeft) {
        if (![self didBallHitPaddle:self.playerOne.superview withinLimit:limitLeft])
            [self playerDidMiss:kPlayerOne];
    }else if (ballX > limitRight) {
        if (![self didBallHitPaddle:self.playerTwo.superview withinLimit:limitRight])
            [self playerDidMiss:kPlayerTwo];
    }


}

/*
 * Calculates new dirX and dirY after the bounce.
 * The longer from the paddle's middle the bigger the result angle gets. (Pong style)
 */
-(void)deflectBallFromPaddle:(UIView *)paddle
{
    dirX *= -1;

    CGFloat diff = self.ball.center.y - paddle.center.y;
    float p = diff / paddle.frame.size.height * 2.0f;
    dirY += p * 0.5;


}


-(void)playerDidMiss:(kPlayer)player
{
    if (player == kPlayerOne) {
        playerTwoScore++;
        [self victoryShake:self.playerTwo];
        [self enlargeAnimation:self.playerTwoScoreLabel];
    }
    else if (player == kPlayerTwo) {
        playerOneScore++;
        [self victoryShake:self.playerOne];
        [self enlargeAnimation:self.playerOneScoreLabel];
    }

    [self resetBoardForNewRound];
    [self updatePlayerScoreLabels];
}

-(void)moveComputerPaddle
{
    UIView *paddle = self.playerOne.superview;
    CGPoint cpuCenter = paddle.center;
    CGFloat diff = self.ball.center.y - paddle.center.y;
    CGFloat movement = MIN((int)cpuSkill, ABS(diff));

    movement *= diff > 0 ? 1 : -1;

    cpuCenter.y += movement;

    [UIView animateWithDuration:0.1 animations:^{
        self.playerOne.superview.center = cpuCenter;
    } completion:^(BOOL b) {
        [self moveComputerPaddle];
    }];
}

#pragma mark Animation
-(void)victoryShake:(UIView *)view
{
    CAKeyframeAnimation * anim = [ CAKeyframeAnimation animationWithKeyPath:@"transform" ] ;
    anim.values = [ NSArray arrayWithObjects:
                   [ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0f, -20.0f, 0.0f) ],
                   [ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0f, 20.0f, 0.0f) ],
                   nil ] ;
    anim.autoreverses = YES ;
    anim.repeatCount = 4.0f ;
    anim.duration = 0.07f ;

    [view.layer addAnimation:anim forKey:nil];
}

-(void)enlargeAnimation:(UIView *)view
{
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
    animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
    animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(3.0, 3.0, 1.0)];
    [animation setDuration:RESET_BALL_ANIMATION_DURATION * 0.5];
    animation.repeatCount = 1.0f ;
    [animation setAutoreverses:YES];

    [view.layer addAnimation:animation forKey:nil];
}

@end

我只是尝试更改其中#define CPU_SkILL再次@"cpuSkill" defaultValue:@"20"];的数字,但我没有改变任何方向的数字。

有什么想法吗?

提前谢谢。

1 个答案:

答案 0 :(得分:0)

cpuSkill变量控制CPU控制的桨的移动:

CGFloat movement = MIN((int)cpuSkill, ABS(diff));

因此,在所有情况下,cpuSkill可能高于预期。尝试更低的值或在计算后对运动进行一些随机的微调。

此外,你应该ABS() cpuSkill以避免在负面移动时完美移动。