Level_01.h
#ifdef WIN32
#pragma execution_character_set("utf-8")
#pragma once
#ifndef __LEVEL01_SCENE_H__
#define __LEVEL01_SCENE_H__
#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include "SimpleAudioEngine.h"
#include <string.h>
#include <time.h>
#include "cocos-ext.h"
#include "Stage.h"
#include "GameOver.h"
using namespace cocos2d::ui;
using namespace CocosDenshion;
USING_NS_CC_EXT;
USING_NS_CC;
class Level_01 : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();
Stage* stage;
bool touchingSwapping = false; //表示当时是否正在交换
int x1, y1; //用于判断第一个触摸的点
int x2, y2; //用于判断第二个触摸的点
Label* scoreLabel;
LoadingBar* timeBar;
float barLength = 1800.0f;
//void initGameArea(); //初始化游戏区域
void backToGameMenuScene(); //返回主菜单
virtual bool init();
void reSwap(float dl);
void eraseBlocks(float dl);
//与玩家交互的三个监听函数
bool onTouchStart(Touch *touch, Event *event);
void onTouchMove(Touch *touch, Event *event);
void onTouchEnd(Touch *touch, Event *event);
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
void update(float dl);
// implement the "static create()" method manually
CREATE_FUNC(Level_01);
};
#endif // __LEVEL01_SCENE_H__#pragma once
#endif
Level_01.cpp
#include "Level_01.h"
USING_NS_CC_EXT;
USING_NS_CC;
Scene* Level_01::createScene(){
return Level_01::create();
}
static void problemLoading(const char* filename){
printf("Error while loading: %s\n", filename);
printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in Level_01Scene.cpp\n");
}
bool Level_01::init()
{
if (!Scene::init()){
return false;
}
// 这两个参数一般用来计算相对位置的
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
//创建背景
Sprite *backGround = Sprite::create("background.png");
backGround->setAnchorPoint(Point(0.5, 0.5));
backGround->setPosition(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y);
backGround->setScale(1);
this->addChild(backGround, 0);
//创建游戏区域
Sprite *gameArea = Sprite::create("gameArea.png");
gameArea->setPosition(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y);
gameArea->setOpacity(200);
this->addChild(gameArea, 1);
//创建方块的Stage层,层可以看作是保留了最基础功能的透明精灵,我们可以在它上面挂载新的节点或者监听事件
stage = Stage::create();
this->addChild(stage, 2);
stage->Bartime = 1800;
stage->score = 0; //分数
stage->setPosition(Vec2(-40, 150));
//创建上方进度条与分数
scoreLabel = Label::createWithTTF("得分", "fonts/蒙纳简电脑体.ttf", 24);
scoreLabel->setColor(Color3B::WHITE);
scoreLabel->setPosition(Vec2(origin.x + visibleSize.width / 2,
origin.y + visibleSize.height - scoreLabel->getContentSize().height - 75));
this->addChild(scoreLabel, 1);
//制作时间进度条
auto timeBarBorder = Sprite::create("prohressBarBorder.png");
timeBarBorder->setAnchorPoint(Point(0.5, 0.5));
timeBarBorder->setPosition(visibleSize.width / 2, visibleSize.height - 150);
this->addChild(timeBarBorder, 6);
timeBar = ui::LoadingBar::create("prohressBar.png");
timeBar->setAnchorPoint(Point(0.5, 0.5));
timeBar->setPosition(Vec2(visibleSize.width / 2, visibleSize.height - 150));
timeBar->setDirection(ui::LoadingBar::Direction::LEFT);
this->addChild(timeBar, 5);
//update更新函数,用于更新每时每刻的时间减少
this->scheduleUpdate();
//创建用户移动方块的代码部分
//监听器监听图标状态
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = CC_CALLBACK_2(Level_01::onTouchStart, this);
listener->onTouchMoved = CC_CALLBACK_2(Level_01::onTouchMove, this);
listener->onTouchEnded = CC_CALLBACK_2(Level_01::onTouchEnd, this);
auto eventDispatcher = Director::getInstance()->getEventDispatcher();
eventDispatcher->addEventListenerWithSceneGraphPriority(listener, stage);
//创建游戏下方的菜单
MenuItemFont::setFontName("BoLeHuaiShuti");
MenuItemFont::setFontSize(48);
auto backToMainScene = MenuItemFont::create("返回游戏主菜单", CC_CALLBACK_0(Level_01::backToGameMenuScene, this));
backToMainScene->setColor(Color3B(255, 250, 250));
backToMainScene->setPosition(visibleSize.width / 2, 100);
auto bottomMenu = Menu::create(backToMainScene, NULL);
bottomMenu->setPosition(Vec2::ZERO);
this->addChild(bottomMenu, 5);
return true;
}
void Level_01::reSwap(float dl) {
stage->swapBlocks(stage->x1, stage->y1, stage->x2, stage->y2);
stage->isSwapping = false;
}
void Level_01::eraseBlocks(float dl) {
stage->removeBlocks();//清除方块
stage->initNewBlocks();//生成新的方块
if (stage->moveDownBlocks()) {//落下未清除的方块
//如果落下后仍可以消除
scheduleOnce(schedule_selector(Level_01::eraseBlocks), 0.3f);
}
else { //说明已经没有可以被消除的方块了
stage->isSwapping = false;
touchingSwapping = false;
}
}
////与玩家交互的三个监听函数
//bool Level_01::onTouchStart(Touch *touch, Event *event) {
// log("touchStart函数触发次数");
// for (int i = 1; i <= (stage->n); i++) {
// for (int j = 1; j <= (stage->m); j++) {
// //接下来我们需要检测,到底是触碰到了哪一个方块
// if (stage->tag[i][j] <= 0)
// continue; //防止触碰到墙壁或者刻意留下的空洞上
//
// //获取block的碰撞Box,并用这个Box自带的containsPoint函数判断touch的点在不在它的里面
// if (stage->blocks[i][j]->getBoundingBox().containsPoint(touch->getLocation())) {
//
// log("方块被触碰的触发次数");
// if (stage->ifSelected == false) { //表示之前没有选择任何一个方块
// log("第一次选择触发次数");
// //那么现在选到了一个
// stage->ifSelected = true;
// //保存选到的方块
// stage->setSelectedBlock(stage->blocks[i][j], 1, true);
//
// }
// else if (stage->firstSelectedBlock!=stage->blocks[i][j]) { //已选中条件下,不允许重复选择
// log("第二次选择触发次数");
// //以下计算表示新的(i,j)与之前选中的是相邻的两个点
// if ((abs(stage->firstSelectedBlock->getX() - i) + abs(stage->firstSelectedBlock->getY() - j) == 1)) {
// stage->ifSelected = false;
// stage->setSelectedBlock(stage->blocks[i][j], 2, true);
// //那么就需要交换
// if(stage->firstSelectedBlock && stage->secondSelectedBlock)
// stage->swapBlocks(stage->firstSelectedBlock->getX(), stage->firstSelectedBlock->getY(), i, j);
// }
// //但如果第二个不是相邻的方块,那么就把第一次选中的更换为当前选择的
// else {
// log("非相邻方块被选中");
// stage->setSelectedBlock(stage->firstSelectedBlock, 1, false); //把第一次的取消选中
// stage->setSelectedBlock(stage->blocks[i][j], 1, true); //把第二次的放进第1号选中位置
//
// stage->ifSelected = true;
// }
// }
// return true; //找到一个就需要中止循环
// }
// }
// }
// return false; //表示不吞没
//}
//交互的三个监听函数
bool Level_01::onTouchStart(Touch *touch, Event *event) {
if (stage->isSwapping) {
log("Swapping!");
return true;
}
log("Touching");
auto target = static_cast<Sprite *>(event->getCurrentTarget());
Vec2 touchLocalPosition = target->convertToNodeSpace(touch->getLocation());
for (int i = 1; i <= (stage-> n); i++) {
for (int j = 1; j <= (stage->m); j++) {
if (stage->tag[i][j] <= 0)
continue;
if (stage->blocks[i][j]->getBoundingBox().containsPoint(touchLocalPosition)) {
if (x1 == -1){//我们让横坐标为-1时,表示1号位没有选中物体,所以当前正在点击第一个点
x1 = i; y1 = j; //保存第一个点的位置信息
stage->setSelectedBlock(stage->blocks[i][j], 1, true); //第一个点被选中
}
else if (x1 != i||y1 != j) { //当第二次点击的点跟第一次的位置不一样时
x2 = i; y2 = j; //保存第二个点的位置信息
if (abs(x1 - x2) + abs(y1 - y2) == 1) { //这个判断可用于判断是否是相邻两点
//交换两点
if (stage->swapBlocks(x1, y1, x2, y2)) //如果交换后满足消除,激发对应回调函数清除方块
scheduleOnce(schedule_selector(Level_01::eraseBlocks), 0.3f);
else //如果交换后不满足,那么还需要交换回来
scheduleOnce(schedule_selector(Level_01::reSwap), 0.3f);
x1 = -1; //重置为-1,表示没有一个砖块被选
}
else{
stage->setSelectedBlock(stage->blocks[x1][y1], 1, false);//把原先的点去除选择
stage->setSelectedBlock(stage->blocks[i][j], 1,true);//如果不是相邻的两点,就把现在的这个点放入1号位
x1 = x2; y1 = y2; //更换一号位的坐标
}
}
return true;
}
}
}
return false; //返回false表示
}
void Level_01::onTouchMove(Touch *touch, Event *event) {
if (stage->isSwapping) {
log("正在交换中");
return;
}
auto target = static_cast<Sprite *>(event->getCurrentTarget());
Vec2 touchLocalPosition = target->convertToNodeSpace(touch->getLocation());
for (int i = 1; i <= (stage->n); i++) {
for (int j = 1; j <= (stage->m); j++) {
if (stage->tag[i][j] <= 0 || touchingSwapping)
continue; //由于move函数将会被触发多次,所以需要有限制
if (stage->blocks[i][j]->getBoundingBox().containsPoint(touchLocalPosition)) {
if ((i == x1&&j == y1) || x1 == -1) //如果是鼠标在同一个点中move,或者第一个点没选中,中止
return;
//只有当第一个点存在,即(x1!=-1)时,我们才进行第二个点的判断
x2 = i;
y2 = j;
if (abs(x1 - x2) + abs(y1 - y2) == 1) { //相邻两点
//交换两点
if (stage->swapBlocks(x1, y1, x2, y2)) { //如果交换后满足消除
touchingSwapping = true;
scheduleOnce(schedule_selector(Level_01::eraseBlocks), 0.3f);
}
else //如果交换后不满足,那么还需要交换回来
scheduleOnce(schedule_selector(Level_01::reSwap), 0.3f);
x1 = -1;
}
else{ //不相邻,就把第二次选择的放入第一个
stage->setSelectedBlock(stage->blocks[x1][y1], 1, false);//把原先的点去除选择
stage->setSelectedBlock(stage->blocks[i][j], 1, true);
x1 = x2; y1 = y2; //更换一号位的坐标
}
}
}
}
}
void Level_01::onTouchEnd(Touch *touch, Event *event) {
if (stage->isSwapping) {
log("正在交换中");
return;
}
//只有当用户抬起鼠标之后,才开放touchingSwapping,防止用户满屏幕乱晃导致的交换时多次移动
touchingSwapping = false;
}
// 返回原菜单
void Level_01::backToGameMenuScene() {
//auto scene = GameMenu::createScene();
Director::getInstance()->popScene();
}
void Level_01::menuCloseCallback(Ref* pSender)
{
Director::getInstance()->end();
}
void Level_01::update(float dl) {
char score[64]="";
if (stage != nullptr) {
if (stage->Bartime > 0) {
stage->Bartime--;
timeBar->setPercent((stage->Bartime / barLength) * 100);
sprintf(score, "得分:%d", stage->score);
scoreLabel->setString(score);
}
else {
auto gameOverScene = GameOver::create();
gameOverScene->setNowScore(stage->score);
Director::getInstance()->replaceScene(gameOverScene);
}
}
}