《一个都不能死》 游戏开发 (物理引擎)
//创建物理场景
auto scene = Scene::createWithPhysics();
//设置重力
scene->getPhysicsWorld()->setGravity(Vec2(0,-1000));
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
//auto scene = Scene::create();
auto scene = Scene::createWithPhysics();
//scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
scene->getPhysicsWorld()->setGravity(Vec2(0,-1000));
// 'layer' is an autorelease object
auto 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()
{
//////////////////////////////
// 1. super init first
if (!LayerColor::initWithColor(Color4B(255, 255, 255, 255)))
{
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
//gcs.pushBack(GameController::create(this, 30));
gcs.insert(0, GameController::create(this, 30));
//gcs.insert(0, GameController::create(this, 250));
scheduleUpdate();
//创建碰撞检测监听
auto listener = EventListenerPhysicsContact::create();
listener->onContactBegin = [this](PhysicsContact &contact){
this->unscheduleUpdate();
Director::getInstance()->replaceScene(GameOver::createScene());
return true;
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
//添加点击监听
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = [this](Touch * t, Event *e){
for (auto it = gcs.begin(); it != gcs.end(); it++){
if ((*it)->hitTestPoint(t->getLocation())){
(*it)->onUserTouch();
break;
}
}
return false;
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, this);
return true;
}
void HelloWorld::update(float dt)
{
for (auto it = gcs.begin(); it != gcs.end(); it++)
{
(*it)->onUpdate(dt);
}
}
创建一个物理世界边缘(一般是窗口大小),
class Edge:public Node{
public:
virtual bool init();
CREATE_FUNC(Edge);
};
bool Edge::init(){
Node::init();
Size visibleSize = Director::getInstance()->getVisibleSize();
//创建一个物理世界边缘
setPhysicsBody(PhysicsBody::createEdgeBox(visibleSize));
setContentSize(visibleSize);
return true;
}
创建人物(刚体)
class Hero :public Sprite{
public:
virtual bool init();
CREATE_FUNC(Hero);
};
bool Hero::init(){
Sprite::init();
Size s = Size(44, 52);
runAction(RepeatForever::create(FlashTool::readJsonSpriteSheet("Hero.json", 0.2f)));
setPhysicsBody(PhysicsBody::createBox(s));
setContentSize(s);
//被撞击后不旋转
getPhysicsBody()->setRotationEnable(false);
//开启碰撞检测
getPhysicsBody()->setContactTestBitmask(1);
//getPhysicsBody()->setCategoryBitmask(1);
//getPhysicsBody()->setCollisionBitmask(1);
return true;
}
创建阻挡物
class Block :public Sprite{
public:
virtual bool init();
//实现向左移动 超出后删除
virtual void update(float dt);
CREATE_FUNC(Block);
};
bool Block::init(){
Sprite::init();
Size s = Size((rand() % 20) + 5, (rand()%30) + 10);
Size visibleSize = Director::getInstance()->getVisibleSize();
setPhysicsBody(PhysicsBody::createBox(s));
setTextureRect(Rect(0, 0, s.width, s.height));
setColor(Color3B(0,0,0));
setContentSize(s);
setPositionX(visibleSize.width);
scheduleUpdate();
//设置静态,不会因为人物卡住 持续运动
getPhysicsBody()->setDynamic(false);
//设置碰撞检测
getPhysicsBody()->setContactTestBitmask(1);
return true;
}
void Block::update(float dt)
{
this->setPositionX(getPositionX() - 3);
if (getPositionX() < 0){
unscheduleUpdate();
removeFromParent();
}
}
//创建控制器
class GameController :public Ref{
private:
Layer *_layer;
float _positionY;
Size visibleSize;
int currentFrameIndex;
int nextFrameCount;
Edge *edge;
Hero *hero;
private:
void resetFrames();
void addBlock();
public:
virtual bool init(Layer *layer,float positionY);
//每过一段时间添加一个障碍物
void onUpdate(float dt);
//是否包含点 用于判断用户点击的位置是否在edgebody中
bool hitTestPoint(Vec2 point);
//用户点击后给英雄一个向上的冲力。
void onUserTouch();
static GameController * create(Layer *layer, float position);
};
GameController * GameController::create(Layer *layer, float position)
{
auto _ins = new GameController();
_ins->init(layer, position);
_ins->autorelease();
return _ins;
}
bool GameController::init(Layer *layer, float positionY)
{
_layer = layer;
_positionY = positionY;
visibleSize = Director::getInstance()->getVisibleSize();
//add edge
edge = Edge::create();
edge->setPosition(visibleSize.width / 2, visibleSize.height / 2 + positionY);
edge->setContentSize(visibleSize);
layer->addChild(edge);
//add ground
auto ground = Sprite::create();
ground->setColor(Color3B(0, 0, 0));
ground->setTextureRect(Rect(0, 0, visibleSize.width, 3));
ground->setPosition(visibleSize.width/2, 1.5 + positionY);
layer->addChild(ground);
//add hero
hero = Hero::create();
hero->setPosition(50, hero->getContentSize().height/2 + positionY);
layer->addChild(hero);
resetFrames();
return true;
}
void GameController::resetFrames()
{
currentFrameIndex = 0;
nextFrameCount = (rand() % 120) + 100;
}
void GameController::addBlock()
{
auto b = Block::create();
_layer->addChild(b);
b->setPositionY(b->getContentSize().height / 2 + _positionY);
}
void GameController::onUpdate(float dt)
{
currentFrameIndex++;
if (currentFrameIndex >= nextFrameCount){
resetFrames();
addBlock();
}
}
bool GameController::hitTestPoint(Vec2 point)
{
return edge->getBoundingBox().containsPoint(point);
}
void GameController::onUserTouch()
{
hero->getPhysicsBody()->setVelocity(Vec2(0, 400));
}