新建一个cocos2d-chipmunk项目
首先AppDelegate.m中加入
- (void)applicationDidFinishLaunching:(UIApplication *)application{
cpInitChipmunk();
}
初始化!!
然后添加类
TestWorld.h
//
// TestWorld.h
// TestPiking
//
// Created by Rayln Guan on 10/3/13.
// Copyright 2013 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "chipmunk.h"
#import "TestSprite.h"
#import "TestSprite2.h"
@interface TestWorld : CCLayerColor {
cpSpace *space;
cpShape *wall[4];
}
+ (CCScene *)scene;
@end
//
// TestWorld.m
// TestPiking
//
// Created by Rayln Guan on 10/3/13.
// Copyright 2013 __MyCompanyName__. All rights reserved.
//
#import "TestWorld.h"
@implementation TestWorld
+ (CCScene *)scene{
TestWorld *t = [TestWorld node];
CCScene *s = [CCScene node];
[s addChild: t];
return s;
}
- (id)init{
if(self = [self initWithColor:ccc4(166, 166, 166, 255)]){
self.isAccelerometerEnabled = YES;
self.isTouchEnabled = YES;
//init physics
[self initPhysics];
[self initSprite];
[self scheduleUpdate];
}
return self;
}
-(void) initSprite{
TestSprite *t1 = [[TestSprite alloc] initWithSpace:space];
[self addChild:t1 z:0 tag:1];
TestSprite2 *t2 = [[TestSprite2 alloc] initWithSpace:space];
[self addChild:t2 z:0 tag:1];
}
//该方法是触发chipmunk的重新渲染
-(void) update:(ccTime)time{
// Should use a fixed size step based on the animation interval.
int steps = 2;
CGFloat dt = [[CCDirector sharedDirector] animationInterval]/(CGFloat)steps;
for(int i=0; i<steps; i++){
cpSpaceStep(space, dt);
}
}
-(void) initPhysics{
CGSize s = [[CCDirector sharedDirector] winSize];
//创建一个space
space = cpSpaceNew();
//设置一个重力的x,y,即是垂直和横向的重力
space->gravity = ccp(10, 10);
//物理空间设定默认的碰撞回调函数,它的设置是针对全局的,也就是物理空间里任何对象的碰撞都会执行设定的回调函数
//cpSpaceSetDefaultCollisionHandler
//设定自定义的碰撞回调规则
cpSpaceAddCollisionHandler(space, 1, 2, begin, NULL, NULL, NULL, NULL);
//设置四面墙壁
wall[0] = cpSegmentShapeNew( space->staticBody, cpv(0,0), cpv(s.width,0), 0.0f);
// top
wall[1] = cpSegmentShapeNew( space->staticBody, cpv(0,s.height), cpv(s.width,s.height), 0.0f);
// left
wall[2] = cpSegmentShapeNew( space->staticBody, cpv(0,0), cpv(0,s.height), 0.0f);
// right
wall[3] = cpSegmentShapeNew( space->staticBody, cpv(s.width,0), cpv(s.width,s.height), 0.0f);
for( int i=0;i<4;i++) {
//摩擦力
cpShapeSetElasticity( wall[i], 1.0f );
//反作用力
cpShapeSetFriction( wall[i], 1.0f );
cpSpaceAddStaticShape(space, wall[i] );
}
}
static int begin(cpArbiter *arb, cpSpace *space, void *unused){
// Get pointers to the two bodies in the collision pair and define local variables for them.
// Their order matches the order of the collision types passed
// to the collision handler this function was defined for
//CP_ARBITER_GET_SHAPES取出是哪两个shape发生了碰撞,a,b是emery还是bullet,与之前设置回调函数时的第2,3参数的顺序有关
CP_ARBITER_GET_SHAPES(arb, a, b);
NSLog(@"begin collision p_x:%1.1f p_y:%1.1f",a->body->p.x,a->body->p.y);
NSLog(@"%i, %i", a->collision_type, b->collision_type);
// additions and removals can't be done in a normal callback.
// Schedule a post step callback to do it.
// Use the hook as t he key and pass along the arbiter.
//我们不能直接在begin函数里面释放刚体或者shape,要等chipmunk做完必要的计算后才能释放。cpSpaceAddPostStepCallback用来安全的完成这个步骤
cpSpaceAddPostStepCallback(space, (cpPostStepFunc)postStepRemove, a, NULL);
// The object is dead, don't process the collision further
//返回1是物体撞击事件有效
//返回0是物体撞击事件无效
return 1;
}
//碰撞的处理函数
static void postStepRemove(cpSpace *space, cpShape *shape, void *unused)
{
TestSprite *sprite = shape->data;
assert(sprite.tag == 1);
if( sprite ) {
//[sprite removeFromParentAndCleanup:YES];
}
}
@end
//
// TestSprite.h
// TestPiking
//
// Created by Rayln Guan on 10/3/13.
// Copyright 2013 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "chipmunk.h"
@interface TestSprite : CCSprite {
cpSpace *space;
cpShape *shape;
cpBody *body;
}
- (id)initWithSpace:(cpSpace *)space;
- (void)setShape:(cpSpace *)space;
@end
//
// TestSprite.m
// TestPiking
//
// Created by Rayln Guan on 10/3/13.
// Copyright 2013 __MyCompanyName__. All rights reserved.
//
#import "TestSprite.h"
@implementation TestSprite
- (id)initWithSpace:(cpSpace *)space_{
if (self = [self initWithFile:@"Icon-72.png"]) {
self.position = ccp(100, 100);
self.tag = 1;
int num = 4;
CGPoint vers[4] = {
ccp(-36, -36),
ccp(-36, 36),
ccp(36, 36),
ccp(36, -36)
};
space = space_;
//cpBodyNew创建一个刚体,参数如下:刚性质量,刚性惯性值。
//惯性值的计算使用chipmunk提供的cpMomentForPoly助手函数,参数如下:刚体质量。多边形点数量。多边形点的坐标集。偏移量,会作用到每个点,设为CGPointZero会让事情简单很多。
body = cpBodyNew(1.0f, cpMomentForPoly(1.0f, num, vers, CGPointZero));
//设置body的位置
body->p = ccp(100, 100);
cpSpaceAddBody(space, body);
shape = cpPolyShapeNew(body, num, vers, CGPointZero);
//自定义一个类型,用于回调函数用,否则不会回调
shape->collision_type = 1;
//shape->e = .5f;shape->u = .5f;
shape->data = self;
cpSpaceAddShape(space, shape);
//cpSpaceAddStaticShape(space, shape);
//cpSpaceSetGravity( space, cpv(0, -100) );
}
return self;
}
- (void)setShape:(cpSpace *)space_{
//shape = shape_;
space = space_;
}
//重写该方法,返回YES,这样可以触发nodeToParentTransform方法
- (BOOL)dirty{
return YES;
}
//重烩Sprite,如果不懂什么意思,可以直接用该方法
-(CGAffineTransform) nodeToParentTransform
{
CGFloat x = body->p.x;
CGFloat y = body->p.y;
if ( ignoreAnchorPointForPosition_ ) {
x += anchorPointInPoints_.x;
y += anchorPointInPoints_.y;
}
// Make matrix
CGFloat c = body->rot.x;
CGFloat s = body->rot.y;
if( ! CGPointEqualToPoint(anchorPointInPoints_, CGPointZero) ){
x += c*-anchorPointInPoints_.x + -s*-anchorPointInPoints_.y;
y += s*-anchorPointInPoints_.x + c*-anchorPointInPoints_.y;
}
// Translate, Rot, anchor Matrix
transform_ = CGAffineTransformMake( c, s,
-s, c,
x, y );
return transform_;
}
- (void)removeFromParentAndCleanup:(BOOL)cleanup{
// cpSpaceRemoveBody(space, shape->body);
// cpBodyFree(shape->body);
//
// cpSpaceRemoveShape(space, shape);
// cpShapeFree(shape);
[super removeFromParentAndCleanup:cleanup];
}
@end