cocos2dx 3.x 实现flappybird 不使用物理引擎

cocos2dx 3.x 实现flappybird 不使用物理引擎

效果截图

在这里插入图片描述

导语

重力的实现是用schedule,碰撞检测是用intersectsRect

项目目录

在这里插入图片描述

代码

GameDefine.h

#pragma once

#define GAME_WIDTH 288
#define GAME_HEIGHT 512
#define GAME_START 1
#define GAME_OVER 0
#define GAME_INIT -1
#define PIPE_WIDTH 52
#define PIPE_START_WIDTH 500
#define PIPE_BETWEEN_WIDTH 170
#define PIPE_SPACE 50
#define PIPE_VARIATION_RANGE 200

GameScene.h

#include "cocos2d.h"
#include "GameDefine.h"

USING_NS_CC;

class GameScene : public Scene
{
public:
	static Scene *createScene();

	virtual bool init();

	CREATE_FUNC(GameScene);

	virtual void update(float delta);
	virtual bool onTouchBeganButton(Touch *touch, Event *event);
	virtual bool onTouchScene(Touch *touch, Event *event);
	virtual void birdUpAction(float delta);

private:
	void gameStart();
	void gameOver();
	void gameRestart();
	Vector<Sprite *> pipes;
	Vector<SpriteFrame *> animFrames;
	int gameStatus;
	int downSpeed;
	int upSpeed;
	int score;
};

GameScene.cpp

#include "GameScene.h"

Scene *GameScene::createScene()
{
	auto scene = Scene::create();
	auto layer = GameScene::create();
	scene->addChild(layer);
	return scene;
}

bool GameScene::init()
{
	if (!Scene::init())
	{
		return false;
	}
	//随机种子//
	srand((int)time(0));
	//背景//
	auto bgSprite = Sprite::create("bg_day.png");
	bgSprite->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2);
	this->addChild(bgSprite);

	//地板//
	auto land1 = Sprite::create("land.png");
	land1->setAnchorPoint(Point::ZERO);
	land1->setPosition(Point::ZERO);
	land1->setName("land1");
	this->addChild(land1);
	auto land2 = Sprite::create("land.png");
	land2->setAnchorPoint(Point::ZERO);
	land2->setPosition(Point::ZERO);
	land2->setName("land2");
	this->addChild(land2);

	//设置初始变量//
	gameStatus = GAME_INIT;
	score = 0;

	//标题//
	auto title = Sprite::create("title.png");
	title->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2 + 100);
	title->setName("title");
	this->addChild(title);

	//小鸟//
	auto birdSprite = Sprite::create("bird1.png");
	birdSprite->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2 + 50);
	birdSprite->setVisible(false);
	birdSprite->setName("birdSprite");
	this->addChild(birdSprite, 9);

	//小鸟飞帧动画//
	animFrames.pushBack(SpriteFrame::create("bird1.png", Rect(0, 0, 38, 27)));
	animFrames.pushBack(SpriteFrame::create("bird2.png", Rect(0, 0, 38, 27)));
	animFrames.pushBack(SpriteFrame::create("bird3.png", Rect(0, 0, 38, 27)));

	//上下抖动//
	//auto up = MoveBy::create(0.4f, Point(0, 8));
	//swingAction = RepeatForever::create(Sequence::create(up, up->reverse(), NULL));
	//birdSprite->runAction(swingAction);

	//开始按钮//
	auto beginSprite = Sprite::create("button_play.png");
	beginSprite->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2);
	beginSprite->setName("beginSprite");
	//绑定事件//
	auto touchListener = EventListenerTouchOneByOne::create();
	touchListener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBeganButton, this);
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, beginSprite);
	this->addChild(beginSprite, 10);

	//分数面板//
	auto scoreSprite = Sprite::create("score.png");
	scoreSprite->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2);
	scoreSprite->setName("scoreSprite");
	scoreSprite->setVisible(false);
	this->addChild(scoreSprite, 9);
	//结束text//
	auto textGameOver = Sprite::create("text_game_over.png");
	textGameOver->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2 + 100);
	textGameOver->setName("textGameOver");
	textGameOver->setVisible(false);
	this->addChild(textGameOver, 10);
	//分数//
	auto scoreLabel = Label::createWithSystemFont("0", "黑体", 20);
	scoreLabel->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2 + 10);
	scoreLabel->setName("scoreLabel");
	scoreLabel->setVisible(false);
	this->addChild(scoreLabel, 10);
	//最好分数//
	auto maxScoreLabel = Label::createWithSystemFont("0", "黑体", 20);
	maxScoreLabel->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2 - 30);
	maxScoreLabel->setName("maxScoreLabel");
	maxScoreLabel->setVisible(false);
	this->addChild(maxScoreLabel, 10);
	//显示在游戏中的分数//
	auto nowScoreLabel = Label::createWithSystemFont("0", "黑体", 50);
	nowScoreLabel->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2 + 200);
	nowScoreLabel->setName("nowScoreLabel");
	nowScoreLabel->setVisible(false);
	this->addChild(nowScoreLabel, 10);
	//绑定事件//
	auto eventListener = EventListenerTouchOneByOne::create();
	eventListener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchScene, this);
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(eventListener, this);
	//启动定时器//
	this->scheduleUpdate();

	return true;
}
bool GameScene::onTouchScene(cocos2d::Touch *touch, cocos2d::Event *event)
{
	if (gameStatus == GAME_START)
	{
		log("click Scene");
		//每点击一次速度重新设定//
		downSpeed = 0;
		upSpeed = 10;
		//点击动作//
		auto rotateUp = RotateTo::create(0.1f, -40.0f);
		auto stop = RotateTo::create(0.4f, -40.0f);
		auto rotateDown = RotateTo::create(0.1f, 40.0f);
		auto touchActionSeq = Sequence::create(rotateUp, stop, rotateDown, nullptr);
		auto birdSprite = this->getChildByName("birdSprite");
		birdSprite->runAction(touchActionSeq);
		//上升加速度事件//
		this->schedule(schedule_selector(GameScene::birdUpAction), 0.0f);
	}
	return true;
}

bool GameScene::onTouchBeganButton(cocos2d::Touch *touch, cocos2d::Event *event)
{
	auto bounds = event->getCurrentTarget()->getBoundingBox();
	if (bounds.containsPoint(touch->getLocation()))
	{
		log("click BeganButton");
		if (gameStatus == GAME_INIT)
		{
			this->removeChildByName("title");
			auto birdSprite = this->getChildByName("birdSprite");
			birdSprite->setVisible(true);
			gameStart();
		}
		if (gameStatus == GAME_OVER)
		{
			gameRestart();
		}
	}
	return true;
}

void GameScene::gameRestart()
{
	//小鸟位置重新设定//
	auto birdSprite = this->getChildByName("birdSprite");
	birdSprite->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2 + 50);

	//显示开始按钮//
	auto beginSprite = this->getChildByName("beginSprite");
	beginSprite->setVisible(false);
	//分数重新设定//
	Label *nowScoreLabel = (Label *)this->getChildByName("nowScoreLabel");
	auto scoreLabel = this->getChildByName("scoreLabel");
	auto maxScoreLabel = this->getChildByName("maxScoreLabel");
	score = 0;
	nowScoreLabel->setVisible(true);
	scoreLabel->setVisible(false);
	maxScoreLabel->setVisible(false);
	nowScoreLabel->setString(StringUtils::format("%d", score));

	this->getChildByName("textGameOver")->setVisible(false);
	this->getChildByName("scoreSprite")->setVisible(false);
	//管道移除//
	for (auto &singlePipe : pipes)
	{
		this->removeChild(singlePipe);
	}

	gameStart();
}
void GameScene::gameStart()
{

	//隐藏开始按钮//
	auto beginSprite = this->getChildByName("beginSprite");
	beginSprite->setVisible(false);
	//小鸟飞行//
	auto birdSprite = this->getChildByName("birdSprite");
	auto animation = Animation::createWithSpriteFrames(animFrames, 0.1f);
	auto animate = Animate::create(animation);
	auto swingAnimate = RepeatForever::create(animate);
	swingAnimate->setTag(99);
	birdSprite->runAction(swingAnimate);

	Label *nowScoreLabel = (Label *)this->getChildByName("nowScoreLabel");
	nowScoreLabel->setVisible(true);
	//设置管道按钮//
	pipes.clear();
	for (int i = 0; i < 2; i++)
	{
		int r = rand() % PIPE_VARIATION_RANGE;
		auto pipeUp = Sprite::create("pipe_up.png");
		pipeUp->setPosition(PIPE_START_WIDTH + i * PIPE_BETWEEN_WIDTH, GAME_HEIGHT - PIPE_SPACE + r);
		pipeUp->setName("newPipe");
		auto pipeDown = Sprite::create("pipe_down.png");
		pipeDown->setPosition(PIPE_START_WIDTH + i * PIPE_BETWEEN_WIDTH, r);
		pipeDown->setName("newPipe");
		this->addChild(pipeUp);
		this->addChild(pipeDown);
		pipes.pushBack(pipeUp);
		pipes.pushBack(pipeDown);
	}
	gameStatus = GAME_START;
}

void GameScene::gameOver()
{
	//显示分数面版//
	this->getChildByName("textGameOver")->setVisible(true);
	this->getChildByName("scoreSprite")->setVisible(true);

	Label *nowScoreLabel = (Label *)this->getChildByName("nowScoreLabel");
	Label *scoreLabel = (Label *)this->getChildByName("scoreLabel");
	Label *maxScoreLabel = (Label *)this->getChildByName("maxScoreLabel");
	scoreLabel->setVisible(true);
	maxScoreLabel->setVisible(true);
	nowScoreLabel->setVisible(false);
	scoreLabel->setString(StringUtils::format("%d", score));

	if (UserDefault::getInstance()->getIntegerForKey("maxScore") < score)
	{
		maxScoreLabel->setString(StringUtils::format("%d", score));
		UserDefault::getInstance()->setIntegerForKey("maxScore", score);
	}
	else
	{
		maxScoreLabel->setString(StringUtils::format("%d", UserDefault::getInstance()->getIntegerForKey("maxScore")));
	}

	//停止飞动作//
	auto birdSprite = this->getChildByName("birdSprite");
	birdSprite->stopAction(birdSprite->getActionByTag(99));

	auto beginSprite = this->getChildByName("beginSprite");
	beginSprite->setVisible(true);
	beginSprite->setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2 - 100);

	gameStatus = GAME_OVER;
}

void GameScene::birdUpAction(float delta)
{
	upSpeed--;
	if (upSpeed < 0)
	{
		this->unschedule(schedule_selector(GameScene::birdUpAction));
	}
	auto birdSprite = this->getChildByName("birdSprite");
	birdSprite->setPositionY(birdSprite->getPositionY() + downSpeed * 1.0f / 2);
}

void GameScene::update(float delta)
{
	//每一帧下落速度都增加//
	downSpeed++;
	Size visibleSize = Director::getInstance()->getVisibleSize();
	auto land1 = this->getChildByName("land1");
	auto land2 = this->getChildByName("land2");
	auto birdSprite = this->getChildByName("birdSprite");
	//游戏中//
	if (gameStatus == GAME_START)
	{
		//两个地板向左平移//
		land1->setPositionX(land1->getPositionX() - 1.0f);
		land2->setPositionX(land1->getPositionX() + land1->getContentSize().width - 2.0f);
		if (land2->getPositionX() <= 0)
		{
			land1->setPosition(Point::ZERO);
		}
		//小鸟重力//
		birdSprite->setPositionY(birdSprite->getPositionY() - downSpeed * 1.0f / 10);

		int index = 0;
		int r = 100;
		//管道移动和生成//
		for (auto &singlePipe : pipes)
		{
			singlePipe->setPositionX(singlePipe->getPositionX() - 1.0f);
			if (singlePipe->getName() == "newPipe")
			{
				if (birdSprite->getPositionX() > singlePipe->getPositionX())
				{
					score++;
					Label *nowScoreLabel = (Label *)this->getChildByName("nowScoreLabel");
					nowScoreLabel->setString(StringUtils::format("%d", score));
					singlePipe->setName("passed");
				}
			}
			if (singlePipe->getPositionX() < -PIPE_WIDTH / 2)
			{
				singlePipe->setPositionX(visibleSize.width + PIPE_WIDTH / 2);
				singlePipe->setName("newPipe");
				if (index % 2 == 0)
				{
					r = rand() % PIPE_VARIATION_RANGE;
					singlePipe->setPositionY(GAME_HEIGHT - PIPE_SPACE + r);
				}
				else
				{
					singlePipe->setPositionY(r);
				}
			}
			index++;
		}
		//碰撞检测//
		//地板
		if (birdSprite->boundingBox().intersectsRect(land2->boundingBox()) || birdSprite->boundingBox().intersectsRect(land1->boundingBox()))
		{
			gameOver();
		}
		//管道
		for (auto &singlePipe : pipes)
		{
			if (birdSprite->boundingBox().intersectsRect(singlePipe->boundingBox()) || birdSprite->boundingBox().intersectsRect(singlePipe->boundingBox()))
			{
				gameOver();
			}
		}
		if (birdSprite->getPositionY() > GAME_HEIGHT)
		{
			gameOver();
		}
	}
	//游戏结束时掉落地板//
	if (gameStatus == GAME_OVER)
	{
		if (!birdSprite->boundingBox().intersectsRect(land2->boundingBox()) && !birdSprite->boundingBox().intersectsRect(land1->boundingBox()))
		{
			birdSprite->setPositionY(birdSprite->getPositionY() - downSpeed * 1.0f);
		}
	}
}

项目地址

https://github.com/ouwenfeng/flappybird.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值