Extra2D/examples/flappy_bird/bird.cpp

196 lines
4.3 KiB
C++
Raw Normal View History

// ============================================================================
// Bird.cpp - 小鸟类实现
// ============================================================================
#include "Bird.h"
#include "ResLoader.h"
namespace flappybird {
Bird::Bird() { setStatus(Status::Idle); }
Bird::~Bird() = default;
void Bird::onEnter() {
Node::onEnter();
if (!sprite_) {
initAnimations();
}
}
void Bird::initAnimations() {
// 随机选择小鸟颜色0-2
int colorMode = extra2d::randomInt(0, 2);
std::string prefix = "bird" + std::to_string(colorMode) + "_";
// 加载动画帧序列: 0 -> 1 -> 2 -> 1
int frameSequence[] = {0, 1, 2, 1};
for (int frameIndex : frameSequence) {
auto frameSprite =
ResLoader::getKeyFrame(prefix + std::to_string(frameIndex));
if (frameSprite) {
frames_.push_back(frameSprite);
} else {
E2D_LOG_WARN("无法加载动画帧: {}{}", prefix, frameIndex);
}
}
// 创建精灵
if (!frames_.empty()) {
sprite_ = extra2d::Sprite::create();
setCurrentFrame(0);
addChild(sprite_);
E2D_LOG_INFO("小鸟动画创建成功: 颜色={}, 帧数={}", colorMode,
frames_.size());
} else {
E2D_LOG_ERROR("小鸟动画创建失败: 没有找到任何动画帧");
}
}
void Bird::setCurrentFrame(int frameIndex) {
if (frames_.empty() || !sprite_)
return;
frameIndex = frameIndex % static_cast<int>(frames_.size());
currentFrame_ = frameIndex;
auto &frame = frames_[frameIndex];
sprite_->setTexture(frame->getTexture());
sprite_->setTextureRect(frame->getRect());
}
void Bird::updateFrameAnimation(float dt) {
if (frames_.empty() || status_ == Status::Still)
return;
frameTimer_ += dt;
float interval = frameInterval_;
if (status_ == Status::StartToFly) {
interval = 0.05f; // 2倍速度
}
while (frameTimer_ >= interval) {
frameTimer_ -= interval;
setCurrentFrame((currentFrame_ + 1) % static_cast<int>(frames_.size()));
}
}
void Bird::onUpdate(float dt) {
extra2d::Node::onUpdate(dt);
// 更新帧动画
updateFrameAnimation(dt);
// 处理闲置动画(上下浮动)
if (status_ == Status::Idle) {
idleTimer_ += dt;
idleOffset_ = std::sin(idleTimer_ * 5.0f) * 4.0f;
}
}
void Bird::onRender(extra2d::Renderer &renderer) {
// 精灵会自动渲染,这里只需要处理旋转和偏移
if (sprite_) {
sprite_->setRotation(rotation_);
// 应用闲置偏移
if (status_ == Status::Idle) {
sprite_->setPosition(extra2d::Vec2(0.0f, idleOffset_));
} else {
sprite_->setPosition(extra2d::Vec2(0.0f, 0.0f));
}
}
// 调用父类的 onRender 来渲染子节点
Node::onRender(renderer);
}
void Bird::fall(float dt) {
if (!living_)
return;
// 更新垂直位置
extra2d::Vec2 position = pos();
position.y += speed_ * dt;
setPosition(position);
// 应用重力
speed_ += gravity * dt;
// 限制顶部边界
if (position.y < 0) {
position.y = 0;
setPosition(position);
speed_ = 0;
}
// 根据速度计算旋转角度
// 上升时抬头(-15度),下降时低头(最大90度)
if (speed_ < 0) {
rotation_ = -15.0f;
} else {
rotation_ = std::min(90.0f, speed_ * 0.15f);
}
}
void Bird::jump() {
if (!living_)
return;
// 给小鸟向上的速度
speed_ = -jumpSpeed;
// 设置状态为飞行
setStatus(Status::Fly);
// 播放音效
ResLoader::playMusic(MusicType::Fly);
}
void Bird::die() {
living_ = false;
// 播放死亡音效
ResLoader::playMusic(MusicType::Hit);
}
void Bird::setStatus(Status status) {
status_ = status;
switch (status) {
case Status::Still:
// 停止所有动画
frameTimer_ = 0.0f;
break;
case Status::Idle:
// 开始闲置动画
frameInterval_ = 0.1f; // 正常速度
idleTimer_ = 0.0f;
break;
case Status::StartToFly:
// 停止闲置动画,加速翅膀扇动
idleOffset_ = 0.0f;
break;
case Status::Fly:
// 飞行状态
break;
default:
break;
}
}
extra2d::Rect Bird::boundingBox() const {
extra2d::Vec2 position = pos();
// 小鸟碰撞框大小约为 24x24
float halfSize = 12.0f;
return extra2d::Rect(position.x - halfSize, position.y - halfSize,
halfSize * 2.0f, halfSize * 2.0f);
}
} // namespace flappybird