box2d

#ifndef __MINIPOOL_B2SPRITE__
#define __MINIPOOL_B2SPRITE__


#define PTM_RATIO 32.0
#define BALL_RADIUS 8.0


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


class GameLayer;


enum{
kSpritePlayer,
kSpriteBall,
kSpriteCue,
kSpritePocket
};


USING_NS_CC;


class b2Sprite : public CCSprite{
public:
b2Sprite(GameLayer *game, int type);


CC_SYNTHESIZE(b2Body*, _body, Body);
CC_SYNTHESIZE(GameLayer*, _game, Game);
CC_SYNTHESIZE(int, _type, Type);


virtual void setSpritePosition(CCPoint position);
virtual void update(float dt);
virtual void hide(void);
virtual void reset(void);
virtual float mag();
};

#endif

#include "b2Sprite.h"
#include "GameLayer.h"


b2Sprite::b2Sprite(GameLayer *game, int type){
_game = game;
_type = type;
}


void b2Sprite::setSpritePosition(CCPoint position){
setPosition(position);


if(_body){
_body->SetTransform(b2Vec2(
                position.x / PTM_RATIO,
position.y / PTM_RATIO),
_body->GetAngle());
}
}


void b2Sprite::update(float dt){


if(_body && isVisible()){
setPositionX(_body->GetPosition().x * PTM_RATIO);
setPositionY(_body->GetPosition().y * PTM_RATIO);
setRotation(CC_RADIANS_TO_DEGREES(-1 * _body->GetAngle()));
}
}


void b2Sprite::hide(){
if(_body){
_body->SetLinearVelocity(b2Vec2_zero);
_body->SetAngularVelocity(0);
_body->SetTransform(b2Vec2_zero,0.0);
_body->SetAwake(false);
}
}


void b2Sprite::reset(){}


float b2Sprite::mag(){
if(_body){
return pow(_body->GetLinearVelocity().x, 2) + 
pow(_body->GetLinearVelocity().y,2);
}
return 0.0;
}


#ifndef __MINIPOOL_BALL_
#define __MINIPOOL_BALL_


#include "b2Sprite.h"


enum{
kColorYellow,
kColorRed,
kColorBlack,
kColorWhite
};


class Ball : public b2Sprite{
public:
CC_SYNTHESIZE(bool, _inPlay, InPlay);
~Ball();
Ball(GameLayer *game, int type, CCPoint position, int color);
static Ball* create(GameLayer *game, int type, CCPoint position, int color);
virtual void reset(void);
virtual void update(float dt);
private:
void initBall();
CCPoint _startPosition;


int _color;
};
#endif

#include "Ball.h"
#include "GameLayer.h"




Ball::~Ball(){


}


Ball::Ball(GameLayer *game, int type, CCPoint position, int color):b2Sprite(game,type){
_type = type;
_startPosition = position;
_color = color;
_inPlay = true;
}


Ball* Ball::create(GameLayer *game, int type, CCPoint position, int color){
Ball *sprite = new Ball(game, type, position, color);
if(sprite){
sprite->initBall();
sprite->autorelease();
return sprite;
}
CC_SAFE_DELETE(sprite);
return NULL;
}


void Ball::initBall(){
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;


_body = _game->getWorld()->CreateBody(&bodyDef);
_body->SetSleepingAllowed(true);
_body->SetLinearDamping(1.2);
_body->SetAngularDamping(0.8);


b2CircleShape circle;
circle.m_radius = BALL_RADIUS / PTM_RATIO;


b2FixtureDef fixtureDef;
fixtureDef.shape = &circle;
fixtureDef.density = 5;
fixtureDef.restitution = 0.7;


if(_type == kSpriteBall){
fixtureDef.filter.categoryBits = 0x0010;
}else if(_type == kSpritePlayer){
_body->SetBullet(true);
fixtureDef.filter.categoryBits = 0x0100;
}


switch(_color){
case kColorBlack:
this->initWithSpriteFrameName("ball_black.png");
break;
case kColorRed:
this->initWithSpriteFrameName("ball_red.png");
break;
case kColorYellow:
this->initWithSpriteFrameName("ball_yellow.png");
break;
case kColorWhite:
this->initWithSpriteFrameName("ball_white.png");
break;
}


_body->CreateFixture(&fixtureDef);
_body->SetUserData(this);


setSpritePosition(_startPosition);
}


void Ball::reset(){
if(_body){
_body->SetLinearVelocity(b2Vec2_zero);
_body->SetAngularVelocity(0);
_body->SetAwake(true);
}
setSpritePosition(_startPosition);
_inPlay = true;
setVisible(true);
}


void Ball::update(float dt){
if(_body && isVisible()){
setPositionX(_body->GetPosition().x * PTM_RATIO);
setPositionY(_body->GetPosition().y * PTM_RATIO);
}
}


#ifndef __MINIPOOL_CUE__
#define __MINIPOOL_CUE__


#include "b2Sprite.h"


class Cue : public b2Sprite{
public:
~Cue();
Cue(GameLayer *game);
static Cue* create(GameLayer *game);
private:
void initCue();
};




#endif


#include "Cue.h"
#include "GameLayer.h"


Cue::~Cue(){


}


Cue::Cue(GameLayer *game):b2Sprite(game, kSpriteCue){


}


Cue* Cue::create(GameLayer *game){
Cue *sprite = new Cue(game);
if(sprite){
sprite->initCue();
sprite->autorelease();
return sprite;
}
CC_SAFE_DELETE(sprite);
return NULL;
}


void Cue::initCue(){


b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;


_body = _game->getWorld()->CreateBody(&bodyDef);
_body->SetSleepingAllowed(true);
_body->SetLinearDamping(8);
_body->SetAngularDamping(5);


b2PolygonShape box;
box.SetAsBox(BALL_RADIUS * 21 / PTM_RATIO, BALL_RADIUS * 0.2 / PTM_RATIO);


b2FixtureDef fixtureDef;
fixtureDef.shape = &box;
fixtureDef.filter.maskBits = 0x0100;
fixtureDef.density = 10;
fixtureDef.restitution = 1;
_body->CreateFixture(&fixtureDef);
_body->SetUserData(this);


this->initWithSpriteFrameName("cue.png");


}


#ifndef __MINIPOLL_COLLISIONLISTENER__
#define __MINIPOLL_COLLISIONLISTENER__


#include "Box2D/Box2D.h"
#include "Ball.h"
#include "Cue.h"


class CollisionListener : public b2ContactListener
{
public:
virtual void BeginContact(b2Contact* contact);
virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
};




#endif



#include "CollisionListener.h"
#include "GameLayer.h"
//#include ""


void CollisionListener::BeginContact(b2Contact* contact){
b2Body *bodyA = contact->GetFixtureA()->GetBody();
b2Body *bodyB = contact->GetFixtureB()->GetBody();


b2Sprite *spriteA = (b2Sprite *)bodyA->GetUserData();
b2Sprite *spriteB = (b2Sprite *)bodyB->GetUserData();


if(spriteA && spriteB){
if(spriteA->getType() == kSpritePocket){
spriteB->setVisible(false);
}else if(spriteB->getType() == kSpritePocket){
spriteA->setVisible(false);
}else if(spriteA->getType() == kSpriteBall && 
spriteB->getType() == kSpriteBall){
if(spriteA->mag() > 10 || spriteB->mag() > 10){


}
}else if((spriteA->getType() == kSpriteBall && 
spriteB->getType() == kSpritePlayer) ||
(spriteB->getType() == kSpriteBall && 
spriteA->getType() == kSpritePlayer)){
            if(spriteA->mag() > 10 || spriteB->mag() > 10){


}
}
}
}


void CollisionListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold){
b2Body *bodyA = contact->GetFixtureA()->GetBody();
b2Body *bodyB = contact->GetFixtureB()->GetBody();


b2Sprite *spriteA = (b2Sprite *)bodyA->GetUserData();
b2Sprite *spriteB = (b2Sprite *)bodyB->GetUserData();


    if (spriteA && spriteB) {
if (spriteA->getType() == kSpriteCue && spriteA->mag() > 2) {
if (spriteB->getType() == kSpritePlayer && spriteA->isVisible()) {
//SimpleAudioEngine::sharedEngine()->playEffect("hit.wav");
spriteA->setVisible(false);
spriteB->getGame()->setCanShoot(false);
}
} else if (spriteB->getType() == kSpriteCue && spriteA->mag() > 2) {
if (spriteA->getType() == kSpritePlayer && spriteB->isVisible()) {
//SimpleAudioEngine::sharedEngine()->playEffect("hit.wav");
spriteB->setVisible(false);
spriteA->getGame()->setCanShoot(false);
}

    }
}


#ifndef __GAME_LAYER_H__
#define __GAME_LAYER_H__


#include "cocos2d.h"


#include "Box2D/Box2D.h"
#include "Ball.h"
#include "Cue.h"
#include "LineContainer.h"
#include "GLES_Render.h"


enum{
kBackground,
kMiddleground,
kForeground
};


enum{
kGameIntro,
kGamePlay,
kGameOver
};


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


CC_SYNTHESIZE(b2World*, _world,World);
CC_SYNTHESIZE(bool,_canShoot,CanShoot);


    // there's no 'id' in cpp, so we recommand to return the exactly class pointer
    static cocos2d::CCScene* scene();
    
void initPhysics();


virtual void draw();
virtual void ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);




    // implement the "static node()" method manually
    CREATE_FUNC(GameLayer);


void update(float dt);
void ticktock(float dt);
private:
GLESDebugDraw *m_debugDraw;
b2ContactListener *_collisionListener;


CCTouch *_touch;
CCArray *_balls;
CCArray *_pockets;
CCSpriteBatchNode *_gameBatchNode;
CCSprite *_intro;
CCSprite *_gameOver;
CCLabelBMFont *_timer;


LineContainer *_lineContainer;


CCPoint _cueStartPoint;
CCSize _screenSize;
bool _running;
bool _usingCue;


float _pullBack;
float _cueAngle;
int _gameState;


int _ballsInPlay;
int _time;



Ball *_player;
Cue *_cue;


void placeCue(CCPoint position);
void resetGame(void);
};


#endif  // __HELLOWORLD_SCENE_H__


#include "GameLayer.h"
#include "CollisionListener.h"


#define SHOT_POWER 6.0


using namespace cocos2d;


GameLayer::GameLayer() {
_screenSize = CCDirector::sharedDirector()->getWinSize();


CCSprite * bg = CCSprite::create("bg.png");
bg->setPosition(ccp(_screenSize.width * 0.5f, _screenSize.height * 0.5f));
this->addChild(bg);


CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("sprite_sheet.plist");
_gameBatchNode = CCSpriteBatchNode::create("sprite_sheet.png", 50);
this->addChild(_gameBatchNode, kMiddleground);


// init physics
this->initPhysics();


setTouchEnabled( true );
scheduleUpdate();


_usingCue = false;
_running = true;
_canShoot = true;
_gameState = kGameIntro;
_time = 0;
_ballsInPlay = 15;


_lineContainer = LineContainer::create();
this->addChild(_lineContainer);


_intro = CCSprite::createWithSpriteFrameName("logo.png");
_intro->setPosition(ccp(_screenSize.width * 0.5f, _screenSize.height * 0.55f));
_gameBatchNode->addChild(_intro, kForeground);


_gameOver = CCSprite::createWithSpriteFrameName("gameover.png");
_gameOver->setPosition(ccp(_screenSize.width * 0.5f, _screenSize.height * 0.55f));
_gameOver->setVisible(false);
_gameBatchNode->addChild(_gameOver, kForeground);


_timer = CCLabelBMFont::create("0", "font.fnt", _screenSize.width * 0.5f);
_timer->setPosition(ccp(_screenSize.width * 0.5f, _screenSize.height * 0.94f));
_timer->setVisible(false);
this->addChild(_timer, kForeground);


this->schedule(schedule_selector(GameLayer::ticktock), 1.5f); 
}


GameLayer::~GameLayer() {
delete _world;
_world = NULL;


    delete m_debugDraw;
delete _collisionListener;


CC_SAFE_RELEASE(_balls);
CC_SAFE_RELEASE(_pockets);
}




CCScene* GameLayer::scene()
{
    CCScene * scene = NULL;
    do 
    {
        // 'scene' is an autorelease object
        scene = CCScene::create();
        CC_BREAK_IF(! scene);


        // 'layer' is an autorelease object
        GameLayer *layer = GameLayer::create();
        CC_BREAK_IF(! layer);


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


    // return the scene
    return scene;
}


// on "init" you need to initialize your instance
bool GameLayer::init()
{
    bool bRet = false;
    do 
    {
        //
        // super init first
        //


        CC_BREAK_IF(! CCLayer::init());


        //
        // add your codes below...
        //
setTouchEnabled( true );
       
        bRet = true;
    } while (0);


    return bRet;
}






void GameLayer::initPhysics(){
b2Vec2 gravity;
gravity.Set(0.0f,0.0f);
_world = new b2World(gravity);


_world->SetAllowSleeping(true);
_world->SetContinuousPhysics(true);
_collisionListener = new CollisionListener();
_world->SetContactListener(_collisionListener);


m_debugDraw = new GLESDebugDraw(PTM_RATIO);
_world->SetDebugDraw(m_debugDraw);


uint32 flags = 0;
flags += b2Draw::e_shapeBit;
m_debugDraw->SetFlags(flags);


b2FixtureDef fixtureDef;
b2BodyDef bodyDef;


_pockets = CCArray::createWithCapacity(6);
_pockets->retain();


b2Body *pocket;
b2Sprite *pocketData;
b2CircleShape circle;


float startX = _screenSize.width * 0.07;
float startY = _screenSize.height * 0.92f;
for(int i = 0; i < 6; ++i){
bodyDef.type = b2_staticBody;
if(i < 3){
bodyDef.position.Set(
  startX / PTM_RATIO,
  (startY - i * (_screenSize.height * 0.84f * 0.5f)) / PTM_RATIO);
}else{
bodyDef.position.Set(
(startX + _screenSize.width * 0.85f) / PTM_RATIO,
(startY - (i - 3) * (_screenSize.height * 0.84f * 0.5f)) / PTM_RATIO);
}
pocket = _world->CreateBody(&bodyDef);
fixtureDef.isSensor = true;
circle.m_radius = (float)(1.5 * BALL_RADIUS) / PTM_RATIO;
fixtureDef.shape = &circle;


pocket->CreateFixture(&fixtureDef);
pocketData = new b2Sprite(this, kSpritePocket);
pocket->SetUserData(pocketData);
_pockets->addObject(pocketData);
}


b2BodyDef tableBodyDef;
tableBodyDef.position.Set(0, 0);
b2Body *tableBody = _world->CreateBody(&tableBodyDef);


b2EdgeShape tableBox;
//bottom
tableBox.Set(b2Vec2(_screenSize.width * 0.14f / PTM_RATIO, _screenSize.height * 0.09f / PTM_RATIO),
         b2Vec2(_screenSize.width * 0.86f / PTM_RATIO, _screenSize.height * 0.09f / PTM_RATIO));
tableBody->CreateFixture(&tableBox, 0);
    // top
    tableBox.Set(b2Vec2(_screenSize.width * 0.14f/PTM_RATIO, _screenSize.height * 0.91f/PTM_RATIO),
                  b2Vec2(_screenSize.width * 0.86f/PTM_RATIO, _screenSize.height * 0.91f/PTM_RATIO));
    tableBody->CreateFixture(&tableBox,0);
//left
tableBox.Set(b2Vec2(_screenSize.width * 0.09f / PTM_RATIO, _screenSize.height * 0.12f / PTM_RATIO),
         b2Vec2(_screenSize.width * 0.09f / PTM_RATIO, _screenSize.height * 0.46f / PTM_RATIO));
tableBody->CreateFixture(&tableBox, 0);


tableBox.Set(b2Vec2(_screenSize.width * 0.91f / PTM_RATIO, _screenSize.height * 0.12f / PTM_RATIO),
         b2Vec2(_screenSize.width * 0.91f / PTM_RATIO, _screenSize.height * 0.46f / PTM_RATIO));
tableBody->CreateFixture(&tableBox, 0);


//right
tableBox.Set(b2Vec2(_screenSize.width * 0.09f/PTM_RATIO, _screenSize.height * 0.54f/PTM_RATIO),
         b2Vec2(_screenSize.width * 0.09f/PTM_RATIO, _screenSize.height * 0.88f/PTM_RATIO));
tableBody->CreateFixture(&tableBox,0);




tableBox.Set(b2Vec2(_screenSize.width * 0.91f/PTM_RATIO, _screenSize.height * 0.54f/PTM_RATIO),
         b2Vec2(_screenSize.width * 0.91f/PTM_RATIO, _screenSize.height * 0.88f/PTM_RATIO));
tableBody->CreateFixture(&tableBox, 0);


_balls = CCArray::createWithCapacity(15);
_balls->retain();


Ball *ball;
int col = 5;
int colCnt = 0;
startX = (_screenSize.width - 8 * BALL_RADIUS) * 0.5f;
startY = _screenSize.height * 0.82f;
float newX;
float newY;
int color;
for (int i = 0; i < 15; i++) {
if (i == 10) {
color = kColorBlack;
} else if (i % 2 == 0) {
color = kColorYellow;
} else {
color = kColorRed;
}
if (colCnt < col) {
newX = startX + colCnt * 2 * BALL_RADIUS;
colCnt++;
} else {
startX += BALL_RADIUS;
startY -= 2 * BALL_RADIUS;
newX = startX;
col--;
colCnt = 1;
}
newY = startY;
ball = Ball::create(this, kSpriteBall, ccp(newX, newY), color);
_gameBatchNode->addChild(ball, kMiddleground);
_balls->addObject(ball);
}


//add cue ball
_player = Ball::create(this, kSpritePlayer, ccp(_screenSize.width * 0.5f, _screenSize.height * 0.3f), kColorWhite);
_gameBatchNode->addChild(_player, kMiddleground);


_cue = Cue::create(this);


_cue->setSpritePosition(ccp(_screenSize.width * 0.2f, _screenSize.height * 0.3f));
_cue->getBody()->SetTransform(_cue->getBody()->GetPosition(), M_PI*0.5);
_gameBatchNode->addChild(_cue, kForeground);
}


void GameLayer::draw(){
CCLayer::draw();


ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position);
kmGLPushMatrix();
_world->DrawDebugData();
kmGLPopMatrix();
}




void GameLayer::update(float dt) {
if(!_running) return;
if(_gameState == kGameOver) return;


_world->Step(dt, 10, 10);


int count = _balls->count();
Ball *ball;


for(int i = 0; i < count; ++i){
ball = (Ball *)_balls->objectAtIndex(i);
if(!ball->isVisible() && ball->getInPlay()){
ball->setInPlay(false);
ball->hide();
_ballsInPlay--;


if(_ballsInPlay == 0){
_gameState = kGameOver;
_gameOver->setVisible(true);
}
}else{
ball->update(dt);
}
}


if(!_cue->isVisible()){
_cue->hide();
}else{
_cue->update(dt);
}


if(!_player->isVisible()){
_player->reset();
_player->setVisible(true);


}
_player->update(dt);


if(_player->mag() < 0.5f && !_canShoot){
_player->getBody()->SetLinearVelocity(b2Vec2_zero);
_player->getBody()->SetAngularVelocity(0);
_canShoot = true;
}


if (_player->getPositionX() < 0 || _player->getPositionX() > _screenSize.width
|| _player->getPositionY() < 0 || _player->getPositionY() > _screenSize.height) {
_player->setVisible(false);
}
}




void GameLayer::ticktock(float dt){
if (_gameState == kGamePlay) {
_time++;
char score[100] = {0};
sprintf(score, "%i", _time);
_timer->setString(score);
}
}


void GameLayer::ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event){
if(!_running) return;


if(_gameState == kGameOver){
if(_gameOver->isVisible()) _gameOver->setVisible(false);
resetGame();
return;
}


if(!_canShoot) return;


CCTouch *touch = (CCTouch*) touches->anyObject();
if(touch){
CCPoint tap = touch->getLocation();


CCPoint playerPos = _player->getPosition();
float diffx = tap.x - playerPos.x;
float diffy = tap.y - playerPos.y;
float diff = pow(diffx, 2) + pow(diffy, 2);
if(diff < pow(BALL_RADIUS * 4, 2)){
if(_gameState != kGamePlay){
_gameState = kGamePlay;
if(_intro->isVisible()) _intro->setVisible(false);
_timer->setVisible(true);
}


if(diff > pow(BALL_RADIUS * 2, 2)){
float angle = atan2(diffy,diffx);
_cueStartPoint = ccp(playerPos.x + BALL_RADIUS * 0.8f * cos(angle),
playerPos.y + BALL_RADIUS * 0.8f * sin(angle));
}else{
_cueStartPoint = playerPos;
}
_lineContainer->setBallPoint(_cueStartPoint);


_cue->getBody()->SetLinearVelocity(b2Vec2(0, 0));
_cue->getBody()->SetAngularVelocity(0.0);
_touch = touch;
}
}
 
}
void GameLayer::ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event){
if(!_running) return;


CCTouch *touch = (CCTouch*)touches->anyObject();
if(touch && touch == _touch){
CCPoint tap = touch->getLocation();
float diffx = tap.x - _player->getPositionX();
float diffy = tap.y - _player->getPositionY();


if(pow(diffx, 2) + pow(diffy, 2) > pow(BALL_RADIUS * 2, 2)){
_usingCue = true;
_cue->setVisible(true);
_lineContainer->setDrawing(true);
placeCue(tap);
_cue->getBody()->SetAwake(true);
}else{
_usingCue = false;
_lineContainer->setDrawing(false);
_cue->setVisible(false);
_cue->getBody()->SetAwake(false);
}
}
}
void GameLayer::ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event){
if(_usingCue && _touch){
b2Body *cueBody = _cue->getBody();
float angle = cueBody->GetAngle();


cueBody->ApplyLinearImpulse(b2Vec2(_pullBack * cos(angle) * SHOT_POWER,
                                _pullBack * sin(angle) * SHOT_POWER),
cueBody->GetWorldCenter());
}
_usingCue = false;
_touch = NULL;
_lineContainer->setDrawing(false);
}
void GameLayer::placeCue(CCPoint position){
float diffx = _cueStartPoint.x - position.x;
float diffy = _cueStartPoint.y - position.y;


float angle = atan2(diffy, diffx);
float distance = sqrt(pow (diffx, 2) + pow(diffy, 2));


_pullBack = distance * 0.5f;
CCPoint cuePosition = ccp(
_cueStartPoint.x - (BALL_RADIUS * 21 + _pullBack) * cos(angle),
_cueStartPoint.y - (BALL_RADIUS * 21 + _pullBack) * sin(angle));


_cue->getBody()->SetTransform(b2Vec2(cuePosition.x/PTM_RATIO, cuePosition.y/PTM_RATIO), angle);
_lineContainer->setCuePoint(ccp(
_cueStartPoint.x - ( _pullBack) * cos(angle),
_cueStartPoint.y - ( _pullBack) * sin(angle)));
}
void GameLayer::resetGame(){
_gameState = kGameIntro;


_player->reset();
_cue->setVisible(false);


int count = _balls->count();
Ball * ball;
for (int i = 0; i < count; i++) {
ball = (Ball *) _balls->objectAtIndex(i);
ball->reset();
}


_time = 0;
_ballsInPlay = 15;
_usingCue = false;
_running = true;
_canShoot = true;
_timer->setVisible(false);


char score[100] = {0};
sprintf(score, "%i", _time);
_timer->setString(score);
}


#ifndef __LINECONTAINER_H__
#define __LINECONTAINER_H__


#include "cocos2d.h"


USING_NS_CC;


class LineContainer : public CCNode{
public:
CC_SYNTHESIZE(CCPoint,_ballPoint,BallPoint);
CC_SYNTHESIZE(CCPoint,_cuePoint,CuePoint);
CC_SYNTHESIZE(bool,_drawing,Drawing);


LineContainer();
//static LineContainer *create();
CREATE_FUNC(LineContainer);
virtual void draw();


private:
int _dash;
int _dashSpace;
CCSize _screenSize;
};




#endif


#include "LineContainer.h"


USING_NS_CC;


LineContainer::LineContainer(){
_dash = 5;
_dashSpace = 5;
_screenSize = CCDirector::sharedDirector()->getWinSize();
_drawing = false;
ccPointSize(0.2f);
}


//LineContainer* LineContainer::create(){
// LineContainer *node = new LineContainer();
// if(node){
// node->autorelease();
// return node;
// }
// CC_SAFE_DELETE(node);
// return NULL;
//}


void LineContainer::draw(){
if(_drawing){
ccDrawColor4F(1.0,1.0,1.0,1.0);


float length = ccpDistance(_ballPoint,_cuePoint);
int segments = length / (_dash + _dashSpace);


float t = 0.0f;
float x_;
float y_;


for (int i = 0; i < segments + 1; ++i){
x_ = _cuePoint.x + t * (_ballPoint.x - _cuePoint.x);
y_ = _cuePoint.y + t * (_ballPoint.y - _cuePoint.y);


ccDrawCircle(ccp(x_,y_),3,M_PI,4,false);


t += (float)1 / segments;
}
}
}


/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/


#ifndef RENDER_H
#define RENDER_H


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


struct b2AABB;


// This class implements debug drawing callbacks that are invoked
// inside b2World::Step.
class GLESDebugDraw : public b2Draw
{
    float32 mRatio;
    cocos2d::CCGLProgram* mShaderProgram;
    GLint        mColorLocation;


    void initShader( void );
public:
    GLESDebugDraw();


    GLESDebugDraw( float32 ratio );


    virtual void DrawPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color);


    virtual void DrawSolidPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color);


    virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);


    virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);


    virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);


    virtual void DrawTransform(const b2Transform& xf);


    virtual void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color);


    virtual void DrawString(int x, int y, const char* string, ...); 


    virtual void DrawAABB(b2AABB* aabb, const b2Color& color);
};




#endif


/*
 * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
 *
 * iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 * 1. The origin of this software must not be misrepresented; you must not
 * claim that you wrote the original software. If you use this software
 * in a product, an acknowledgment in the product documentation would be
 * appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */


#include "GLES_Render.h"
#include "cocos2d.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>


USING_NS_CC;


GLESDebugDraw::GLESDebugDraw()
    : mRatio( 1.0f )
{
    this->initShader();
}


GLESDebugDraw::GLESDebugDraw( float32 ratio )
    : mRatio( ratio )
{
    this->initShader();
}


void GLESDebugDraw::initShader( void )
{
    mShaderProgram = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_Position_uColor);


    mColorLocation = glGetUniformLocation( mShaderProgram->getProgram(), "u_color");
}


void GLESDebugDraw::DrawPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
    mShaderProgram->use();
    //mShaderProgram->setUniformForModelViewProjectionMatrix();


    b2Vec2* vertices = new b2Vec2[vertexCount];
    for( int i=0;i<vertexCount;i++) 
    {
        vertices[i] = old_vertices[i];
        vertices[i] *= mRatio;
    }


    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);


    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);


    CC_INCREMENT_GL_DRAWS(1);


    CHECK_GL_ERROR_DEBUG();


    delete[] vertices;
}


void GLESDebugDraw::DrawSolidPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
    mShaderProgram->use();
    //mShaderProgram->setUniformForModelViewProjectionMatrix();


    b2Vec2* vertices = new b2Vec2[vertexCount];
    for( int i=0;i<vertexCount;i++) {
        vertices[i] = old_vertices[i];
        vertices[i] *= mRatio;
    }
    
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r*0.5f, color.g*0.5f, color.b*0.5f, 0.5f);


    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices);


    glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);


    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);


    CC_INCREMENT_GL_DRAWS(2);


    CHECK_GL_ERROR_DEBUG();


    delete[] vertices;
}


void GLESDebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
{
    mShaderProgram->use();
    //mShaderProgram->setUniformForModelViewProjectionMatrix();


    const float32 k_segments = 16.0f;
    int vertexCount=16;
    const float32 k_increment = 2.0f * b2_pi / k_segments;
    float32 theta = 0.0f;
    
    GLfloat*    glVertices = new GLfloat[vertexCount*2];
    for (int i = 0; i < k_segments; ++i)
    {
        b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
        glVertices[i*2]=v.x * mRatio;
        glVertices[i*2+1]=v.y * mRatio;
        theta += k_increment;
    }
    
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);


    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);


    CC_INCREMENT_GL_DRAWS(1);


    CHECK_GL_ERROR_DEBUG();


    delete[] glVertices;
}


void GLESDebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
{
    mShaderProgram->use();
    //mShaderProgram->setUniformForModelViewProjectionMatrix();


    const float32 k_segments = 16.0f;
    int vertexCount=16;
    const float32 k_increment = 2.0f * b2_pi / k_segments;
    float32 theta = 0.0f;
    
    GLfloat*    glVertices = new GLfloat[vertexCount*2];
    for (int i = 0; i < k_segments; ++i)
    {
        b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
        glVertices[i*2]=v.x * mRatio;
        glVertices[i*2+1]=v.y * mRatio;
        theta += k_increment;
    }
    
    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r*0.5f, color.g*0.5f, color.b*0.5f, 0.5f);
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);
    glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);




    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);


    // Draw the axis line
    DrawSegment(center,center+radius*axis,color);


    CC_INCREMENT_GL_DRAWS(2);


    CHECK_GL_ERROR_DEBUG();


    delete[] glVertices;
}


void GLESDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
    mShaderProgram->use();
    //mShaderProgram->setUniformForModelViewProjectionMatrix();


    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);


    GLfloat    glVertices[] = 
    {
        p1.x * mRatio, p1.y * mRatio,
        p2.x * mRatio, p2.y * mRatio
    };
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);


    glDrawArrays(GL_LINES, 0, 2);


    CC_INCREMENT_GL_DRAWS(1);


    CHECK_GL_ERROR_DEBUG();
}


void GLESDebugDraw::DrawTransform(const b2Transform& xf)
{
    b2Vec2 p1 = xf.p, p2;
    const float32 k_axisScale = 0.4f;
    p2 = p1 + k_axisScale * xf.q.GetXAxis();
    DrawSegment(p1, p2, b2Color(1,0,0));


    p2 = p1 + k_axisScale * xf.q.GetYAxis();
    DrawSegment(p1,p2,b2Color(0,1,0));
}


void GLESDebugDraw::DrawPoint(const b2Vec2& p, float32 size, const b2Color& color)
{
    mShaderProgram->use();
    //mShaderProgram->setUniformForModelViewProjectionMatrix();


    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);


    //    glPointSize(size);


    GLfloat                glVertices[] = {
        p.x * mRatio, p.y * mRatio
    };


    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);


    glDrawArrays(GL_POINTS, 0, 1);
    //    glPointSize(1.0f);


    CC_INCREMENT_GL_DRAWS(1);


    CHECK_GL_ERROR_DEBUG();
}


void GLESDebugDraw::DrawString(int x, int y, const char *string, ...)
{
//    NSLog(@"DrawString: unsupported: %s", string);
    //printf(string);
    /* Unsupported as yet. Could replace with bitmap font renderer at a later date */
}


void GLESDebugDraw::DrawAABB(b2AABB* aabb, const b2Color& color)
{
    mShaderProgram->use();
    //mShaderProgram->setUniformForModelViewProjectionMatrix();


    mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1);


    GLfloat                glVertices[] = {
        aabb->lowerBound.x * mRatio, aabb->lowerBound.y * mRatio,
        aabb->upperBound.x * mRatio, aabb->lowerBound.y * mRatio,
        aabb->upperBound.x * mRatio, aabb->upperBound.y * mRatio,
        aabb->lowerBound.x * mRatio, aabb->upperBound.y * mRatio
    };


    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);
    glDrawArrays(GL_LINE_LOOP, 0, 8);


    CC_INCREMENT_GL_DRAWS(1);


    CHECK_GL_ERROR_DEBUG();
    
}








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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值