作业要求
- 控制板子左右移动
- 在顶部生成小砖块
- 使用关节固定球与板子
- 为板子、球、以及砖块设置物理属性
- 砖、球碰撞则消去砖头,球与地板碰撞则游戏结束
- 至少使用一种粒子效果(加在球上面,etc)
游戏演示
具体实现
HitBrick.h
#ifndef __HIT_BRICK_H__
#define __HIT_BRICK_H__
#include "cocos2d.h"
using namespace std;
USING_NS_CC;
class HitBrick : public Layer {
public:
static PhysicsWorld* world;
static cocos2d::Scene* createScene();
void setPhysicsWorld(PhysicsWorld * world);
virtual bool init();
void setJoint();
void addSprite();
void addPlayer();
void addListener();
void update(float dt);
void updateShip(float dt);
void BrickGeneraetd();
void onKeyPressed(EventKeyboard::KeyCode code, Event * event);
void onKeyReleased(EventKeyboard::KeyCode code, Event * event);
bool onConcactBegin(PhysicsContact & contact);
void preloadMusic();
void GameOver();
void loadAnimation(string filepath);
void replayCallback(Ref * pSender);
void exitCallback(Ref * pSender);
CREATE_FUNC(HitBrick);
private:
PhysicsWorld* m_world;
Size visibleSize;
Sprite* player;
Sprite* ship;
bool onBall;
Sprite* ball;
PhysicsJointPin * joint1;
int spHolded;
int spFactor;
enum Tag {SHIP, BALL, BOX, BOARD};
};
#endif // __HIT_BRICK_H__
HitBrick.cpp
#pragma execution_character_set("utf-8")
#include "HitBrick.h"
#include "cocos2d.h"
#include "SimpleAudioEngine.h"
#define database UserDefault::getInstance()
USING_NS_CC;
using namespace CocosDenshion;
void HitBrick::setPhysicsWorld(PhysicsWorld* world) { m_world = world; }
Scene* HitBrick::createScene() {
srand((unsigned)time(NULL));
auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setAutoStep(true);
scene->getPhysicsWorld()->setGravity(Vec2(0, -300.0f));
auto layer = HitBrick::create();
layer->setPhysicsWorld(scene->getPhysicsWorld());
layer->setJoint();
scene->addChild(layer);
return scene;
}
bool HitBrick::init() {
if (!Layer::init()) {
return false;
}
visibleSize = Director::getInstance()->getVisibleSize();
auto edgeSp = Sprite::create();
auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PhysicsMaterial(0.0f, 1.0f, 0.0f), 3);
edgeSp->setPosition(visibleSize.width / 2, visibleSize.height / 2);
edgeSp->setPhysicsBody(boundBody);
addChild(edgeSp);
preloadMusic();
addSprite();
addListener();
addPlayer();
BrickGeneraetd();
schedule(schedule_selector(HitBrick::update), 0.01f, kRepeatForever, 0.1f);
onBall = true;
spHolded = -1;
spFactor = 0;
return true;
}
void HitBrick::setJoint() {
Vec2 fixPoint = Vec2(ball->getAnchorPoint().x, ball->getAnchorPoint().y - 30);
joint1 = PhysicsJointPin::construct(ball->getPhysicsBody(), player->getPhysicsBody(), fixPoint, player->getAnchorPoint());
m_world->addJoint(joint1);
}
void HitBrick::preloadMusic() {
auto sae = SimpleAudioEngine::getInstance();
sae->preloadEffect("gameover.mp3");
sae->preloadBackgroundMusic("bgm.mp3");
sae->playBackgroundMusic("bgm.mp3", true);
}
void HitBrick::addSprite() {
auto bgSprite = Sprite::create("bg.png");
bgSprite->setPosition(visibleSize / 2);
bgSprite->setScale(visibleSize.width / bgSprite->getContentSize().width, visibleSize.height / bgSprite->getContentSize().height);
this->addChild(bgSprite, 0);
ship = Sprite::create("ship.png");
ship->setScale(visibleSize.width / ship->getContentSize().width * 0.97, 1.2f);
ship->setPosition(visibleSize.width / 2, 0);
auto shipbody = PhysicsBody::createBox(ship->getContentSize(), PhysicsMaterial(100.0f, 0.0f, 1.0f));
shipbody->setCategoryBitmask(0xFFFFFFFF);
shipbody->setCollisionBitmask(0xFFFFFFFF);
shipbody->setContactTestBitmask(0xFFFFFFFF);
shipbody->setTag(Tag::SHIP);
shipbody->setDynamic(false);
ship->setPhysicsBody(shipbody);
this->addChild(ship, 1);
auto sunSprite = Sprite::create("sun.png");
sunSprite->setPosition(rand() % (int)(visibleSize.width - 200) + 100, 550);
this->addChild(sunSprite);
auto cloudSprite1 = Sprite::create("cloud.png");
cloudSprite1->setPosition(rand() % (int)(visibleSize.width - 200) + 100, rand() % 100 + 450);
this->addChild(cloudSprite1);
auto cloudSprite2 = Sprite::create("cloud.png");
cloudSprite2->setPosition(rand() % (int)(visibleSize.width - 200) + 100, rand() % 100 + 450);
this->addChild(cloudSprite2);
}
void HitBrick::addListener() {
auto keyboardListener = EventListenerKeyboard::create();
keyboardListener->onKeyPressed = CC_CALLBACK_2(HitBrick::onKeyPressed, this);
keyboardListener->onKeyReleased = CC_CALLBACK_2(HitBrick::onKeyReleased, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(HitBrick::onConcactBegin, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
}
void HitBrick::addPlayer() {
player = Sprite::create("bar.png");
int xpos = visibleSize.width / 2;
player->setScale(0.1f, 0.1f);
player->setPosition(Vec2(xpos, ship->getContentSize().height - player->getContentSize().height*0.1f));
auto playerBody = PhysicsBody::createBox(player->getContentSize(), PhysicsMaterial(1000.0f, 1.0f, 10.0f));
playerBody->setCategoryBitmask(0xFFFFFFFF);
playerBody->setCollisionBitmask(0xFFFFFFFF);
playerBody->setContactTestBitmask(0xFFFFFFFF);
playerBody->setGravityEnable(false);
playerBody->setTag(Tag::BOARD);
player->setPhysicsBody(playerBody);
player->getPhysicsBody()->setRotationEnable(false);
this->addChild(player, 2);
ball = Sprite::create("ball.png");
ball->setPosition(Vec2(xpos, player->getPosition().y + ball->getContentSize().height*0.1f));
ball->setScale(0.1f, 0.1f);
auto ballBody = PhysicsBody::createCircle(ball->getContentSize().height / 2, PhysicsMaterial(0.1f, 1.0f, 0.0f));
ballBody->setCategoryBitmask(0xFFFFFFFF);
ballBody->setCollisionBitmask(0xFFFFFFFF);
ballBody->setContactTestBitmask(0xFFFFFFFF);
ballBody->setGravityEnable(false);
ballBody->setTag(Tag::BALL);
ballBody->setRotationEnable(false);
ball->setPhysicsBody(ballBody);
addChild(ball, 3);
}
void HitBrick::update(float dt) {
if (player->getPosition().x < 100) {
player->setPosition(100,player->getPosition().y);
player->getPhysicsBody()->setVelocity(Vec2(0, 0));
}
else if (player->getPosition().x > visibleSize.width - 100)
{
player->setPosition(visibleSize.width - 100, player->getPosition().y);
player->getPhysicsBody()->setVelocity(Vec2(0, 0));
}
if (spHolded == 1)
spFactor++;
}
void HitBrick::BrickGeneraetd() {
for (int i = 0; i < 3; i++) {
int cw = 30;
while (cw <= visibleSize.width) {
auto box = Sprite::create("box.png");
box->setPosition(cw, visibleSize.height - box->getContentSize().height * (i + 1));
cw += box->getContentSize().width;
auto boxBody = PhysicsBody::createCircle(box->getContentSize().height / 2, PhysicsMaterial(100.0f, 1.0f, 0.0f));
boxBody->setCategoryBitmask(0xFFFFFFFF);
boxBody->setCollisionBitmask(0xFFFFFFFF);
boxBody->setContactTestBitmask(0xFFFFFFFF);
boxBody->setGravityEnable(false);
boxBody->setTag(Tag::BOX);
boxBody->setDynamic(false);
box->setPhysicsBody(boxBody);
box->getPhysicsBody()->setRotationEnable(false);
addChild(box, 4);
}
}
}
void HitBrick::onKeyPressed(EventKeyboard::KeyCode code, Event* event) {
switch (code) {
case cocos2d::EventKeyboard::KeyCode::KEY_LEFT_ARROW:
if (player->getPosition().x > 100) {
player->getPhysicsBody()->setVelocity(Vec2(-500, 0));
}
else {
player->getPhysicsBody()->setVelocity(Vec2(0, 0));
}
break;
case cocos2d::EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
if (player->getPosition().x < visibleSize.width - 100) {
player->getPhysicsBody()->setVelocity(Vec2(500, 0));
}
else {
player->getPhysicsBody()->setVelocity(Vec2(0, 0));
}
break;
case cocos2d::EventKeyboard::KeyCode::KEY_SPACE:
if (spHolded == -1)
spHolded = 1;
break;
default:
break;
}
}
void HitBrick::onKeyReleased(EventKeyboard::KeyCode code, Event* event) {
switch (code) {
case cocos2d::EventKeyboard::KeyCode::KEY_LEFT_ARROW:
case cocos2d::EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
player->getPhysicsBody()->setVelocity(Vec2(0, 0));
break;
case cocos2d::EventKeyboard::KeyCode::KEY_SPACE:
if (spHolded == 1) {
spHolded = 0;
m_world->removeJoint(joint1);
ball->getPhysicsBody()->setVelocity(Vec2(0, spFactor * 30));
}
break;
default:
break;
}
}
bool HitBrick::onConcactBegin(PhysicsContact & contact) {
auto c1 = contact.getShapeA()->getBody(), c2 = contact.getShapeB()->getBody();
auto s1 = (Sprite*)c1->getNode(), s2 = (Sprite*)c2->getNode();
auto rain = ParticleRain::create();
if (c1->getTag() == Tag::BOX && c2->getTag() == Tag::BALL) {
rain->setPosition(s1->getPosition());
addChild(rain);
s1->removeFromParentAndCleanup(true);
}
else if (c2->getTag() == Tag::BOX && c1->getTag() == Tag::BALL) {
rain->setPosition(s2->getPosition());
addChild(rain);
s2->removeFromParentAndCleanup(true);
}
else if (c1->getTag() == Tag::SHIP && c2->getTag() == Tag::BALL ||
c2->getTag() == Tag::SHIP && c1->getTag() == Tag::BALL) {
GameOver();
}
return true;
}
void HitBrick::GameOver() {
_eventDispatcher->removeAllEventListeners();
ball->getPhysicsBody()->setVelocity(Vec2(0, 0));
player->getPhysicsBody()->setVelocity(Vec2(0, 0));
SimpleAudioEngine::getInstance()->stopBackgroundMusic("bgm.mp3");
SimpleAudioEngine::getInstance()->playEffect("gameover.mp3", false);
auto label1 = Label::createWithTTF("Game Over~", "fonts/STXINWEI.TTF", 60);
label1->setColor(Color3B(0, 0, 0));
label1->setPosition(visibleSize.width / 2, visibleSize.height / 2);
this->addChild(label1);
auto label2 = Label::createWithTTF("重玩", "fonts/STXINWEI.TTF", 40);
label2->setColor(Color3B(0, 0, 0));
auto replayBtn = MenuItemLabel::create(label2, CC_CALLBACK_1(HitBrick::replayCallback, this));
Menu* replay = Menu::create(replayBtn, NULL);
replay->setPosition(visibleSize.width / 2 - 80, visibleSize.height / 2 - 100);
this->addChild(replay);
auto label3 = Label::createWithTTF("退出", "fonts/STXINWEI.TTF", 40);
label3->setColor(Color3B(0, 0, 0));
auto exitBtn = MenuItemLabel::create(label3, CC_CALLBACK_1(HitBrick::exitCallback, this));
Menu* exit = Menu::create(exitBtn, NULL);
exit->setPosition(visibleSize.width / 2 + 90, visibleSize.height / 2 - 100);
this->addChild(exit);
}
void HitBrick::replayCallback(Ref * pSender) {
Director::getInstance()->replaceScene(HitBrick::createScene());
}
void HitBrick::exitCallback(Ref * pSender) {
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
视频以及资源
视频以及资源