Search code examples
cncursescurses

As, move the object per above and behind another object?


map Moon[MOON HEIGHT] object appears above const char *map World[MAP HEIGHT], because const char *map World[MAP HEIGHT] is printed before const char *mapMoon[MOON_HEIGHT].

The mapMoon object moves in ellipse.
how to make this object also pass per behind, when moving in one direction of the ellipse? To give the illusion that mapMoon hides behind mapWorld?

#include <stdio.h>
#include <math.h>
#include <curses.h>

#define MOON_HEIGHT 17
#define MOON_WIDTH 50
#define MOON_ASPECT_RATIO 2
#define MOON_RADIUS 5
#define MOON_CENTER_X (MOON_WIDTH / 2.0)
#define MOON_CENTER_Y (MOON_HEIGHT / 2.0)

#define MAP_HEIGHT 34
#define MAP_WIDTH 140
#define ASPECT_RATIO 2
#define RADIUS 17
#define CENTER_X (MAP_WIDTH / 2.0)
#define CENTER_Y (MAP_HEIGHT / 2.0)

const char *mapMoon[MOON_HEIGHT] = {
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "oooooooooooooooooooooooooooooooooooooooooooooooooo",
  "                                                  "
};

const char *mapWorld[MAP_HEIGHT] = {
  "--------------------------------------------------------------------------------------------------------------------------------------------",
  "--------------------------------------------------------------------------------------------------------------------------------------------",
  "----------------------------------+++++++--+++++++++++++++++++------------------------------------------------------------------------------",
  "----------------------+-+++++--+-+-+++++--------++++++++++++++-----------------------------+----------++++++++++++++--+-----++--------------",
  "------++++++++++++++++++++++++++++++++--++++-----++++++++++-----------------++++++++-----+++++++++++++++++++++++++++++++++++++++++++++++++++",
  "------+++++++++++++++++++++++++++++-----++++------++++-------------------++++-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-",
  "--------++-------+++++++++++++++++------++++++----------------------+----++++--++++++++++++++++++++++++++++++++++++++++++++++------++-------",
  "--------------------++++++++++++++++++-+++++++++--------------------++--++++++++++++++++++++++++++++++++++++++++++++++++++++-------+--------",
  "----------------------+++++++++++++++++++++++------------------------+++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------",
  "----------------------+++++++++++++++++++++------------------------++++---+-+++++----++++-+++++++++++++++++++++++++++++++-------------------",
  "----------------------+++++++++++++++++++--------------------------+++--------+--++++++++--+++++++++++++++++++++++++---+----+---------------",
  "-------------------------++++++++++++++----------------------------+++++++++--+----++++++++++++++++++++++++++++++++++-----------------------",
  "--------------------------++++++------+--------------------------++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------",
  "-----------------------------+++--------------------------------++++++++++++++++++++-++++++++----+++++++++++++++++--------------------------",
  "-------------------------------++-++----------------------------+++++++++++++++++++++-+++++-------++++-----+++++----------------------------",
  "------------------------------------++--------------------------+++++++++++++++++++++++++----------++-------+-++----------------------------",
  "----------------------------------------+++++++------------------++++++++++++++++++++++++---------------------------------------------------",
  "---------------------------------------+++++++++++------------------------++++++++++++++---------------------+---+++------------------------",
  "---------------------------------------++++++++++++++++-------------------++++++++++++-----------------------++--++--------++---------------",
  "---------------------------------------+++++++++++++++++-------------------++++++++++---------------------------------------++--------------",
  "----------------------------------------+++++++++++++++--------------------+++++++++++----------------------------------+++--+--------------",
  "------------------------------------------+++++++++++++--------------------+++++++++---++----------------------------++++++++++-------------",
  "-------------------------------------------+++++++++------------------------++++++++---+--------------------------+++++++++++++++-----------",
  "------------------------------------------+++++++++-------------------------++++++--------------------------------+++++++++++++++-----------",
  "------------------------------------------+++++++----------------------------+++-----------------------------------+++----+++++++-----------",
  "------------------------------------------++++--------------------------------------------------------------------------------+-------------",
  "-----------------------------------------++++-----------------------------------------------------------------------------------------------",
  "-----------------------------------------+++------------------------------------------------------------------------------------------------",
  "--------------------------------------------------------------------------------------------------------------------------------------------",
  "--------------------------------------------------------------------------------------------------------------------------------------------",
  "--------------------------------------------------------------------------------------------------------------------------------------------",
  "--------------------------------------------++-------------------------------------+-++++++++++++--+++++++++++++++++++++++++++++++++--------",
  "--------------------+++++++---++++++++++++++++-----------------+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------",
  "----------+++++++++++++++++++++++++++++++----------+----+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------"
};

int clip(int v, int max)
{
    return v < max ? v : max - 1;
}

int main()
{
    initscr();
    start_color();
    cbreak();
    noecho();
    curs_set(0);

    int maxX, maxY;
    getmaxyx(stdscr, maxY, maxX);

    float a = MOON_RADIUS * 22.0;
    float b = MOON_RADIUS * 0.5 * MOON_ASPECT_RATIO;
    float moonAngle = 0.0;
    float moonAngleIncrement = 4.0;

    float worldAngle = 0.0;
    float worldAngleIncrement = 1.0;

    init_pair(1, COLOR_WHITE, COLOR_BLACK);
    init_pair(2, COLOR_BLUE, COLOR_BLACK);
    init_pair(3, COLOR_GREEN, COLOR_BLACK);
    init_pair(4, 231, COLOR_BLACK);
    init_pair(5, 236, COLOR_BLACK);

    while (1)
    {
        erase();

        // World animation
        int worldOffset = (int)(MAP_WIDTH * worldAngle / (2.0 * M_PI));
        for (int x = 0; x < MAP_WIDTH; x++)
        {
            for (int y = 0; y < MAP_HEIGHT; y++)
            {
                float distance = sqrt(pow((x - CENTER_X) / ASPECT_RATIO, 2) + pow(y - CENTER_Y, 2));

                if (distance <= RADIUS)
                {
                    if (mapWorld[y][(x - worldOffset + MAP_WIDTH) % MAP_WIDTH] == '-')
                    {
                        attron(COLOR_PAIR(2));
                    }
                    else if (mapWorld[y][(x - worldOffset + MAP_WIDTH) % MAP_WIDTH] == '+')
                    {
                        attron(COLOR_PAIR(3));
                    }

                    // Check if the point is in the right half of the circle
                    if (x <= CENTER_X - 1)
                    {
                        // Set the color to white
                        if (mapWorld[y][(x - worldOffset + MAP_WIDTH) % MAP_WIDTH] == '+')
                        {
                            attron(COLOR_PAIR(4));
                        }
                        else if (mapWorld[y][(x - worldOffset + MAP_WIDTH) % MAP_WIDTH] == '-')
                        {
                        attron(COLOR_PAIR(5));
                    }
                }

                // Print the corresponding character
                mvprintw(y, x, "%c", mapWorld[y][(x - worldOffset + MAP_WIDTH) % MAP_WIDTH]);

                // Disable color
                attroff(COLOR_PAIR(2));
                attroff(COLOR_PAIR(3));
                attroff(COLOR_PAIR(4));
                attroff(COLOR_PAIR(5));
            }
        }
    }

    // Moon animation
    float t = moonAngle / (2.0 * M_PI);
    int moonOffsetX = (int)(a * cos(2.0 * M_PI * t) / MOON_ASPECT_RATIO);
    int moonOffsetY = (int)(b * sin(2.0 * M_PI * t));

    for (int y = 0; y < MOON_HEIGHT; y++)
    {
        for (int x = 0; x < MOON_WIDTH; x++)
        {
            float distance = sqrt(pow((x - MOON_CENTER_X) / MOON_ASPECT_RATIO, 2) + pow(y - MOON_CENTER_Y, 2));

            if (distance <= MOON_RADIUS)
            {
                if (mapMoon[y][(x + moonOffsetX + MOON_WIDTH) % MOON_WIDTH] == 'o')
                {
                    attron(COLOR_PAIR(1));
                }

                int printX = MOON_WIDTH - 1 - (x + moonOffsetX) + 44;
                int printY = y + moonOffsetY + 9;

                printX = clip(printX, maxX);
                printY = clip(printY, maxY);

                // Changed the order of printing: Moon before World
                mvprintw(printY, printX, "%c", mapMoon[y][(x + moonOffsetX + MOON_WIDTH) % MOON_WIDTH]);

                attroff(COLOR_PAIR(1));
            }
        }
    }

    refresh();
    napms(50);
    moonAngle += moonAngleIncrement * (M_PI / 180.0);
    if (moonAngle >= 2 * M_PI)
    {
        moonAngle -= 2 * M_PI;
        }
        worldAngle += worldAngleIncrement * (M_PI / 180.0);
        if (worldAngle >= 2 * M_PI)
        {
            worldAngle -= 2 * M_PI;
        }
    }

    endwin();
    return 0;
}

Solution

  • You already know how to calculate the limits of earth. Just apply same calculation for the characters forming the moon and take the distant from center of earth. Then only draw if the position is outside of earth's boundary or if it is in front of the earth:

                    distance = sqrt(pow((printX - CENTER_X) / ASPECT_RATIO, 2) + pow(printY - CENTER_Y, 2));
    
                    if ((moonOffsetY > 0) || (distance > RADIUS))
                    {
                        mvprintw(printY, printX, "%c", mapMoon[y][(x + moonOffsetX + MOON_WIDTH) % MOON_WIDTH]);
                    }
    

    I just used (moonOffsetY > 0) as indicator that the moon is in front. If you want to have it the other way around, just invert that condition or use moonAngle for that decision.