cocos2d-x 简单游戏例子

原文:http://www.raywenderlich.com/28606/how-to-create-a-breakout-game-with-box2d-and-cocos2d-2-x-tutorial-part-2


可以在这里下载我打包的APK文件:http://download.csdn.net/detail/u010639508/5869737


我翻成C++的代码(包括resources):https://github.com/serika00/android/tree/master/cocos2d-x/BreakoutGame

cocs2d-x-2.14 + vs2010

运行截图:




HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "Box2D/Box2D.h"
#include "MyContactListener.h"

#define PTM_RATIO 32
USING_NS_CC;

class HelloWorld : public cocos2d::CCLayer
{
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::CCScene* scene();
    
    // a selector callback
    void menuCloseCallback(CCObject* pSender);
    
    // implement the "static node()" method manually
    CREATE_FUNC(HelloWorld);

	b2World* _world;
	b2Body* _groundBody;
	b2Fixture* _bottomFixture;
	b2Fixture* _ballFixture;
	b2Body* _paddleBody;
	b2Fixture* _paddleFixture;
	b2MouseJoint* _mouseJoint;
	MyContactListener* _contactListener;

	void tick(float dt);
	void dealloc();
	virtual void ccTouchesBegan(CCSet* pTouches, CCEvent* pEvent);
	virtual void ccTouchesMoved(CCSet* pTouches, CCEvent* pEvent);
//	void ccTouchesCancelled(CCSet* pTouches, CCEvent* pEvent);
	virtual void ccTouchesEnded(CCSet* pTouches, CCEvent* pEvent);
};

#endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();
    
    // 'layer' is an autorelease object
    HelloWorld *layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
	CCSize winSize = CCDirector::sharedDirector()->getWinSize();

	b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
	_world = new b2World(gravity);

	b2BodyDef groundBodyDef;
	groundBodyDef.position.Set(0, 0);
	_groundBody = _world->CreateBody(&groundBodyDef);

	b2EdgeShape groundBox;
	b2FixtureDef groundBoxDef;
	groundBoxDef.shape = &groundBox;

	groundBox.Set(b2Vec2(0, 0), b2Vec2(winSize.width/PTM_RATIO, 0));
	_bottomFixture = _groundBody->CreateFixture(&groundBoxDef);

	groundBox.Set(b2Vec2(0, 0), b2Vec2(0, winSize.height/PTM_RATIO));
	_groundBody->CreateFixture(&groundBoxDef);

	groundBox.Set(b2Vec2(0, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 
		winSize.height/PTM_RATIO));
	_groundBody->CreateFixture(&groundBoxDef);

	groundBox.Set(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO),
		b2Vec2(winSize.width/PTM_RATIO, 0));
	_groundBody->CreateFixture(&groundBoxDef);

	CCSprite *ball = CCSprite::create("ball.png");
	ball->setTag(1);
	ball->setPosition(ccp(100, 100));
	addChild(ball);

	b2BodyDef ballBodyDef;
	ballBodyDef.type = b2_dynamicBody;
	ballBodyDef.type = b2_dynamicBody;
	ballBodyDef.position.Set(100/PTM_RATIO, 100/PTM_RATIO);
	ballBodyDef.userData = ball;
	b2Body* ballBody = _world->CreateBody(&ballBodyDef);

	b2CircleShape circle;
	circle.m_radius = 26.0/PTM_RATIO;

	b2FixtureDef ballShapeDef;
	ballShapeDef.shape = &circle;
	ballShapeDef.density = 1.0f;
	ballShapeDef.friction = 0.0f;
	ballShapeDef.restitution = 1.0f;
	_ballFixture = ballBody->CreateFixture(&ballShapeDef);

	b2Vec2 force = b2Vec2(10, 10);
	ballBody->ApplyLinearImpulse(force, ballBodyDef.position);

	CCSprite* paddle = CCSprite::create("paddle.png");
	paddle->setPosition(ccp(winSize.width/2, 50));
	addChild(paddle);

	b2BodyDef paddleBodyDef;
	paddleBodyDef.type = b2_dynamicBody;
	paddleBodyDef.position.Set(winSize.width/2/PTM_RATIO, 50/PTM_RATIO);
	paddleBodyDef.userData = paddle;
	_paddleBody = _world->CreateBody(&paddleBodyDef);

	b2PolygonShape paddleShape;
	paddleShape.SetAsBox(paddle->getContentSize().width/PTM_RATIO/2, paddle->getContentSize().height/PTM_RATIO/2);

	b2FixtureDef paddleShapeDef;
	paddleShapeDef.shape = &paddleShape;
	paddleShapeDef.density = 10.0f;
	paddleShapeDef.friction = 0.4f;
	paddleShapeDef.restitution = 0.1f;
	_paddleFixture = _paddleBody->CreateFixture(&paddleShapeDef);

	setTouchEnabled(true);
	_mouseJoint = NULL;
	
	b2PrismaticJointDef jointDef;
	b2Vec2 worldAxis(1.0f, 0.0f);
	jointDef.collideConnected = true;
	jointDef.Initialize(_paddleBody, _groundBody,
		_paddleBody->GetWorldCenter(), worldAxis);
	_world->CreateJoint(&jointDef);

	_contactListener = new MyContactListener();
	_world->SetContactListener(_contactListener);

	for (int i = 0; i < 4; i++) {
		static int padding=20;
		CCSprite* block = CCSprite::create("block.png");
		int xOffset = padding + block->getContentSize().width/2 +
			((block->getContentSize().width + padding)*i);
		block->setPosition(ccp(xOffset, 250));
		block->setTag(2);
		addChild(block);

		b2BodyDef blockBodyDef;
		blockBodyDef.type = b2_dynamicBody;
		blockBodyDef.position.Set(xOffset/PTM_RATIO, 250/PTM_RATIO);
		blockBodyDef.userData = block;
		b2Body* blockBody = _world->CreateBody(&blockBodyDef);

		b2PolygonShape blockShape;
		blockShape.SetAsBox(block->getContentSize().width/PTM_RATIO/2,
			block->getContentSize().height/PTM_RATIO/2);

		b2FixtureDef blockShapeDef;
		blockShapeDef.shape = &blockShape;
		blockShapeDef.density = 10.0;
		blockShapeDef.friction = 0.0;
		blockShapeDef.restitution = 0.1f;
		blockBody->CreateFixture(&blockShapeDef);
	}

	schedule(schedule_selector(HelloWorld::tick));

//	dealloc();
    return true;
}


void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    CCDirector::sharedDirector()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

void HelloWorld::tick(float dt) {
	bool blockFound = false;
	_world->Step(dt, 10, 10);
	for (b2Body* b = _world->GetBodyList(); b; b = b->GetNext()) {
		if (b->GetUserData() != NULL) {
			CCSprite* sprite = (CCSprite*)b->GetUserData();
			if (sprite->getTag() == 2) {
				blockFound = true;
			}
			sprite->setPosition(ccp(b->GetPosition().x*PTM_RATIO, b->GetPosition().y*PTM_RATIO));
			sprite->setRotation(-1*CC_RADIANS_TO_DEGREES(b->GetAngle()));
			if (sprite->getTag() == 1) {
				static int maxSpeed = 10;
				b2Vec2 velocity = b->GetLinearVelocity();
				float32 speed = velocity.Length();
				if (speed > maxSpeed) {
					b->SetLinearDamping(0.5);
				} else if (speed < maxSpeed) {
					b->SetLinearDamping(0.0);
				}
			}
		
		}
	}
	std::vector<b2Body*> toDestroy;
	std::vector<MyContact>::iterator pos;
	for (pos = _contactListener->_contacts.begin();
		 pos != _contactListener->_contacts.end(); ++pos) {
			MyContact contact = *pos;
			if ((contact.fixtureA == _bottomFixture && contact.fixtureB == _ballFixture)
				|| (contact.fixtureA == _ballFixture && contact.fixtureB == _bottomFixture)) {
					CCLog("You Lose :[");
			}

			b2Body* bodyA = contact.fixtureA->GetBody();
			b2Body* bodyB = contact.fixtureB->GetBody();
			if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
				CCSprite* spriteA = (CCSprite*)bodyA->GetUserData();
				CCSprite* spriteB = (CCSprite*)bodyB->GetUserData();

				if (spriteA->getTag() == 1 && spriteB->getTag() == 2) {
					if (std::find(toDestroy.begin(),  toDestroy.end(), bodyB) == toDestroy.end()) {
						toDestroy.push_back(bodyB);
					}
				} else if (spriteA->getTag() == 2 && spriteB->getTag() == 1) {
					if (std::find(toDestroy.begin(), toDestroy.end(), bodyA) == toDestroy.end()) {
						toDestroy.push_back(bodyA);
					}
				}
			}
	}
	std::vector<b2Body*>::iterator pos2;
	for (pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) {
		b2Body* body = *pos2;
		if (body->GetUserData() != NULL) {
			CCSprite* sprite = (CCSprite*)body->GetUserData();
			this->removeChild(sprite);
		}
		_world->DestroyBody(body);
	}
	
	if (!blockFound) {
		CCLog("You Won!");
	}
	
}

void HelloWorld::dealloc() {
	delete _world;
	_groundBody = NULL;
	delete _contactListener;
}

void HelloWorld::ccTouchesBegan(CCSet* pTouches, CCEvent* pEvent) {
	if (_mouseJoint != NULL) return;

	CCTouch* myTouch = (CCTouch*)pTouches->anyObject();
	CCPoint location = myTouch->getLocation();
	location = CCDirector::sharedDirector()->convertToGL(location);
	b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);

//	if (_paddleFixture->TestPoint(locationWorld)) {
	if (1) {
		b2MouseJointDef md;
		md.bodyA = _groundBody;
		md.bodyB = _paddleBody;
		md.target = locationWorld;
		md.collideConnected = true;
		md.maxForce = 1000.0f*_paddleBody->GetMass();

		_mouseJoint = (b2MouseJoint*)_world->CreateJoint(&md);
		_paddleBody->SetAwake(true);
	}
}

void HelloWorld::ccTouchesMoved(CCSet* pTouches, CCEvent* pEvent) {
	if (_mouseJoint == NULL) return;

	CCTouch* myTouch = (CCTouch*)pTouches->anyObject();
	CCPoint location = myTouch->getLocation();
	location = CCDirector::sharedDirector()->convertToGL(location);
	b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);

	_mouseJoint->SetTarget(locationWorld);
}
/*
void HelloWorld::ccTouchesCancelled(CCSet* pTouches, CCEvent* pEvent) {
	if (_mouseJoint) {
		_world->DestroyJoint(_mouseJoint);
		_mouseJoint = NULL;
	}
}
*/
void HelloWorld::ccTouchesEnded(CCSet* pTouches, CCEvent* pEvent) {
	if (_mouseJoint) {
		_world->DestroyJoint(_mouseJoint);
		_mouseJoint = NULL;
	}
}


MyContactListener.h

#ifndef __MYCONTACTLISTENER_H__
#define __MYCONTACTLISTENER_H__

#include <vector>
#include <algorithm>
#include "Box2D/Box2D.h"

struct MyContact {
	b2Fixture* fixtureA;
	b2Fixture* fixtureB;
	bool operator==(const MyContact& other) const {
		return (fixtureA == other.fixtureA) && (fixtureB == other.fixtureB);
	}
};

class MyContactListener: public b2ContactListener {
public:
	std::vector<MyContact> _contacts;

	MyContactListener();
	~MyContactListener();

	virtual void BeginContact(b2Contact* contact);
	virtual void EndContact(b2Contact* contact);
	virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
	virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
};

#endif

MyContactListener.cpp

#include "MyContactListener.h"
#include "HelloWorldScene.h"

USING_NS_CC;

MyContactListener::MyContactListener(): _contacts() {}
MyContactListener::~MyContactListener() {}

void MyContactListener::BeginContact(b2Contact* contact) {
	MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
	_contacts.push_back(myContact);
}

void MyContactListener::EndContact(b2Contact* contact) {
	MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
	std::vector<MyContact>::iterator pos;
	pos = std::find(_contacts.begin(), _contacts.end(), myContact);
	if (pos != _contacts.end()) {
		_contacts.erase(pos);
	}
}

void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) {}
void MyContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) {}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值