1.先要为飞机创建触摸移动事件
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchMoved = CC_CALLBACK_2(SecondScene::onTouchMoved, this);
listener->onTouchBegan = CC_CALLBACK_2(SecondScene::onTouchBegin, this);
listener->onTouchEnded = CC_CALLBACK_2(SecondScene::onTouchEnd, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
this->addChild(primesprite,1);
void SecondScene::onTouchMoved(Touch* touch, Event* event) {
Rect ballRect = primesprite->getBoundingBox();
//获取精灵的区域
Vec2 beginPoint = touch->getLocation();
//获取触摸的开始位置
if (ballRect.containsPoint(beginPoint)) {
Point endPoint = touch->getPreviousLocation();
//获取触摸的结束位置
Point offSet = beginPoint - endPoint;
//计算出两个位置的差
Point newPosition = primesprite->getPosition() + offSet;
//计算出精灵现在应该在的位置
primesprite->setPosition(newPosition);
//把精灵的位置设置到它应该在的位置
}
}
2.创建物理世界
Scene* SecondScene::createScene()
{
Scene* scene = Scene::createWithPhysics();
SecondScene* layer = SecondScene::create();
scene->addChild(layer);
return scene;
}
3.创建刚体并与精灵结合
//创建刚体
auto playphysicsbody = PhysicsBody::createBox(visibleSize);
playphysicsbody->setGravityEnable(false);//不受重力影响
playphysicsbody->setContactTestBitmask(0xFFFFFFFF);
//
primesprite->addComponent(playphysicsbody);
1.当一个身体的CategoryBitmask并与另一主体的ContactTestBitmask其结果不等于零时,接触事件将被发出,相反接触的事件将不被发送。在默认情况下,CategoryBitmask值为0xFFFFFFFF,ContactTestBitmask值是00000000
4.创建物理碰撞事件
auto contactlistener = EventListenerPhysicsContact::create();
contactlistener->onContactBegin = CC_CALLBACK_1(SecondScene::onContactBegin, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactlistener,this);
bool SecondScene::onContactBegin(PhysicsContact& contact)
{
auto nodeA = contact.getShapeA()->getBody()->getNode();//两个碰撞刚体相对应的节点之A
auto nodeB = contact.getShapeB()->getBody()->getNode();
//两个碰撞刚体相对应的节点之B
if (nodeA&&nodeB)
{
//当节点为敌人和子弹时,则移除子弹和敌人
if (nodeA->getName() == "enemy"&&nodeB->getName() == "bullet")
{
this->removeChild(nodeA);
this->removeChild(nodeB);
grade++;
gradeLabel->setString("分数:" + std::to_string(grade*100));
}
else if (nodeA->getName() == "bullet" && nodeB->getName() == "enemy") {
this->removeChild(nodeA);
this->removeChild(nodeB);
grade++;
gradeLabel->setString("分数 : " + std::to_string(grade * 100));
}
//当为飞机和敌人时,场景跳转游戏结束
else if (nodeA->getName() == "play" && nodeB->getName() == "enemy") {
auto gameOver = HelloWorld::create();
/*gameOver->setGrade(gradeLabel->getString());
Director::getInstance()->replaceScene(gameOver);*/
}
else if (nodeA->getName() == "enemy" && nodeB->getName() == "play") {
auto gameOver = HelloWorld::create();
/*gameOver->setGrade(gradeLabel->getString());
Director::getInstance()->replaceScene(gameOver);*/
}
}
return false;
}
5.最后设置子弹和敌机的轨迹即可,
很明显子弹的x坐标与飞机一样,而敌机从屏幕最上方下落,x用rand()函数即可,其中任要为子弹和敌机与刚体结合。
全代码:
SecondScene.h
#ifndef __SecendScene_H__
#define __SecendScene_H__
#include "cocos2d.h"
USING_NS_CC;
class SecondScene : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();
cocos2d::Size visibleSize;
Vec2 origin;
Sprite* sprite;
Sprite* sprite1;
Sprite* primesprite;
int grade = 0;
LabelTTF* gradeLabel;//分数板
virtual bool init();
bool onContactBegin(PhysicsContact & contact);
void update(float delta);
void creatEnemySpriteAction(float delta);
void playFireAction(float delta);
void imgrotate(float a);
void removeBulletSprite(cocos2d::Node * bullet);
bool onTouchBegin(Touch * touch, Event * event);
void onTouchEnd(Touch * touch, Event * event);
void onTouchMoved(Touch * touch, Event * event);
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
//char * FontToUTF8(const char * font);
// implement the "static create()" method manually
CREATE_FUNC(SecondScene);
};
#endif // __HELLOWORLD_SCENE_H__
BOOL WCharToMByte(LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize);
SecondScene.cpp
#include "SecondScene.h"
#include "SimpleAudioEngine.h"
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* SecondScene::createScene()
{
Scene* scene = Scene::createWithPhysics();
SecondScene* layer = SecondScene::create();
scene->addChild(layer);
return scene;
}
// on "init" you need to initialize your instance
bool SecondScene::init()
{
//
// 1. super init first
if (!Scene::init())
{
return false;
}
if (!Scene::initWithPhysics())
{
return false;
}
visibleSize = Director::getInstance()->getVisibleSize();
origin = Director::getInstance()->getVisibleOrigin();
sprite = Sprite::create("background.png");
sprite->setContentSize(visibleSize);
sprite->setAnchorPoint(Point::ZERO);
sprite->setPosition(origin);
this->addChild(sprite, 0);
sprite1 = Sprite::create("background.png");
sprite1->setContentSize(visibleSize);
sprite1->setAnchorPoint(Point::ZERO);
sprite1->setPosition(Vec2(origin.x, origin.y + visibleSize.height));
this->addChild(sprite1, 0);
Size playsize = sprite->getContentSize();
primesprite = Sprite::create("donhua/1.png");
SpriteFrame* frame = NULL;
Vector<SpriteFrame*>aniframe;
for (int i = 1; i <= 7; i++)
{
frame = SpriteFrame::create(String::createWithFormat("donhua/%d.png", i)
->getCString(), CCRectMake(0, 0, 132, 105));
aniframe.pushBack(frame);
}
CCAnimation* animation = CCAnimation::createWithSpriteFrames(aniframe, 0.1f, -1);
//1.图片数组2.帧动画间隔时间3.动画次数,为-1是重复
Animate* animate = Animate::create(animation);
//RepeatForever* forever = RepeatForever::create(animate);
primesprite->runAction(animate);
primesprite->setPosition(ccp(visibleSize.width / 2+ origin.x, visibleSize.height / 2+ origin.x-200));
//创建刚体
auto playphysicsbody = PhysicsBody::createBox(visibleSize);
playphysicsbody->setGravityEnable(false);
playphysicsbody->setContactTestBitmask(0xFFFFFFFF);
primesprite->addComponent(playphysicsbody);
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchMoved = CC_CALLBACK_2(SecondScene::onTouchMoved, this);
listener->onTouchBegan = CC_CALLBACK_2(SecondScene::onTouchBegin, this);
listener->onTouchEnded = CC_CALLBACK_2(SecondScene::onTouchEnd, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
this->addChild(primesprite,1);
wchar_t str[100] = {
L"number:" };
char strs[200] = {
0 };
WCharToMByte(str, strs, sizeof(str) / sizeof(strs[0]));
gradeLabel = LabelTTF::create(strs, "Felt", 24);
gradeLabel->setAnchorPoint(Vec2(0, 0));
gradeLabel->setPosition(Vec2(origin.x,
origin.y + visibleSize.height - gradeLabel->getContentSize().height));
this->addChild(gradeLabel, 3);
auto contactlistener = EventListenerPhysicsContact::create();
contactlistener->onContactBegin = CC_CALLBACK_1(SecondScene::onContactBegin, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactlistener,this);
this->scheduleUpdate();
this->schedule(schedule_selector(SecondScene::playFireAction), 0.5f);
this->schedule(schedule_selector(SecondScene::creatEnemySpriteAction), 0.5f);
this->schedule(schedule_selector(SecondScene::imgrotate), 0.001);
return true;
}
bool SecondScene::onContactBegin(PhysicsContact& contact)
{
auto nodeA = contact.getShapeA()->getBody()->getNode();//两个碰撞刚体相对应的节点之A
auto nodeB = contact.getShapeB()->getBody()->getNode();
if (nodeA&&nodeB)
{
if (nodeA->getName() == "enemy"&&nodeB->getName() == "bullet")
{
this->removeChild(nodeA);
this->removeChild(nodeB);
grade++;
gradeLabel->setString("分数:" + std::to_string(grade*100));
}
else if (nodeA->getName() == "bullet" && nodeB->getName() == "enemy") {
this->removeChild(nodeA);
this->removeChild(nodeB);
grade++;
gradeLabel->setString("分数 : " + std::to_string(grade * 100));
}
else if (nodeA->getName() == "play" && nodeB->getName() == "enemy") {
auto gameOver = HelloWorld::create();
/*gameOver->setGrade(gradeLabel->getString());
Director::getInstance()->replaceScene(gameOver);*/
}
else if (nodeA->getName() == "enemy" && nodeB->getName() == "play") {
auto gameOver = HelloWorld::create();
/*gameOver->setGrade(gradeLabel->getString());
Director::getInstance()->replaceScene(gameOver);*/
}
}
return false;
}
void SecondScene::update(float delta)
{
}
void SecondScene::creatEnemySpriteAction(float delta) {
auto enemy = Sprite::create("diren.png");
int x = rand() % ((int)(visibleSize.width + origin.x) + 1);
enemy->setPosition(ccp(x, origin.y + visibleSize.height));
enemy->setName("enemy");
auto enemyphysicsbody = PhysicsBody::createBox(enemy->getContentSize());
enemyphysicsbody->setGravityEnable(false);
enemyphysicsbody->setContactTestBitmask(0xFFFFFFFF);
enemy->addComponent(enemyphysicsbody);
auto moveto = MoveTo::create(3.0, Vec2(enemy->getPosition().x, 0));
auto funn = CallFuncN::create(this, callfuncN_selector(
SecondScene::removeBulletSprite));
FiniteTimeAction* movefinite = Sequence::create(moveto, funn, NULL);
enemy->runAction(movefinite);
this->addChild(enemy, 1);
}
void SecondScene::playFireAction(float delta) {
Size playSize = primesprite->getContentSize();
Point playPoint = primesprite->getPosition();
auto bulletSprite = Sprite::create("zidan.png");
bulletSprite->setPosition(Vec2(playPoint.x, playPoint.y + playSize.height / 2.0 + 5));
bulletSprite->setName("bullet");
auto bulletPhysicsBody = PhysicsBody::createBox(bulletSprite->getContentSize());
bulletPhysicsBody->setGravityEnable(false);//不受重力影响
bulletPhysicsBody->setContactTestBitmask(0xFFFFFFFF);
bulletSprite->addComponent(bulletPhysicsBody);
auto visibleSize = Director::getInstance()->getVisibleSize();
auto moveTo = MoveTo::create(0.5, Vec2(bulletSprite->getPosition().x, visibleSize.height));
CallFuncN *funN = CallFuncN::create(this, callfuncN_selector(SecondScene::removeBulletSprite));
FiniteTimeAction *moveFiniteTimeAction = Sequence::create(moveTo, funN, NULL);
bulletSprite->runAction(moveFiniteTimeAction);
this->addChild(bulletSprite, 1);
}
//销毁子弹
void SecondScene::removeBulletSprite(cocos2d::Node *bullet) {
this->removeChild(bullet);
}
bool SecondScene::onTouchBegin(Touch* touch, Event* event) {
return true;
}
void SecondScene::onTouchMoved(Touch* touch, Event* event) {
Rect ballRect = primesprite->getBoundingBox();
//获取精灵的区域
Vec2 beginPoint = touch->getLocation();
//获取触摸的开始位置
if (ballRect.containsPoint(beginPoint)) {
Point endPoint = touch->getPreviousLocation();
//获取触摸的结束位置
Point offSet = beginPoint - endPoint;
//计算出两个位置的差
Point newPosition = primesprite->getPosition() + offSet;
//计算出精灵现在应该在的位置
primesprite->setPosition(newPosition);
//把精灵的位置设置到它应该在的位置
}
}
void SecondScene::onTouchEnd(Touch* touch, Event* event) {
}
void SecondScene::imgrotate(float a)
{
visibleSize = Director::getInstance()->getVisibleSize();
origin = Director::getInstance()->getVisibleOrigin();
sprite->setPositionY(sprite->getPositionY() - 0.3);//-0.3使精灵之间衔接自然
sprite1->setPositionY(sprite->getPositionY() + visibleSize.height);//精灵2与精灵1始终保持1个屏幕的距离
if (sprite1->getPositionY() <= 0)
{
sprite->setPositionY(0);//精灵2到底后,重置精灵1
}
}
void SecondScene::menuCloseCallback(Ref* pSender)
{
//Director::getInstance()->end();
}
//中午显示
BOOL WCharToMByte(LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize)
{
DWORD dwMinSize;
dwMinSize = WideCharToMultiByte(CP_UTF8, NULL, lpcwszStr, -1, NULL, 0, NULL, FALSE);
if (dwSize < dwMinSize)
{
return false;
}
WideCharToMultiByte(CP_UTF8, NULL, lpcwszStr, -1, lpszStr, dwSize, NULL, FALSE);
return true;
}