Created
June 24, 2012 16:42
-
-
Save pixelrevision/2983946 to your computer and use it in GitHub Desktop.
A very simple character class for use with cocos2D iphone. Will perform basic collision testing with a orthogonal CCTMXTiledMap. Very useful if wanting to get something up and running quickly without wrestling with box2d or chipmunk.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
#import "cocos2d.h" | |
@interface CCTMXMapCharacter : CCNode { | |
CCTMXTiledMap *_map; | |
CCTMXLayer *_collidersLayer; | |
CGRect _collisionRect; | |
CGSize _mapSize; | |
CGSize _tileSize; | |
CGSize _actualMapSize; | |
CGPoint _movement; | |
CGPoint _velocity; | |
CGPoint _maxVelocity; | |
CGPoint _acceleration; | |
BOOL _touchingTop; | |
BOOL _touchingBottom; | |
BOOL _touchingLeft; | |
BOOL _touchingRight; | |
BOOL _oversizedCollisionRect; | |
int _oversizedStepsX; | |
int _oversizedStepsY; | |
float _padding; | |
} | |
@property (nonatomic, retain) CCTMXTiledMap *map; | |
@property (nonatomic, assign) CGPoint velocity; | |
@property (nonatomic, assign) CGRect collisionRect; | |
@property (nonatomic, assign) CGPoint maxVelocity; | |
@property (nonatomic, assign) CGPoint acceleration; | |
- (void)moveRight:(float)amount; | |
- (void)moveLeft:(float)amount; | |
- (void)moveUp:(float)amount; | |
- (void)moveDown:(float)amount; | |
- (void)normalizeVelocity; | |
- (void)update:(ccTime)deltaTime; | |
- (CGPoint)validateTile:(CGPoint)tile; | |
- (void)resetCollisionFlags; | |
- (void)checkForOversizedCollisionRect; | |
- (BOOL)overlapsCharacter:(CCTMXMapCharacter*)character; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "CCTMXMapCharacter.h" | |
@implementation CCTMXMapCharacter | |
@synthesize map = _map; | |
@synthesize velocity = _velocity; | |
@synthesize collisionRect = _collisionRect; | |
@synthesize maxVelocity = _maxVelocity; | |
@synthesize acceleration = _acceleration; | |
- (id)init{ | |
self = [super init]; | |
_padding = 0.1f; | |
_velocity = CGPointMake(0.0f, 0.0f); | |
_maxVelocity = CGPointMake(1000.0f, 1000.0f); | |
_collisionRect = CGRectMake(100.0f, 300.0f, 16.0f, 16.0f); | |
[self schedule:@selector(update:)]; | |
return self; | |
} | |
- (void)setMap:(CCTMXTiledMap *)m{ | |
if(_map){ | |
[_map release]; | |
_map = nil; | |
} | |
if(m){ | |
_map = [m retain]; | |
} | |
if(_map){ | |
_mapSize = [_map mapSize]; | |
_tileSize = [_map tileSize]; | |
_actualMapSize = CGSizeMake(_mapSize.width * _tileSize.width, _mapSize.height * _tileSize.height); | |
_collidersLayer = [_map layerNamed:@"colliders"]; | |
[self checkForOversizedCollisionRect]; | |
} | |
} | |
- (void)setCollisionRect:(CGRect)collRect{ | |
_collisionRect = collRect; | |
[self checkForOversizedCollisionRect]; | |
} | |
- (void)checkForOversizedCollisionRect{ | |
_oversizedCollisionRect = NO; | |
_oversizedStepsX = 1; | |
_oversizedStepsY = 1; | |
if(_collisionRect.size.width > _tileSize.width){ | |
_oversizedStepsX = ceil(_collisionRect.size.width/_tileSize.width); | |
_oversizedCollisionRect = YES; | |
} | |
if(_collisionRect.size.height > _tileSize.height){ | |
_oversizedStepsY = ceil(_collisionRect.size.height/_tileSize.height); | |
_oversizedCollisionRect = YES; | |
} | |
} | |
- (void)moveRight:(float)amount{ | |
if(!_collidersLayer){ | |
_collisionRect.origin.x = _collisionRect.origin.x + amount; | |
return; | |
} | |
float right = floor((_collisionRect.origin.x + _collisionRect.size.width + amount)/_tileSize.width); | |
float nextOffset = 0.0f; | |
int numSteps = ceil(_collisionRect.size.height/_map.tileSize.height); | |
float incSize = _collisionRect.size.height/numSteps; | |
for(int y=0; y<=numSteps; y++) { | |
CGPoint next = CGPointMake(right, floor((_collisionRect.origin.y + nextOffset)/_tileSize.height) ); | |
if ([_collidersLayer tileAt:next]) { | |
_touchingRight = YES; | |
_collisionRect.origin.x = (next.x * _tileSize.width) - _collisionRect.size.width - _padding; | |
return; | |
} | |
nextOffset += incSize; | |
} | |
_collisionRect.origin.x = _collisionRect.origin.x + amount; | |
} | |
- (void)moveLeft:(float)amount{ | |
if(!_collidersLayer){ | |
_collisionRect.origin.x = _collisionRect.origin.x + amount; | |
return; | |
} | |
float left = floor((_collisionRect.origin.x + amount)/_tileSize.width); | |
float nextOffset = 0.0f; | |
int numSteps = ceil(_collisionRect.size.height/_map.tileSize.height); | |
float incSize = _collisionRect.size.height/numSteps; | |
for(int y=0; y<=numSteps; y++) { | |
CGPoint next = CGPointMake(left, floor((_collisionRect.origin.y + nextOffset)/_tileSize.height) ); | |
if ([_collidersLayer tileAt:next]) { | |
_touchingLeft = YES; | |
_collisionRect.origin.x = (next.x * _tileSize.width) + _tileSize.width + _padding; | |
return; | |
} | |
nextOffset += incSize; | |
} | |
_collisionRect.origin.x = _collisionRect.origin.x + amount; | |
} | |
- (void)moveUp:(float)amount{ | |
if(!_collidersLayer){ | |
_collisionRect.origin.y = _collisionRect.origin.y + amount; | |
return; | |
} | |
float top = floor((_collisionRect.origin.y + amount)/_tileSize.height); | |
float nextOffset = 0.0f; | |
int numSteps = ceil(_collisionRect.size.width/_map.tileSize.width); | |
float incSize = _collisionRect.size.width/numSteps; | |
for(int x=0; x<=numSteps; x++){ | |
CGPoint next = CGPointMake(floor((_collisionRect.origin.x + nextOffset)/_tileSize.width), top); | |
if ([_collidersLayer tileAt:next]) { | |
_touchingTop = YES; | |
_collisionRect.origin.y = (next.y * _tileSize.height) + _tileSize.height + _padding; | |
return; | |
} | |
nextOffset += incSize; | |
} | |
_collisionRect.origin.y = _collisionRect.origin.y + amount; | |
} | |
- (void)moveDown:(float)amount{ | |
if(!_collidersLayer){ | |
_collisionRect.origin.y = _collisionRect.origin.y + amount; | |
return; | |
} | |
float bottom = floor((_collisionRect.origin.y + _collisionRect.size.height + amount)/_tileSize.height); | |
float nextOffset = 0.0f; | |
int numSteps = ceil(_collisionRect.size.width/_map.tileSize.width); | |
float incSize = _collisionRect.size.width/numSteps; | |
for(int x=0; x<=numSteps; x++) { | |
CGPoint next = CGPointMake(floor((_collisionRect.origin.x + nextOffset)/_tileSize.width), bottom); | |
if ([_collidersLayer tileAt:next]) { | |
_touchingBottom = YES; | |
_collisionRect.origin.y = (next.y * _tileSize.height) - _collisionRect.size.height - _padding; | |
return; | |
} | |
nextOffset += incSize; | |
} | |
_collisionRect.origin.y = _collisionRect.origin.y + amount; | |
} | |
- (CGPoint)validateTile:(CGPoint)tile{ | |
if(tile.x < 0){ | |
tile.x = 0; | |
} | |
if(tile.x >= _mapSize.width){ | |
tile.x = _mapSize.width - 1; | |
} | |
if(tile.y < 0){ | |
tile.y = 0; | |
} | |
if(tile.y >= _mapSize.height){ | |
tile.y = _mapSize.height - 1; | |
} | |
return tile; | |
} | |
- (void)normalizeVelocity{ | |
if(_velocity.x > _maxVelocity.x){ | |
_velocity.x = _maxVelocity.x; | |
}else if(_velocity.x < -_maxVelocity.x){ | |
_velocity.x = -_maxVelocity.x; | |
} | |
if(_velocity.y > _maxVelocity.y){ | |
_velocity.y = _maxVelocity.y; | |
}else if(_velocity.y < -_maxVelocity.y){ | |
_velocity.y = -_maxVelocity.y; | |
} | |
} | |
- (void)resetCollisionFlags{ | |
_touchingRight = NO; | |
_touchingLeft = NO; | |
_touchingTop = NO; | |
_touchingBottom = NO; | |
} | |
- (BOOL)overlapsCharacter:(CCTMXMapCharacter*)character{ | |
return CGRectIntersectsRect(_collisionRect, character.collisionRect); | |
} | |
- (void)update:(ccTime)deltaTime{ | |
[self resetCollisionFlags]; | |
// apply acceleration | |
if(_acceleration.x > 0 || _acceleration.x < 0){ | |
_velocity.x = _velocity.x + (_acceleration.x * deltaTime); | |
} | |
if(_acceleration.y > 0 || _acceleration.y < 0){ | |
_velocity.y = _velocity.y + (_acceleration.y * deltaTime); | |
} | |
// apply velocity | |
[self normalizeVelocity]; | |
if(_velocity.x > 0.0f){ | |
[self moveRight:_velocity.x * deltaTime]; | |
}else if(_velocity.x < 0.0f){ | |
[self moveLeft:_velocity.x * deltaTime]; | |
} | |
if(_velocity.y > 0.0f){ | |
[self moveDown:_velocity.y * deltaTime]; | |
}else if(_velocity.y < 0.0f){ | |
[self moveUp:_velocity.y * deltaTime]; | |
} | |
// coordinate use top left to work well with the tile map | |
CGPoint newPos = CGPointMake(_collisionRect.origin.x + (_collisionRect.size.width/2), _actualMapSize.height - (_collisionRect.origin.y + (_collisionRect.size.height/2) )); | |
[self setPosition:newPos]; | |
} | |
- (void)dealloc{ | |
self.map = nil; | |
[self unschedule:@selector(update:)]; | |
[super dealloc]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment