-
Notifications
You must be signed in to change notification settings - Fork 55
Add light pollution visual demo (graph_light_pollution.cpp) #359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 总体概述该PR引入了一个新的C++图形演示文件,实现了动态"光污染"视觉效果,包含圆形、矩形、星形和线条四种原始元素的初始化、更新与渲染逻辑。 变更内容
预期代码审查工作量🎯 3 (中等) | ⏱️ ~20 分钟 庆祝诗
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
Comment |
Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com>
Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com>
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
1 similar comment
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a new graphical demo graph_light_pollution.cpp that showcases "光污染" (light pollution) effects through overwhelming visual stimulation with bright, rapidly-changing colors and multiple animated elements. The demo follows project conventions by using the graph_ prefix for rendering demonstrations and integrates automatically into the CMake build system.
Key Changes:
- Implements 4 types of animated elements: pulsating circles with HSV color cycling, moving rectangles with rotation-based colors, blinking stars with cross-shaped flashes, and animated lines with color transitions
- Uses 60 FPS delta-time animation with HSV color space for vibrant effects, alpha blending for translucency, and anti-aliasing for smooth rendering
- Includes buffer-safe string handling with
snprintfand pre-calculated values for performance optimization
| float vx, vy; // 速度 | ||
| float rotation; // 旋转角度 | ||
| float rot_speed; // 旋转速度 | ||
| float hue; // 色相 |
Copilot
AI
Jan 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The FlashRect struct includes a hue field (line 40) that is initialized (line 97) but never used. The color is instead calculated from the rotation angle (line 233). Consider either using the hue field for color calculation (and updating it over time like in UpdateCircles) or removing the unused hue field to reduce memory usage and clarify the code's intent.
| float hue; // 色相 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (3)
demo/graph_light_pollution.cpp (3)
133-134: 建议:提取帧率归一化常量代码中多处使用
dt * 60.0f进行帧率归一化(将增量转换为每秒单位)。建议提取为命名常量以提高可维护性。🔎 建议的改进
+#define FRAME_RATE_NORM 60.0f // 帧率归一化因子 + // 更新圆形 void UpdateCircles(float dt) { for (int i = 0; i < MAX_CIRCLES; i++) { // 更新位置 - circles[i].x += circles[i].vx * dt * 60.0f; - circles[i].y += circles[i].vy * dt * 60.0f; + circles[i].x += circles[i].vx * dt * FRAME_RATE_NORM; + circles[i].y += circles[i].vy * dt * FRAME_RATE_NORM;对
UpdateRects中的类似代码应用相同的改动。Also applies to: 157-158, 171-171
313-313: 变量名与类型冲突局部变量
fps与include/ege/fps.h中定义的fps类同名。虽然在当前代码中未引起问题(因为未包含该头文件),但这可能导致混淆。建议使用更具描述性的名称。🔎 建议的改进
- int fps = 60; + int target_fps = 60; float time = 0.0f; - float dt = 1.0f / fps; + float dt = 1.0f / target_fps; // 启用抗锯齿 ege_enable_aa(true); // 显示提示信息 bool show_hint = true; float hint_time = 3.0f; // 主循环 - for (; is_run() && !kbhit(); delay_fps(fps)) { + for (; is_run() && !kbhit(); delay_fps(target_fps)) {
215-219: 建议:提取颜色转换辅助函数代码中多处使用相同的模式:调用
HSVtoRGB()后用EGEGET_R/G/B提取分量,再用EGERGBA重新构造带透明度的颜色。可以提取为辅助函数以减少重复。🔎 建议的改进
+// 辅助函数:HSV转RGBA +inline color_t HSVtoRGBA(float h, float s, float v, int alpha) { + color_t rgb = HSVtoRGB(h, s, v); + return EGERGBA(EGEGET_R(rgb), EGEGET_G(rgb), EGEGET_B(rgb), alpha); +} + // 绘制圆形 void DrawCircles() { for (int i = 0; i < MAX_CIRCLES; i++) { // 计算脉动半径 float pulse_factor = (float)(sin(circles[i].pulse) * 0.3 + 1.0); float current_radius = circles[i].radius * pulse_factor; - // 转换HSV到RGB - color_t color = HSVtoRGB(circles[i].hue, 1.0f, 1.0f); - // 设置透明色 - setfillcolor(EGERGBA(EGEGET_R(color), EGEGET_G(color), EGEGET_B(color), circles[i].alpha)); - setcolor(EGERGBA(EGEGET_R(color), EGEGET_G(color), EGEGET_B(color), circles[i].alpha + 50)); + setfillcolor(HSVtoRGBA(circles[i].hue, 1.0f, 1.0f, circles[i].alpha)); + setcolor(HSVtoRGBA(circles[i].hue, 1.0f, 1.0f, circles[i].alpha + 50));类似的改进可应用于
DrawRects和DrawLines。Also applies to: 233-236, 272-273
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
demo/graph_light_pollution.cpp
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{h,hpp,cpp,cc,cxx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
All implementations must be in
egenamespace, with public API in global namespace
Files:
demo/graph_light_pollution.cpp
🧬 Code graph analysis (1)
demo/graph_light_pollution.cpp (1)
include/ege/fps.h (1)
fps(9-52)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Agent
- GitHub Check: MSYS2 Latest - Debug
- GitHub Check: MSYS2 Latest - Release
| /** | ||
| * @file graph_light_pollution.cpp | ||
| * @brief 光污染效果演示 - 展示眼花缭乱的炫目效果 | ||
| * | ||
| * 这个演示程序展示"光污染"效果,通过快速变化的颜色、闪烁的图形、 | ||
| * 重叠的半透明元素等方式,创造出令人眼花缭乱的视觉效果。 | ||
| * | ||
| * 按任意键退出 | ||
| */ | ||
|
|
||
| #include <graphics.h> | ||
| #include <math.h> | ||
| #include <stdlib.h> | ||
| #include <stdio.h> | ||
|
|
||
| #define MAX_CIRCLES 30 // 圆形数量 | ||
| #define MAX_RECTS 20 // 矩形数量 | ||
| #define MAX_STARS 50 // 星星闪烁效果数量 | ||
| #define MAX_LINES 40 // 线条数量 | ||
|
|
||
| // 闪烁圆形结构 | ||
| struct FlashCircle { | ||
| float x, y; // 位置 | ||
| float radius; // 半径 | ||
| float vx, vy; // 速度 | ||
| float pulse; // 脉动相位 | ||
| float pulse_speed; // 脉动速度 | ||
| float hue; // 色相 | ||
| float hue_speed; // 色相变化速度 | ||
| int alpha; // 透明度 | ||
| }; | ||
|
|
||
| // 闪烁矩形结构 | ||
| struct FlashRect { | ||
| float x, y; // 位置 | ||
| float w, h; // 宽高 | ||
| float vx, vy; // 速度 | ||
| float rotation; // 旋转角度 | ||
| float rot_speed; // 旋转速度 | ||
| float hue; // 色相 | ||
| int alpha; // 透明度 | ||
| }; | ||
|
|
||
| // 闪烁星星结构 | ||
| struct FlashStar { | ||
| int x, y; // 位置 | ||
| float brightness; // 亮度 | ||
| float blink_speed; // 闪烁速度 | ||
| float phase; // 相位 | ||
| int size; // 大小 | ||
| float hue; // 色相(预计算) | ||
| }; | ||
|
|
||
| // 彩色线条结构 | ||
| struct ColorLine { | ||
| int x1, y1, x2, y2; // 起止点 | ||
| float hue; // 色相 | ||
| float hue_speed; // 色相变化速度 | ||
| int alpha; // 透明度 | ||
| int width; // 线宽 | ||
| }; | ||
|
|
||
| FlashCircle circles[MAX_CIRCLES]; | ||
| FlashRect rects[MAX_RECTS]; | ||
| FlashStar stars[MAX_STARS]; | ||
| ColorLine lines[MAX_LINES]; | ||
|
|
||
| int screen_w, screen_h; | ||
|
|
||
| // 初始化圆形 | ||
| void InitCircles() { | ||
| for (int i = 0; i < MAX_CIRCLES; i++) { | ||
| circles[i].x = (float)(random(screen_w)); | ||
| circles[i].y = (float)(random(screen_h)); | ||
| circles[i].radius = (float)(random(30) + 20); | ||
| circles[i].vx = (float)(random(200) - 100) / 50.0f; | ||
| circles[i].vy = (float)(random(200) - 100) / 50.0f; | ||
| circles[i].pulse = (float)(random(628)) / 100.0f; | ||
| circles[i].pulse_speed = (float)(random(50) + 10) / 100.0f; | ||
| circles[i].hue = (float)(random(360)); | ||
| circles[i].hue_speed = (float)(random(100) + 50) / 10.0f; | ||
| circles[i].alpha = random(100) + 100; | ||
| } | ||
| } | ||
|
|
||
| // 初始化矩形 | ||
| void InitRects() { | ||
| for (int i = 0; i < MAX_RECTS; i++) { | ||
| rects[i].x = (float)(random(screen_w)); | ||
| rects[i].y = (float)(random(screen_h)); | ||
| rects[i].w = (float)(random(80) + 40); | ||
| rects[i].h = (float)(random(80) + 40); | ||
| rects[i].vx = (float)(random(200) - 100) / 60.0f; | ||
| rects[i].vy = (float)(random(200) - 100) / 60.0f; | ||
| rects[i].rotation = (float)(random(360)); | ||
| rects[i].rot_speed = (float)(random(100) - 50) / 50.0f; | ||
| rects[i].hue = (float)(random(360)); | ||
| rects[i].alpha = random(80) + 80; | ||
| } | ||
| } | ||
|
|
||
| // 初始化星星 | ||
| void InitStars() { | ||
| for (int i = 0; i < MAX_STARS; i++) { | ||
| stars[i].x = random(screen_w); | ||
| stars[i].y = random(screen_h); | ||
| stars[i].brightness = 0.0f; | ||
| stars[i].blink_speed = (float)(random(50) + 20) / 100.0f; | ||
| stars[i].phase = (float)(random(628)) / 100.0f; | ||
| stars[i].size = random(3) + 2; | ||
| stars[i].hue = (float)(random(360)); // 预计算色相 | ||
| } | ||
| } | ||
|
|
||
| // 初始化线条 | ||
| void InitLines() { | ||
| for (int i = 0; i < MAX_LINES; i++) { | ||
| lines[i].x1 = random(screen_w); | ||
| lines[i].y1 = random(screen_h); | ||
| lines[i].x2 = random(screen_w); | ||
| lines[i].y2 = random(screen_h); | ||
| lines[i].hue = (float)(random(360)); | ||
| lines[i].hue_speed = (float)(random(100) + 30) / 10.0f; | ||
| lines[i].alpha = random(150) + 80; | ||
| lines[i].width = random(3) + 1; // 预计算线宽 | ||
| } | ||
| } | ||
|
|
||
| // 更新圆形 | ||
| void UpdateCircles(float dt) { | ||
| for (int i = 0; i < MAX_CIRCLES; i++) { | ||
| // 更新位置 | ||
| circles[i].x += circles[i].vx * dt * 60.0f; | ||
| circles[i].y += circles[i].vy * dt * 60.0f; | ||
|
|
||
| // 边界反弹 | ||
| if (circles[i].x < 0 || circles[i].x > screen_w) { | ||
| circles[i].vx = -circles[i].vx; | ||
| circles[i].x = circles[i].x < 0 ? 0.0f : (float)screen_w; | ||
| } | ||
| if (circles[i].y < 0 || circles[i].y > screen_h) { | ||
| circles[i].vy = -circles[i].vy; | ||
| circles[i].y = circles[i].y < 0 ? 0.0f : (float)screen_h; | ||
| } | ||
|
|
||
| // 更新脉动和色相 | ||
| circles[i].pulse += circles[i].pulse_speed * dt; | ||
| circles[i].hue += circles[i].hue_speed * dt; | ||
| if (circles[i].hue >= 360.0f) circles[i].hue -= 360.0f; | ||
| } | ||
| } | ||
|
|
||
| // 更新矩形 | ||
| void UpdateRects(float dt) { | ||
| for (int i = 0; i < MAX_RECTS; i++) { | ||
| // 更新位置 | ||
| rects[i].x += rects[i].vx * dt * 60.0f; | ||
| rects[i].y += rects[i].vy * dt * 60.0f; | ||
|
|
||
| // 边界反弹 | ||
| if (rects[i].x < 0 || rects[i].x > screen_w) { | ||
| rects[i].vx = -rects[i].vx; | ||
| rects[i].x = rects[i].x < 0 ? 0.0f : (float)screen_w; | ||
| } | ||
| if (rects[i].y < 0 || rects[i].y > screen_h) { | ||
| rects[i].vy = -rects[i].vy; | ||
| rects[i].y = rects[i].y < 0 ? 0.0f : (float)screen_h; | ||
| } | ||
|
|
||
| // 更新旋转 | ||
| rects[i].rotation += rects[i].rot_speed * dt * 60.0f; | ||
| if (rects[i].rotation > 360.0f) rects[i].rotation -= 360.0f; | ||
| if (rects[i].rotation < 0.0f) rects[i].rotation += 360.0f; | ||
| } | ||
| } | ||
|
|
||
| // 更新星星 | ||
| void UpdateStars(float dt) { | ||
| for (int i = 0; i < MAX_STARS; i++) { | ||
| stars[i].phase += stars[i].blink_speed * dt; | ||
| stars[i].brightness = (float)((sin(stars[i].phase) + 1.0) * 0.5); | ||
|
|
||
| // 偶尔改变色相以增加变化 | ||
| if (random(1000) < 5) { | ||
| stars[i].hue = (float)(random(360)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // 更新线条 | ||
| void UpdateLines(float dt) { | ||
| for (int i = 0; i < MAX_LINES; i++) { | ||
| lines[i].hue += lines[i].hue_speed * dt; | ||
| if (lines[i].hue >= 360.0f) lines[i].hue -= 360.0f; | ||
|
|
||
| // 偶尔重新生成线条位置和线宽 | ||
| if (random(1000) < 10) { | ||
| lines[i].x1 = random(screen_w); | ||
| lines[i].y1 = random(screen_h); | ||
| lines[i].x2 = random(screen_w); | ||
| lines[i].y2 = random(screen_h); | ||
| lines[i].width = random(3) + 1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // 绘制圆形 | ||
| void DrawCircles() { | ||
| for (int i = 0; i < MAX_CIRCLES; i++) { | ||
| // 计算脉动半径 | ||
| float pulse_factor = (float)(sin(circles[i].pulse) * 0.3 + 1.0); | ||
| float current_radius = circles[i].radius * pulse_factor; | ||
|
|
||
| // 转换HSV到RGB | ||
| color_t color = HSVtoRGB(circles[i].hue, 1.0f, 1.0f); | ||
|
|
||
| // 设置透明色 | ||
| setfillcolor(EGERGBA(EGEGET_R(color), EGEGET_G(color), EGEGET_B(color), circles[i].alpha)); | ||
| setcolor(EGERGBA(EGEGET_R(color), EGEGET_G(color), EGEGET_B(color), circles[i].alpha + 50)); | ||
|
|
||
| // 绘制圆形 | ||
| ege_fillellipse((int)(circles[i].x - current_radius), | ||
| (int)(circles[i].y - current_radius), | ||
| (int)(current_radius * 2), | ||
| (int)(current_radius * 2)); | ||
| } | ||
| } | ||
|
|
||
| // 绘制矩形 | ||
| void DrawRects() { | ||
| for (int i = 0; i < MAX_RECTS; i++) { | ||
| // 转换HSV到RGB,使用高饱和度 | ||
| color_t color = HSVtoRGB((float)((int)(rects[i].rotation * 2) % 360), 1.0f, 1.0f); | ||
|
|
||
| // 设置透明色 | ||
| setfillcolor(EGERGBA(EGEGET_R(color), EGEGET_G(color), EGEGET_B(color), rects[i].alpha)); | ||
|
|
||
| // 绘制旋转矩形(简化版,使用填充矩形) | ||
| ege_fillrect((int)(rects[i].x - rects[i].w / 2), | ||
| (int)(rects[i].y - rects[i].h / 2), | ||
| (int)(rects[i].w), | ||
| (int)(rects[i].h)); | ||
| } | ||
| } | ||
|
|
||
| // 绘制星星 | ||
| void DrawStars() { | ||
| for (int i = 0; i < MAX_STARS; i++) { | ||
| // 根据亮度和预计算的色相生成颜色 | ||
| color_t color = HSVtoRGB(stars[i].hue, 1.0f, stars[i].brightness); | ||
|
|
||
| setcolor(EGERGB(EGEGET_R(color), EGEGET_G(color), EGEGET_B(color))); | ||
| setfillcolor(EGERGB(EGEGET_R(color), EGEGET_G(color), EGEGET_B(color))); | ||
|
|
||
| // 绘制星星(小圆形或十字) | ||
| if (stars[i].brightness > 0.5f) { | ||
| ege_fillellipse(stars[i].x - stars[i].size / 2, | ||
| stars[i].y - stars[i].size / 2, | ||
| stars[i].size, stars[i].size); | ||
| // 添加十字闪光效果 | ||
| line(stars[i].x - stars[i].size * 2, stars[i].y, | ||
| stars[i].x + stars[i].size * 2, stars[i].y); | ||
| line(stars[i].x, stars[i].y - stars[i].size * 2, | ||
| stars[i].x, stars[i].y + stars[i].size * 2); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // 绘制线条 | ||
| void DrawLines() { | ||
| for (int i = 0; i < MAX_LINES; i++) { | ||
| color_t color = HSVtoRGB(lines[i].hue, 1.0f, 1.0f); | ||
| setcolor(EGERGBA(EGEGET_R(color), EGEGET_G(color), EGEGET_B(color), lines[i].alpha)); | ||
|
|
||
| setlinewidth(lines[i].width); | ||
| line(lines[i].x1, lines[i].y1, lines[i].x2, lines[i].y2); | ||
| } | ||
| } | ||
|
|
||
| // 绘制闪烁背景 | ||
| void DrawFlashingBackground(float time) { | ||
| // 使用正弦波产生闪烁效果 | ||
| float flash = (float)((sin(time * 3.0) + 1.0) * 0.5); | ||
| int bg_brightness = (int)(flash * 30); | ||
|
|
||
| // 随机改变背景色相 | ||
| float bg_hue = (float)((int)(time * 50) % 360); | ||
| color_t bg_color = HSVtoRGB(bg_hue, 0.3f, (float)bg_brightness / 255.0f); | ||
|
|
||
| setbkcolor(bg_color); | ||
| cleardevice(); | ||
| } | ||
|
|
||
| int main() { | ||
| // 初始化图形窗口 | ||
| setinitmode(INIT_ANIMATION); | ||
| initgraph(800, 600); | ||
| randomize(); | ||
|
|
||
| screen_w = getwidth(); | ||
| screen_h = getheight(); | ||
|
|
||
| // 初始化所有元素 | ||
| InitCircles(); | ||
| InitRects(); | ||
| InitStars(); | ||
| InitLines(); | ||
|
|
||
| // 设置字体 | ||
| setfont(16, 0, "宋体"); | ||
| setcolor(WHITE); | ||
|
|
||
| int fps = 60; | ||
| float time = 0.0f; | ||
| float dt = 1.0f / fps; | ||
|
|
||
| // 启用抗锯齿 | ||
| ege_enable_aa(true); | ||
|
|
||
| // 显示提示信息 | ||
| bool show_hint = true; | ||
| float hint_time = 3.0f; | ||
|
|
||
| // 主循环 | ||
| for (; is_run() && !kbhit(); delay_fps(fps)) { | ||
| time += dt; | ||
|
|
||
| // 绘制闪烁背景 | ||
| DrawFlashingBackground(time); | ||
|
|
||
| // 更新所有元素 | ||
| UpdateCircles(dt); | ||
| UpdateRects(dt); | ||
| UpdateStars(dt); | ||
| UpdateLines(dt); | ||
|
|
||
| // 绘制所有元素 | ||
| DrawLines(); | ||
| DrawRects(); | ||
| DrawCircles(); | ||
| DrawStars(); | ||
|
|
||
| // 显示提示信息(前3秒) | ||
| if (show_hint && time < hint_time) { | ||
| float alpha = 1.0f; | ||
| if (time > hint_time - 1.0f) { | ||
| alpha = hint_time - time; | ||
| } | ||
| int text_alpha = (int)(alpha * 200); | ||
|
|
||
| setcolor(EGERGBA(255, 255, 255, text_alpha)); | ||
| outtextxy(10, 10, "光污染效果演示 - 按任意键退出"); | ||
|
|
||
| char fps_str[64]; | ||
| snprintf(fps_str, sizeof(fps_str), "FPS: %.1f", getfps()); | ||
| outtextxy(10, 30, fps_str); | ||
| } else { | ||
| show_hint = false; | ||
| } | ||
| } | ||
|
|
||
| // 清除键盘缓冲 | ||
| while (kbhit()) getch(); | ||
|
|
||
| closegraph(); | ||
| return 0; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
严重问题:违反命名空间编码规范
根据编码规范要求:"所有实现必须在 ege 命名空间中,公共 API 在全局命名空间中"。当前代码中的所有结构体、函数和变量都直接定义在全局命名空间中,未使用 ege 命名空间。
建议将内部实现(结构体、初始化/更新/绘制函数、全局变量等)放入匿名命名空间或 ege 命名空间中。
Based on coding guidelines.
🔎 建议的修复方案
将内部实现封装在匿名命名空间中:
#include <graphics.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
+namespace {
+
#define MAX_CIRCLES 30 // 圆形数量
#define MAX_RECTS 20 // 矩形数量
#define MAX_STARS 50 // 星星闪烁效果数量
#define MAX_LINES 40 // 线条数量
// 闪烁圆形结构
struct FlashCircle {
// ...
};
// ... 其他结构体、全局变量和内部函数 ...
+} // anonymous namespace
+
int main() {
// ...
}🤖 Prompt for AI Agents
demo/graph_light_pollution.cpp lines 1-367: All structs, globals and helper
functions are currently in the global namespace which violates the guideline
that implementations must live in the ege namespace (public API may remain
global). Move all internal symbols — FlashCircle/FlashRect/FlashStar/ColorLine,
the arrays (circles, rects, stars, lines), screen_w/screen_h, and all
Init*/Update*/Draw*/DrawFlashingBackground and any other non-public helpers —
into namespace ege (or an anonymous namespace inside ege); leave main() in the
global namespace. After moving them, update calls in main to qualify those
functions/variables with ege:: (or add a short using-declaration inside main) so
code compiles and public API (main) stays global.
demo/graph_light_pollution.cpp
Outdated
| if (circles[i].x < 0 || circles[i].x > screen_w) { | ||
| circles[i].vx = -circles[i].vx; | ||
| circles[i].x = circles[i].x < 0 ? 0.0f : (float)screen_w; | ||
| } | ||
| if (circles[i].y < 0 || circles[i].y > screen_h) { | ||
| circles[i].vy = -circles[i].vy; | ||
| circles[i].y = circles[i].y < 0 ? 0.0f : (float)screen_h; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
边界碰撞检测未考虑圆形半径
当前的边界检测逻辑仅检查圆心位置,未考虑圆形的半径。这会导致圆形在屏幕边缘被裁剪,而不是在完全可见的范围内反弹。
🔎 建议的修复
// 边界反弹
- if (circles[i].x < 0 || circles[i].x > screen_w) {
+ float max_radius = circles[i].radius * 1.3f; // 考虑脉动因子
+ if (circles[i].x - max_radius < 0 || circles[i].x + max_radius > screen_w) {
circles[i].vx = -circles[i].vx;
- circles[i].x = circles[i].x < 0 ? 0.0f : (float)screen_w;
+ circles[i].x = (circles[i].x < screen_w / 2) ? max_radius : (screen_w - max_radius);
}
- if (circles[i].y < 0 || circles[i].y > screen_h) {
+ if (circles[i].y - max_radius < 0 || circles[i].y + max_radius > screen_h) {
circles[i].vy = -circles[i].vy;
- circles[i].y = circles[i].y < 0 ? 0.0f : (float)screen_h;
+ circles[i].y = (circles[i].y < screen_h / 2) ? max_radius : (screen_h - max_radius);
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In demo/graph_light_pollution.cpp around lines 137 to 144, the boundary
collision checks use the circle center only and ignore each circle's radius,
causing circles to clip at the screen edge; update the checks to compare
circles[i].x and .y against circles[i].r and (screen_w - circles[i].r)/(screen_h
- circles[i].r) respectively, invert the velocity component as before, and clamp
the position to circles[i].r or (screen_bound - circles[i].r) so the entire
circle stays onscreen when bouncing.
demo/graph_light_pollution.cpp
Outdated
| if (rects[i].x < 0 || rects[i].x > screen_w) { | ||
| rects[i].vx = -rects[i].vx; | ||
| rects[i].x = rects[i].x < 0 ? 0.0f : (float)screen_w; | ||
| } | ||
| if (rects[i].y < 0 || rects[i].y > screen_h) { | ||
| rects[i].vy = -rects[i].vy; | ||
| rects[i].y = rects[i].y < 0 ? 0.0f : (float)screen_h; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
边界碰撞检测未考虑矩形尺寸
与圆形类似,矩形的边界检测只检查中心点位置,未考虑矩形的宽度和高度(从绘制代码第 239 行可见,x/y 是中心点),这会导致矩形边缘被裁剪。
🔎 建议的修复
// 边界反弹
- if (rects[i].x < 0 || rects[i].x > screen_w) {
+ float half_w = rects[i].w / 2.0f;
+ if (rects[i].x - half_w < 0 || rects[i].x + half_w > screen_w) {
rects[i].vx = -rects[i].vx;
- rects[i].x = rects[i].x < 0 ? 0.0f : (float)screen_w;
+ rects[i].x = (rects[i].x < screen_w / 2) ? half_w : (screen_w - half_w);
}
- if (rects[i].y < 0 || rects[i].y > screen_h) {
+ float half_h = rects[i].h / 2.0f;
+ if (rects[i].y - half_h < 0 || rects[i].y + half_h > screen_h) {
rects[i].vy = -rects[i].vy;
- rects[i].y = rects[i].y < 0 ? 0.0f : (float)screen_h;
+ rects[i].y = (rects[i].y < screen_h / 2) ? half_h : (screen_h - half_h);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (rects[i].x < 0 || rects[i].x > screen_w) { | |
| rects[i].vx = -rects[i].vx; | |
| rects[i].x = rects[i].x < 0 ? 0.0f : (float)screen_w; | |
| } | |
| if (rects[i].y < 0 || rects[i].y > screen_h) { | |
| rects[i].vy = -rects[i].vy; | |
| rects[i].y = rects[i].y < 0 ? 0.0f : (float)screen_h; | |
| } | |
| float half_w = rects[i].w / 2.0f; | |
| if (rects[i].x - half_w < 0 || rects[i].x + half_w > screen_w) { | |
| rects[i].vx = -rects[i].vx; | |
| rects[i].x = (rects[i].x < screen_w / 2) ? half_w : (screen_w - half_w); | |
| } | |
| float half_h = rects[i].h / 2.0f; | |
| if (rects[i].y - half_h < 0 || rects[i].y + half_h > screen_h) { | |
| rects[i].vy = -rects[i].vy; | |
| rects[i].y = (rects[i].y < screen_h / 2) ? half_h : (screen_h - half_h); | |
| } |
🤖 Prompt for AI Agents
In demo/graph_light_pollution.cpp around lines 161-168, the collision checks use
the rectangle center only and ignore rectangle width/height, causing edges to be
clipped; change the checks to account for half the rectangle width and height
(halfW = rects[i].w/2, halfH = rects[i].h/2), test x against [halfW, screen_w -
halfW] and y against [halfH, screen_h - halfH], flip vx/vy when a boundary is
hit, and clamp x/y to those corrected limits so the rectangle edge — not its
center — stays within the screen.
demo/graph_light_pollution.cpp
Outdated
| void DrawRects() { | ||
| for (int i = 0; i < MAX_RECTS; i++) { | ||
| // 转换HSV到RGB,使用高饱和度 | ||
| color_t color = HSVtoRGB((float)((int)(rects[i].rotation * 2) % 360), 1.0f, 1.0f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
矩形颜色使用旋转角度而非 hue 字段
第 233 行使用 rotation * 2 计算颜色,但 FlashRect 结构体的 hue 字段(第 40 行定义,第 97 行初始化)从未被使用。这与其他元素(圆形、星星、线条)使用独立 hue 字段的设计不一致。
建议统一设计:要么使用 hue 字段并在 UpdateRects 中更新它,要么移除未使用的 hue 字段。
🔎 建议的修复方案(使用 hue 字段)
在 UpdateRects 中添加色相更新:
void UpdateRects(float dt) {
for (int i = 0; i < MAX_RECTS; i++) {
// 更新位置
rects[i].x += rects[i].vx * dt * 60.0f;
rects[i].y += rects[i].vy * dt * 60.0f;
// ... 边界反弹代码 ...
// 更新旋转
rects[i].rotation += rects[i].rot_speed * dt * 60.0f;
if (rects[i].rotation > 360.0f) rects[i].rotation -= 360.0f;
if (rects[i].rotation < 0.0f) rects[i].rotation += 360.0f;
+
+ // 更新色相(与旋转关联或独立)
+ rects[i].hue += rects[i].rot_speed * 30.0f * dt;
+ if (rects[i].hue >= 360.0f) rects[i].hue -= 360.0f;
}
}在 DrawRects 中使用 hue:
- color_t color = HSVtoRGB((float)((int)(rects[i].rotation * 2) % 360), 1.0f, 1.0f);
+ color_t color = HSVtoRGB(rects[i].hue, 1.0f, 1.0f);Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In demo/graph_light_pollution.cpp around line 233 (FlashRect.hue defined at
~line 40 and initialized at ~line 97), the code computes rect color from
rotation*2 instead of using the struct's hue field; either remove the unused hue
field or wire it up. To fix, update UpdateRects to set rects[i].hue each frame
(e.g., derive from rotation or assign a wrapped 0–360 float) and change the
DrawRects line at 233 to call HSVtoRGB(rects[i].hue, 1.0f, 1.0f) (ensure hue
range/type matches HSVtoRGB's expectation).
…asks - Double all element counts (circles, rects, stars, lines) - Add new visual effects: high-speed particles, spiral circles, random flashes - Double movement and rotation speeds for more intense effects - Enhance strobe background with 20% white flashing - Add warning overlay for intense flashing content - Implement particle system with 200 fast-moving particles - Add radial gradient flash effects - Increase color change speed significantly - Add high-width colored lines with rapid changes - Enhance star flashing with larger cross effects - Add missing VSCode launch tasks for Light Pollution demo (Debug and Release)
Adds a graphical demo showcasing "光污染" (light pollution) effects - overwhelming visual stimulation from excessive bright, rapidly-changing colors.
Implementation
Technical Details
snprintf)Example Usage
Follows project conventions:
graph_prefix for rendering demos, automatically integrated into CMake build system. Press any key to exit.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
esm.ubuntu.com/usr/lib/apt/methods/https /usr/lib/apt/methods/https(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.
Summary by CodeRabbit
新增功能
✏️ Tip: You can customize this high-level summary in your review settings.