如何实现点击生成的绿色圆形随时间缓慢消失(仿MOBA游戏)
问题分析
你的代码核心问题是把动画逻辑放在了鼠标点击的单次触发里:当你点击鼠标时,for循环会在同一帧内快速执行完所有半径和透明度的更新,所有绘制操作瞬间完成,视觉上就表现为圆形一闪而过。游戏的动画需要和主渲染循环绑定,逐帧更新状态,才能实现平滑的消失效果。
解决方案
要实现这种点击生成、逐帧消失的效果,需要把每个圆形的状态(位置、大小、透明度)单独存储,然后在主循环的每一帧里更新并绘制这些圆形:
- 定义圆形状态结构体,保存每个点击生成的圆形的所有必要信息
- 维护一个列表,存储所有正在播放消失动画的圆形
- 鼠标点击时只生成新的圆形实例加入列表,不直接执行动画
- 在主循环里遍历列表,更新每个圆形的大小和透明度,移除已消失的圆形并绘制剩余的
完整示例代码
#include "raylib.h" #include <vector> // 定义单个点击圆形的状态 struct ClickCircle { float x; float y; float radius; int opacity; bool isAlive; }; // 存储所有正在播放动画的圆形 std::vector<ClickCircle> circles; void HandleMouseClick() { if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { Vector2 mousePos = GetMousePosition(); // 创建新的圆形,初始化状态 ClickCircle newCircle = { .x = mousePos.x, .y = mousePos.y, .radius = 10.0f, .opacity = 200, .isAlive = true }; circles.push_back(newCircle); } } void UpdateAndDrawCircles() { float delta = GetFrameTime(); // 遍历更新所有圆形 for (int i = 0; i < circles.size(); ) { ClickCircle& circle = circles[i]; if (!circle.isAlive) { // 移除已消失的圆形 circles.erase(circles.begin() + i); continue; } // 基于帧率更新半径和透明度(确保不同帧率下动画速度一致) circle.radius -= circle.radius / 20 * delta * 60; circle.opacity -= circle.opacity / 20 * delta * 60; // 判断是否已经消失 if (circle.opacity <= 0 || circle.radius <= 0) { circle.isAlive = false; i++; continue; } // 绘制当前状态的圆形 DrawCircle(circle.x, circle.y, circle.radius, (Color){0, 255, 0, circle.opacity}); i++; } } int main() { InitWindow(800, 600, "Click Circle Fade"); SetTargetFPS(60); while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(RAYWHITE); HandleMouseClick(); UpdateAndDrawCircles(); EndDrawing(); } CloseWindow(); return 0; }
关键说明
- 分离逻辑:把点击事件和动画更新完全分开,点击只负责创建实例,动画交给主循环逐帧处理
- 帧率无关:用
GetFrameTime()获取每帧的时间间隔,乘以60把速度统一到60帧的基准,避免不同帧率下动画速度不一致 - 状态管理:用列表维护所有活跃的圆形,及时移除已消失的实例避免内存占用
内容的提问来源于stack exchange,提问作者ubersmurf
相关产品推荐
相关产品推荐

