#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();
}