cocos2d-x 开发贪吃蛇代码
时间: 2023-07-25 11:10:05 浏览: 216
以下是用 C++ 和 cocos2d-x 开发贪吃蛇的代码示例:
首先,我们需要创建一个 Snake 类,用于管理贪吃蛇的运动和状态:
```c++
class Snake : public cocos2d::Node {
public:
virtual bool init() override;
CREATE_FUNC(Snake);
void move(); // 移动
void turn(Direction direction); // 转向
bool isDead() const; // 是否死亡
private:
std::vector<cocos2d::Sprite*> m_body; // 身体
Direction m_direction; // 运动方向
bool m_isDead; // 是否死亡
int m_gridWidth; // 网格宽度
};
```
在 Snake 类中,我们定义了以下成员变量:
- m_body:存储贪吃蛇身体的精灵数组;
- m_direction:表示当前的运动方向;
- m_isDead:表示是否已经死亡;
- m_gridWidth:网格宽度,即每个格子的大小。
接下来,我们需要实现 Snake 类的成员函数:
```c++
bool Snake::init() {
if (!Node::init()) {
return false;
}
// 初始化
m_direction = Direction::RIGHT;
m_isDead = false;
m_gridWidth = 10;
// 添加蛇头
auto head = cocos2d::Sprite::create("snake_head.png");
head->setPosition(cocos2d::Vec2(0, 0));
addChild(head);
m_body.push_back(head);
// 添加蛇身
for (int i = 1; i < 4; i++) {
auto body = cocos2d::Sprite::create("snake_body.png");
body->setPosition(cocos2d::Vec2(-i * m_gridWidth, 0));
addChild(body);
m_body.push_back(body);
}
return true;
}
void Snake::move() {
if (m_isDead) {
return;
}
// 移动身体
for (int i = m_body.size() - 1; i > 0; i--) {
auto prevPos = m_body[i - 1]->getPosition();
m_body[i]->setPosition(prevPos);
}
// 移动头部
auto headPos = m_body[0]->getPosition();
switch (m_direction) {
case Direction::UP:
headPos.y += m_gridWidth;
break;
case Direction::DOWN:
headPos.y -= m_gridWidth;
break;
case Direction::LEFT:
headPos.x -= m_gridWidth;
break;
case Direction::RIGHT:
headPos.x += m_gridWidth;
break;
}
m_body[0]->setPosition(headPos);
}
void Snake::turn(Direction direction) {
if (m_isDead) {
return;
}
if ((int)direction + (int)m_direction == 0) {
return;
}
m_direction = direction;
}
bool Snake::isDead() const {
return m_isDead;
}
```
在 init 函数中,我们初始化了贪吃蛇的状态,并添加了蛇头和蛇身。
在 move 函数中,我们首先移动了蛇身,然后根据当前的运动方向移动了蛇头。
在 turn 函数中,我们检查了新的方向是否与当前方向相反,如果是,则不做任何操作。
在 isDead 函数中,我们简单地返回 m_isDead 的值。
接下来,我们需要创建一个 GameLayer 类,用于管理游戏的逻辑和界面:
```c++
class GameLayer : public cocos2d::Layer {
public:
virtual bool init() override;
CREATE_FUNC(GameLayer);
void update(float delta) override; // 帧更新函数
private:
void createFood(); // 创建食物
bool checkCollision(); // 检查碰撞
Snake* m_snake; // 贪吃蛇
cocos2d::Sprite* m_food; // 食物
int m_gridWidth; // 网格宽度
float m_interval; // 更新间隔
};
```
在 GameLayer 类中,我们定义了以下成员变量:
- m_snake:贪吃蛇对象;
- m_food:食物对象;
- m_gridWidth:网格宽度,即每个格子的大小;
- m_interval:更新间隔,即每隔多少秒更新一次贪吃蛇的状态。
接下来,我们需要实现 GameLayer 类的成员函数:
```c++
bool GameLayer::init() {
if (!Layer::init()) {
return false;
}
// 初始化
m_gridWidth = 10;
m_interval = 0.1f;
// 添加贪吃蛇
m_snake = Snake::create();
m_snake->setPosition(cocos2d::Vec2(0, 0));
addChild(m_snake);
// 创建食物
createFood();
// 注册键盘事件
auto listener = cocos2d::EventListenerKeyboard::create();
listener->onKeyPressed = [=](cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event) {
switch (keyCode) {
case cocos2d::EventKeyboard::KeyCode::KEY_UP_ARROW:
m_snake->turn(Direction::UP);
break;
case cocos2d::EventKeyboard::KeyCode::KEY_DOWN_ARROW:
m_snake->turn(Direction::DOWN);
break;
case cocos2d::EventKeyboard::KeyCode::KEY_LEFT_ARROW:
m_snake->turn(Direction::LEFT);
break;
case cocos2d::EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
m_snake->turn(Direction::RIGHT);
break;
default:
break;
}
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
// 开始更新
scheduleUpdate();
return true;
}
void GameLayer::update(float delta) {
m_interval -= delta;
if (m_interval <= 0) {
m_snake->move();
// 检查碰撞
if (checkCollision()) {
m_snake->stopAllActions();
m_snake->setScale(1.0f);
m_snake->runAction(cocos2d::Blink::create(2, 5));
m_snake->setIsDead(true);
return;
}
// 检查是否吃到食物
auto headPos = m_snake->getPosition();
auto foodPos = m_food->getPosition();
if (headPos.distance(foodPos) < m_gridWidth) {
m_food->removeFromParent();
createFood();
auto body = cocos2d::Sprite::create("snake_body.png");
body->setPosition(m_snake->getChildByName("tail")->getPosition());
m_snake->addChild(body);
}
m_interval = 0.1f;
}
}
void GameLayer::createFood() {
// 随机创建食物
auto visibleSize = cocos2d::Director::getInstance()->getVisibleSize();
auto origin = cocos2d::Director::getInstance()->getVisibleOrigin();
int x = (int)origin.x + m_gridWidth + rand() % ((int)visibleSize.width - 2 * m_gridWidth);
int y = (int)origin.y + m_gridWidth + rand() % ((int)visibleSize.height - 2 * m_gridWidth);
m_food = cocos2d::Sprite::create("snake_food.png");
m_food->setPosition(cocos2d::Vec2(x, y));
addChild(m_food);
}
bool GameLayer::checkCollision() {
// 检查是否碰到边界
auto visibleSize = cocos2d::Director::getInstance()->getVisibleSize();
auto origin = cocos2d::Director::getInstance()->getVisibleOrigin();
auto headPos = m_snake->getPosition();
if (headPos.x < origin.x || headPos.y < origin.y
|| headPos.x > origin.x + visibleSize.width || headPos.y > origin.y + visibleSize.height) {
return true;
}
// 检查是否碰到自己
for (int i = 1; i < m_snake->getChildrenCount() - 1; i++) {
auto bodyPos = m_snake->getChildByTag(i)->getPosition();
if (headPos.distance(bodyPos) < m_gridWidth) {
return true;
}
}
return false;
}
```
在 init 函数中,我们初始化了游戏状态,并添加了贪吃蛇和食物。此外,我们还注册了键盘事件,并开始更新。
在 update 函数中,我们首先检查更新间隔是否已经到达,然后移动贪吃蛇,并检查是否碰到边界或自己。如果碰到了,则设置贪吃蛇为死亡状态,并返回。如果贪吃蛇吃到了食物,则创建一个新的身体部分,并重新生成食物。最后,重置更新间隔。
在 createFood 函数中,我们随机生成一个食物,并添加到场景中。
在 checkCollision 函数中,我们检查贪吃蛇是否碰到了边界或自己。如果碰到了,则返回 true,否则返回 false。
最后,在场景中添加 GameLayer 类的实例,即可运行贪吃蛇游戏。
阅读全文