Cocos2d C ++ Score系统

时间:2016-06-05 20:59:38

标签: c++ cocos2d-x

所以我正在开发这个游戏,我想实现一个分数系统。 这是我第一次使用Cocos2d。 我尝试了几件事,但并没有真正取得成功。

我希望如果对于从场景中删除的每个敌人,名称得分的int将增加1。

你们有什么建议吗?

#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
using namespace CocosDenshion;

USING_NS_CC;

#define BACKGROUND_MUSIC_SFX  "bee.mp3"
#define PEW_PEW_SFX           "splatter.mp3"

// These bit masks define the physics categories; monster + projectile with two values to specify no type or all types, I use this to see what objects are allowed to collide
enum class PhysicsCategory {
  None = 0,
  Monster = (1 << 0),    // 1
  Projectile = (1 << 1), // 2
  All = PhysicsCategory::Monster | PhysicsCategory::Projectile // 3
};

Scene* HelloWorld::createScene()
{
  // 'scene' is an autorelease object, turn psysics on
  auto scene = Scene::createWithPhysics();
  scene->getPhysicsWorld()->setGravity(Vec2(0,0));
  scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_NONE);

  // 'layer' is an autorelease object
  auto layer = HelloWorld::create();

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

  // return scene
  return scene;
}

// initialize instance
bool HelloWorld::init()
{
  // call the super class’s init method, if succeeds proceed HelloWorldScene‘s setup
  if ( !Layer::init() ) {
    return false;
  }
  // get window bounds using game Director singleton.
  auto origin = Director::getInstance()->getVisibleOrigin();
  auto winSize = Director::getInstance()->getVisibleSize();
  // create a DrawNode to draw a green rectangle that fills the screen
  auto background = DrawNode::create();
  background->drawSolidRect(origin, winSize, Color4F(0.0,0.6,0.0,0.7));
  this->addChild(background);
  // create the player sprite, position 10% from the left edge of the screen, centered vertically
  _player = Sprite::create("player.png");
  _player->setPosition(Vec2(winSize.width * 0.1, winSize.height * 0.5));
  this->addChild(_player);

  // seed the random number generator
  srand((unsigned int)time(nullptr));
  this->schedule(schedule_selector(HelloWorld::addMonster), 1.5);

  auto eventListener = EventListenerTouchOneByOne::create();
  eventListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
  this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(eventListener, _player);

  auto contactListener = EventListenerPhysicsContact::create();
  contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegan, this);
  this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(contactListener, this);

  SimpleAudioEngine::getInstance()->playBackgroundMusic(BACKGROUND_MUSIC_SFX, true);

  return true;
}


void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
  MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
  return;
#endif

  Director::getInstance()->end();

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

void HelloWorld::addMonster(float dt) {
  auto monster = Sprite::create("monster.png");

  //Create a PhysicsBody for the sprite, Physics bodies represent the object in Cocos2d physics simulation.
  auto monsterSize = monster->getContentSize();
  auto physicsBody = PhysicsBody::createBox(Size(monsterSize.width , monsterSize.height),
                                            PhysicsMaterial(0.1f, 1.0f, 0.0f));
  //Set the sprite to be dynamic. physics engine will not apply forces to the bear.
  physicsBody->setDynamic(true);
  // set the category, collision and contact test bit masks:
  physicsBody->setCategoryBitmask((int)PhysicsCategory::Monster);
  physicsBody->setCollisionBitmask((int)PhysicsCategory::None);
  physicsBody->setContactTestBitmask((int)PhysicsCategory::Projectile);

  monster->setPhysicsBody(physicsBody);

  // create a bear sprite and place it offscreen to the right, random y position
  auto monsterContentSize = monster->getContentSize();
  auto selfContentSize = this->getContentSize();
  int minY = monsterContentSize.height/2;
  int maxY = selfContentSize.height - monsterContentSize.height/2;
  int rangeY = maxY - minY;
  int randomY = (rand() % rangeY) + minY;

  monster->setPosition(Vec2(selfContentSize.width + monsterContentSize.width/2, randomY));
  this->addChild(monster);

  // random duration for bear, each bear will move the same distance across the screen, varying the duration results in bears with random speeds.
  int minDuration = 2.0;
  int maxDuration = 4.0;
  int rangeDuration = maxDuration - minDuration;
  int randomDuration = (rand() % rangeDuration) + minDuration;

  // move the bear across the screen.
  auto actionMove = MoveTo::create(randomDuration, Vec2(-monsterContentSize.width/2, randomY));
  auto actionRemove = RemoveSelf::create();
  monster->runAction(Sequence::create(actionMove,actionRemove, nullptr));
}

bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event) {
  // 1  - get the  _player object
  //auto node = unused_event->getCurrentTarget();

  // coordinate of the click within the scene’s coordinate system, calculate the offset of this point from the current position. vector math.
  Vec2 touchLocation = touch->getLocation();
  Vec2 offset = touchLocation - _player->getPosition();

  // If offset‘s x value is negative, the player tries to shoot backwards,return without firing.
  if (offset.x < 0) {
    return true;
  }

  // Create projectile, add to screen
  auto projectile = Sprite::create("projectile.png");
  projectile->setPosition(_player->getPosition());
  auto projectileSize = projectile->getContentSize();
  auto physicsBody = PhysicsBody::createCircle(projectileSize.width/2 );
  physicsBody->setDynamic(true); 
  physicsBody->setCategoryBitmask((int)PhysicsCategory::Projectile);
  physicsBody->setCollisionBitmask((int)PhysicsCategory::None);
  physicsBody->setContactTestBitmask((int)PhysicsCategory::Monster);
  projectile->setPhysicsBody(physicsBody);

  this->addChild(projectile);

  // call normalize() to convert the offset into a unit vector, which is a vector of length 1. Multiplying that by 1000 that points in the direction of the user’s tap.
  offset.normalize();
  auto shootAmount = offset * 1000;

  // Adding the vector to the projectile’s position gives the target position.
  auto realDest = shootAmount + projectile->getPosition();

  // move the projectile to the target position, remove after 5 sec.
  auto actionMove = MoveTo::create(5.0f, realDest);
  auto actionRemove = RemoveSelf::create();
  projectile->runAction(Sequence::create(actionMove,actionRemove, nullptr));

  SimpleAudioEngine::getInstance()->playEffect(PEW_PEW_SFX);

  return true;
}


// PhysicsContact passed to this method is collision, remove at the end
bool HelloWorld::onContactBegan(PhysicsContact &contact) {
  auto nodeA = contact.getShapeA()->getBody()->getNode();
  auto nodeB = contact.getShapeB()->getBody()->getNode();

  nodeA->removeFromParent();
  nodeB->removeFromParent();
  return true;
}

1 个答案:

答案 0 :(得分:0)

我不确定我是否完全理解你的问题,但似乎你想创建一个标签来显示当前的分数。

当然,您需要一个变量来跟踪您的分数。我们假设变量是一个整数,它被称为 m_score

然后,您需要为场景创建并添加标签。在 init()函数中添加:

m_scoreLabel = Label::createWithTTF(std::to_string(m_score), "fonts/Arial.ttf", 36);
this->addChild(m_scoreLabel);

您需要 m_scoreLabel 来保留对 Label 的引用,以便稍后您可以更改其显示文本。现在,每当您更改分数时,首先更新 m_score 的值,然后更新标签调用所显示的文本:

m_scoreLabel->setString(std::to_string(m_score));