Permalink
Browse files

Merge branch 'change-angle'

  • Loading branch information...
jakeboxer committed Apr 22, 2012
2 parents 4447071 + 33a4717 commit 671fed9fda8665d13ec770fd5adbe86c2def4496
Showing with 123 additions and 20 deletions.
  1. +2 −0 Pong.xcodeproj/project.pbxproj
  2. +15 −10 Pong/HelloWorldLayer.m
  3. +9 −3 Pong/Models/Ball.h
  4. +97 −7 Pong/Models/Ball.m
@@ -1035,6 +1035,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Pong/Prefix.pch;
"GCC_THUMB_SUPPORT[arch=armv6]" = "";
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INFOPLIST_FILE = Pong/Resources/Info.plist;
OTHER_LDFLAGS = "-lz";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1050,6 +1051,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Pong/Prefix.pch;
"GCC_THUMB_SUPPORT[arch=armv6]" = "";
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INFOPLIST_FILE = Pong/Resources/Info.plist;
OTHER_LDFLAGS = "-lz";
PRODUCT_NAME = "$(TARGET_NAME)";
View
@@ -66,11 +66,9 @@ + (CCScene *)scene {
return scene;
}
-// on "init" you need to initialize your instance
- (id)init {
self = [super init];
- // Apple recommends to re-assign "self" with the "super" return value
if(nil != self) {
CCLabelTTF *scoreLabel1 = [CCLabelTTF labelWithString:@"" fontName:@"Helvetica" fontSize:24.0f];
scoreLabel1.position = ccp(50.0f, self.contentSize.height - 50.0f);
@@ -113,7 +111,6 @@ - (void)dealloc {
[player2 release];
[scoreLabels release];
- // don't forget to call "super dealloc"
[super dealloc];
}
@@ -128,18 +125,26 @@ - (void)update:(ccTime)dt {
- (void)updateGameObjects:(ccTime)dt {
// Check for ball containment
if (!CGRectContainsRect(self.boundingBox, self.ball.sprite.boundingBox)) {
- if ((self.ball.sprite.topY >= self.contentSize.height && self.ball.velocity.y >= 0) ||
- (self.ball.sprite.bottomY <= 0 && self.ball.velocity.y <= 0)) {
+ if ((self.ball.sprite.topY >= self.contentSize.height && [self.ball isMovingUp]) ||
+ (self.ball.sprite.bottomY <= 0 && [self.ball isMovingDown])) {
// Ball collided with a top/bottom wall and is moving in that wall's direction.
- [self.ball flipVelocityY];
+ [self.ball flipAngleVertically];
}
}
// Check for ball collisions.
- if ((CGRectIntersectsRect(self.ball.sprite.boundingBox, self.player1.sprite.boundingBox) && self.ball.velocity.x <= 0) ||
- (CGRectIntersectsRect(self.ball.sprite.boundingBox, self.player2.sprite.boundingBox) && self.ball.velocity.x >= 0)) {
+ Player *collidingPlayer = nil;
+
+ if (CGRectIntersectsRect(self.ball.sprite.boundingBox, self.player1.sprite.boundingBox) && [self.ball isMovingLeft]) {
+ collidingPlayer = self.player1;
+ } else if (CGRectIntersectsRect(self.ball.sprite.boundingBox, self.player2.sprite.boundingBox) && [self.ball isMovingRight]) {
+ collidingPlayer = self.player2;
+ }
+
+ if (nil != collidingPlayer) {
// Ball collided with a paddle and is moving in the paddle's direction.
- [self.ball flipVelocityX];
+ CGFloat percentageFromCenter = (self.ball.sprite.position.y - collidingPlayer.sprite.position.y) / collidingPlayer.sprite.contentSize.height;
+ [self.ball updateAngleAfterHittingPaddleAtPercentageFromCenter:percentageFromCenter];
}
[self.ball update:dt];
@@ -246,7 +251,7 @@ - (void)startGame {
- (void)resetGameState {
self.ball.sprite.position = self.center;
- self.ball.velocity = ccp(-160.0f, 80.0f);
+ self.ball.angleInRadians = 5.0f * M_PI / 6.0f;
self.player1.sprite.position = ccp(self.player1.sprite.halfWidth + 16.0f, self.halfHeight);
self.player2.sprite.position = ccp(self.contentSize.width - self.player2.sprite.halfWidth - 16.0f, self.halfHeight);
View
@@ -10,11 +10,17 @@
@interface Ball : NSObject
-- (void)flipVelocityX;
-- (void)flipVelocityY;
- (void)update:(ccTime)dt;
+- (void)flipAngleHorizontally;
+- (void)flipAngleVertically;
+- (void)updateAngleAfterHittingPaddleAtPercentageFromCenter:(CGFloat)percentage;
+- (BOOL)isMovingLeft;
+- (BOOL)isMovingRight;
+- (BOOL)isMovingUp;
+- (BOOL)isMovingDown;
@property (nonatomic, retain) CCSprite *sprite;
-@property (nonatomic, assign) CGPoint velocity;
+@property (nonatomic, assign) CGFloat angleInRadians;
+@property (nonatomic, assign) CGFloat speed;
@end
View
@@ -8,17 +8,27 @@
#import "Ball.h"
+@interface Ball ()
+
++ (CGFloat)normalizedAngle:(CGFloat)angle;
+- (CGFloat)xOffsetOverTime:(ccTime)dt;
+- (CGFloat)yOffsetOverTime:(ccTime)dt;
+
+@end
+
@implementation Ball
+@synthesize angleInRadians;
+@synthesize speed;
@synthesize sprite;
-@synthesize velocity;
#pragma mark - Creation/removal methods
- (id)init {
self = [super init];
-
+
if (nil != self) {
+ self.speed = 5.0f;
self.sprite = [CCSprite spriteWithFile:@"ball.png"];
}
@@ -28,17 +38,97 @@ - (id)init {
#pragma mark - Scheduled methods
- (void)update:(ccTime)dt {
- self.sprite.position = ccpAdd(self.sprite.position, ccpMult(self.velocity, dt));
+ self.sprite.position = ccpAdd(self.sprite.position, ccp([self xOffsetOverTime:dt], [self yOffsetOverTime:dt]));
}
#pragma mark - Movement methods
-- (void)flipVelocityX {
- self.velocity = ccp(-self.velocity.x, self.velocity.y);
++ (CGFloat)normalizedAngle:(CGFloat)angle {
+ while (angle >= M_PI * 2.0f) {
+ angle -= M_PI * 2.0f;
+ }
+
+ while (angle < 0) {
+ angle += M_PI * 2.0f;
+ }
+
+ return angle;
+}
+
+- (void)flipAngleHorizontally {
+ CGFloat offsetAngle;
+
+ if (self.angleInRadians > M_PI) {
+ offsetAngle = 3.0f * M_PI;
+ } else {
+ offsetAngle = M_PI;
+ }
+
+ self.angleInRadians = offsetAngle - self.angleInRadians;
+}
+
+- (void)flipAngleVertically {
+ if (self.angleInRadians > 0) {
+ self.angleInRadians = 2.0f * M_PI - self.angleInRadians;
+ }
+}
+
+- (void)updateAngleAfterHittingPaddleAtPercentageFromCenter:(CGFloat)percentage {
+ [self flipAngleHorizontally];
+
+ CGFloat absoluteOffset = M_PI_4 * percentage;
+ CGFloat newAngle;
+
+ if ([self isMovingRight]) {
+ // Moving right.
+
+ // Offset is easy cuz increasing the angle always points further upwards.
+ newAngle = [Ball normalizedAngle:self.angleInRadians + absoluteOffset];
+
+ // Restriction is hard cuz of 2*pi - 0 cutoff.
+ if (newAngle >= 3.0f * M_PI_2) {
+ // Bottom-right quadrant (3*pi/2 to 2*pi). Restrict to above 19*pi/12
+ newAngle = MAX(19.0f * M_PI / 12.0f, newAngle);
+ } else {
+ // Top-right quadrant (0 to pi/2). Restrict to below 5*pi/12
+ newAngle = MIN(5.0f * M_PI / 12.0f, newAngle);
+ }
+ } else {
+ // Moving left.
+
+ // Offset is easy cuz increasing the angle always points further downwards.
+ newAngle = [Ball normalizedAngle:self.angleInRadians - absoluteOffset];
+
+ // Restriction is easy. Restrict to between 7*pi/12 and 17*pi/12
+ newAngle = MAX(7.0f * M_PI / 12.0f, newAngle);
+ newAngle = MIN(17.0f * M_PI / 18.0f, newAngle);
+ }
+
+ self.angleInRadians = newAngle;
+}
+
+- (BOOL)isMovingLeft {
+ return self.angleInRadians >= (M_PI_2) && self.angleInRadians <= (3.0f * M_PI_2);
+}
+
+- (BOOL)isMovingRight {
+ return ![self isMovingLeft];
+}
+
+- (BOOL)isMovingUp {
+ return self.angleInRadians >= 0 && self.angleInRadians <= M_PI;
+}
+
+- (BOOL)isMovingDown {
+ return ![self isMovingUp];
+}
+
+- (CGFloat)xOffsetOverTime:(ccTime)dt {
+ return cosf(self.angleInRadians) * self.speed;
}
-- (void)flipVelocityY {
- self.velocity = ccp(self.velocity.x, -self.velocity.y);
+- (CGFloat)yOffsetOverTime:(ccTime)dt {
+ return sinf(self.angleInRadians) * self.speed;
}
@end

0 comments on commit 671fed9

Please sign in to comment.