You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现mapMoon沿椭圆运动时隐藏在mapWorld后方的视觉效果?

解决Curses终端图形中月亮被世界地图遮挡的视觉效果方案

核心逻辑

要实现椭圆运动的月亮被世界地图遮挡的错觉,关键是按遮挡层级分阶段绘制:不再一次性绘制整个月亮,而是根据月亮当前位置与世界地图的覆盖关系,拆分月亮为「被遮挡部分」和「可见部分」,先画被遮挡的月亮片段,再画完整的世界地图,最后画可见的月亮片段。

具体修改步骤

假设你的世界地图mapWorld固定在终端某一区域(比如垂直方向占据终端下方MAP_HEIGHT行),月亮mapMoon沿椭圆轨迹穿过世界地图区域:

  1. 计算位置边界
    获取月亮当前的左上角坐标(moon_x, moon_y),结合月亮尺寸MOON_WIDTH、MOON_HEIGHT算出右下角坐标(moon_x + MOON_WIDTH - 1, moon_y + MOON_HEIGHT - 1);同时确定世界地图的覆盖范围,比如世界地图的顶部行world_top_y、底部行world_bottom_y。

  2. 拆分月亮绘制区域
    根据垂直方向的重叠情况拆分:

    • 被遮挡区域:月亮中y >= world_top_y的行(落在世界地图范围内的部分)
    • 可见区域:月亮中y < world_top_y的行(在世界地图上方的部分)
  3. 调整绘制顺序
    把原有的「先画世界→再画月亮」改为三步绘制:

    • 第一步:绘制月亮的被遮挡部分。遍历月亮落在世界地图内的行,逐行绘制mapMoon对应字符,这部分会被后续的世界地图覆盖。
    • 第二步:绘制完整的mapWorld,覆盖掉之前画的月亮被遮挡部分。
    • 第三步:绘制月亮的可见部分。遍历月亮在世界地图上方的行,逐行绘制mapMoon对应字符,这部分会显示在世界地图上层。
  4. 动态适配椭圆轨迹
    因为月亮沿椭圆运动,每帧刷新都要重新计算位置和重叠区域:比如月亮完全在世界地图下方时,只执行前两步;完全在上方时,执行后两步。

代码示例片段

// 假设已获取当前月亮坐标(moon_x, moon_y),世界地图顶部行world_top_y
int moon_bottom_y = moon_y + MOON_HEIGHT - 1;
int world_bottom_y = world_top_y + MAP_HEIGHT - 1;

// 1. 绘制月亮被遮挡的部分
if (moon_y <= world_bottom_y) {
    int start_row = (moon_y < world_top_y) ? world_top_y : moon_y;
    int end_row = (moon_bottom_y > world_bottom_y) ? world_bottom_y : moon_bottom_y;
    for (int y = start_row; y <= end_row; y++) {
        int moon_row_idx = y - moon_y;
        for (int x = moon_x; x < moon_x + MOON_WIDTH; x++) {
            int moon_col_idx = x - moon_x;
            if (mapMoon[moon_row_idx][moon_col_idx] != ' ') {
                mvaddch(y, x, mapMoon[moon_row_idx][moon_col_idx]);
            }
        }
    }
}

// 2. 绘制世界地图
for (int y = world_top_y; y <= world_bottom_y; y++) {
    int world_row_idx = y - world_top_y;
    for (int x = 0; x < MAP_WIDTH; x++) {
        mvaddch(y, x, mapWorld[world_row_idx][x]);
    }
}

// 3. 绘制月亮可见的部分
if (moon_bottom_y >= world_top_y) {
    int start_row = moon_y;
    int end_row = (moon_bottom_y < world_top_y) ? moon_bottom_y : world_top_y - 1;
    for (int y = start_row; y <= end_row; y++) {
        int moon_row_idx = y - moon_y;
        for (int x = moon_x; x < moon_x + MOON_WIDTH; x++) {
            int moon_col_idx = x - moon_x;
            if (mapMoon[moon_row_idx][moon_col_idx] != ' ') {
                mvaddch(y, x, mapMoon[moon_row_idx][moon_col_idx]);
            }
        }
    }
}

额外注意事项

  • 如果世界地图有镂空区域(空白处不遮挡月亮),绘制被遮挡部分时,要先检查mapWorld对应位置是否为非空白,再决定是否绘制月亮的该字符。
  • 每帧绘制前用clear()或局部刷新清除上一帧内容,避免残影。

内容的提问来源于stack exchange,提问作者Exponecial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:17:31