Problem while assigning the cell with mouse position

57 views Asked by At

I am trying to create Conway's game of life in C using raylab. I have made the manual version which works fine which is below but when I try to implement the version in which the user clicks the cell and when clicked space button the simulation starts, it fails.

MANUAL WORKING VERSION

#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "raylib.h"
#include "raymath.h"

int main()
{
    int mat[20][20] =
        {
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int buffer[20][20];
    int up, down, left, right;
    int life;
    int k, i, j;
    int COLS = 20;
    int ROWS = 20;

    int screenWidth = 600;
    int screenHeight = 600;
    int cellWidth = screenWidth / COLS;
    int cellHeight = screenHeight / ROWS;

    SetTargetFPS(2);
    InitWindow(screenWidth, screenHeight, "trial render");
    while (!WindowShouldClose())
    {
        BeginDrawing();

        for (i = 0; i < 20; i++)
        {
            for (j = 0; j < 20; j++)
            {
                buffer[i][j] = 0;
            }
        }
        // default temp mat
        for (i = 0; i < 20; i++)
        {
            for (j = 0; j < 20; j++)
            {
                buffer[i][j] = 0;
            }
        }

        for (k = 0; k < 4; k++)
        {
            // sleep(1);
            //  system("@cls||clear");

            ClearBackground(WHITE);

            for (i = 0; i < 20; i++)
            {
                for (j = 0; j < 20; j++)
                {
                    right = (j + 1) % 20; //   19->0 2

                    left = ((j - 1) + 20) % 20; // 0->19 1->20
                    up = ((i - 1) + 20) % 20;   // 0->19 1->20
                    down = (i + 1) % 20;        // 20-->1 19-->0
                    // add 8 dir
                    life = mat[down][j] + mat[i][left] + mat[up][left] + mat[up][j] + mat[up][right] + mat[i][right] + mat[down][right] + mat[down][left];
                    if (mat[i][j] == 1 && (life < 2 || life > 3))
                    {
                        buffer[i][j] = 0;
                    }
                    else if (mat[i][j] == 1 && (life == 2 || life == 3))
                    {
                        buffer[i][j] = 1;
                    }
                    else if (mat[i][j] == 0 && life == 3)
                    {
                        buffer[i][j] = 1;
                    }
                }
            }
            for (i = 0; i < 20; i++)
            {
                for (j = 0; j < 20; j++)
                {
                    mat[i][j] = buffer[i][j];
                }
            }

            for (i = 0; i < 20; i++)
            {
                for (j = 0; j < 20; j++)
                {
                    if (mat[i][j] == 0)
                    {
                        DrawRectangleLines(i * cellWidth, j * cellHeight, cellWidth, cellHeight, WHITE);
                    }
                    else
                    {
                        DrawRectangle(i * cellWidth, j * cellHeight, cellWidth, cellHeight, BLACK);
                    }
                    DrawRectangleLines(i * cellWidth, j * cellHeight, cellWidth, cellHeight, GRAY);
                }
            }

            EndDrawing();
        }
    }
    CloseWindow();
    return 0;
}

NOT WORKING HELP

#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "raylib.h"
#include "raymath.h"

int main()
{
    int mat[20][20];
    int buffer[20][20];
    int up, down, left, right;
    int life;
    int k, i, j;
    int COLS = 20;
    int ROWS = 20;

    int screenWidth = 600;
    int screenHeight = 600;
    int cellWidth = screenWidth / COLS;
    int cellHeight = screenHeight / ROWS;

    SetTargetFPS(2);
    InitWindow(screenWidth, screenHeight, "trial render");
    while (!WindowShouldClose())
    {
        for (i = 0; i < 20; i++)
        {
            for (j = 0; j < 20; j++)
            {
                mat[i][j] = 0;
            }
        }

        for (i = 0; i < 20; i++)
        {
            for (j = 0; j < 20; j++)
            {
                buffer[i][j] = 0;
            }
        }
        // alive cell on the mouse click------------------------------------------------------
        if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
        {
            Vector2 mPos = GetMousePosition();
            int x = mPos.x;
            int y = mPos.y;
            mat[x][y] = 1;
        }
        // default temp mat
        for (i = 0; i < 20; i++)
        {
            for (j = 0; j < 20; j++)
            {
                buffer[i][j] = 0;
            }
        }
        //---------------------------------------------------------------------
        // start
        if (IsKeyPressed(KEY_SPACE))
        {
            for (k = 0; k < 4; k++)
            {
                ClearBackground(WHITE);

                for (i = 0; i < 20; i++)
                {
                    for (j = 0; j < 20; j++)
                    {
                        right = (j + 1) % 20; //   19->0 2

                        left = ((j - 1) + 20) % 20; // 0->19 1->20
                        up = ((i - 1) + 20) % 20;   // 0->19 1->20
                        down = (i + 1) % 20;        // 20-->1 19-->0
                        // add 8 dir
                        life = mat[down][j] + mat[i][left] + mat[up][left] + mat[up][j] + mat[up][right] + mat[i][right] + mat[down][right] + mat[down][left];
                        if (mat[i][j] == 1 && (life < 2 || life > 3))
                        {
                            buffer[i][j] = 0;
                        }
                        else if (mat[i][j] == 1 && (life == 2 || life == 3))
                        {
                            buffer[i][j] = 1;
                        }
                        else if (mat[i][j] == 0 && life == 3)
                        {
                            buffer[i][j] = 1;
                        }
                    }
                }
                if (IsKeyDown(KEY_A))
                {
                    for (i = 0; i < 20; i++)
                    {
                        for (j = 0; j < 20; j++)
                        {
                            mat[i][j] = buffer[i][j];
                        }
                    }
                }
                //  BeginDrawing();
                for (i = 0; i < 20; i++)
                {
                    for (j = 0; j < 20; j++)
                    {
                        if (mat[i][j] == 0)
                        {
                            DrawRectangleLines(i * cellWidth, j * cellHeight, cellWidth, cellHeight, WHITE);
                        }
                        else
                        {
                            DrawRectangle(i * cellWidth, j * cellHeight, cellWidth, cellHeight, BLACK);
                        }
                        DrawRectangleLines(i * cellWidth, j * cellHeight, cellWidth, cellHeight, GRAY);
                    }
                }

                EndDrawing();
            }
        }
    }
    CloseWindow();
    return 0;
}

The screen is not rendering in the last version and I am trying to solve this.

1

There are 1 answers

3
chqrlie On

The mouse position is reported in screen units, you should divide them to get cell coordinates and you should test that the resulting coordinates are inside the matrix to avoid undefined behavior writing beyond the array boundaries. Also swap the index variables used for the matrix coordinates as y is a row number and x a column:

        if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
            Vector2 mPos = GetMousePosition();
            int x = mPos.x / cellWidth;
            int y = mPos.y / cellHeight;
            if (x >= 0 && x < COLS && y >= 0 && y < ROWS) {
                if (mat[y][x] != 1) {
                    mat[y][x] = 1;
                   refresh_screen(...);
                }
            }
        }

The logic is somewhat flawed: in the event loop you should

  • track mouse clicks and change the cell value. Beware that your code has rows and columns swapped;

  • track space bar presses and toggle the game running state using a a boolean game_on initially false;

  • run the game logic only if the game is running;

  • fix the x and y coordinate computations when drawing the game for consistency with the source code matrix.

Here is a modified version for you to study:

  • I pushed the refresh rate to 24 FPS so mouse clicks are handled more often, but the game only iterates every twice a second;
  • The space bar acts as a run / stop toggle.
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "raylib.h"
#include "raymath.h"

int main(void)
{
    enum { COLS = 20, ROWS = 20 };
#define _ 0
#define X 1
    int mat[ROWS][COLS] = {
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,X,_,X,_,X,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,X,_,_,_,X,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,X,_,_,_,X,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,X,_,_,_,X,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,X,_,X,_,X,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
        { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ },
    };
#undef _
#undef X
    int screenWidth = 600;
    int screenHeight = 600;
    int cellWidth = screenWidth / COLS;
    int cellHeight = screenHeight / ROWS;
    int game_on = 0;
    int frames_per_sec = 24;
    int runs_per_sec = 2;
    int empty_runs = 0;

    SetTargetFPS(frames_per_sec);
    InitWindow(screenWidth, screenHeight, "trial render");
    while (!WindowShouldClose())
    {
        BeginDrawing();

        if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
            Vector2 mPos = GetMousePosition();
            int x = (int)mPos.x / cellWidth;
            int y = (int)mPos.y / cellHeight;
            if (x >= 0 && x < COLS && y >= 0 && y < ROWS) {
                mat[y][x] = 1;
            }
        }

        if (IsKeyPressed(KEY_SPACE)) {
            game_on ^= 1;
        }

        if (game_on && --empty_runs <= 0) {
            int buffer[ROWS][COLS];

            for (int i = 0; i < ROWS; i++)
            {
                for (int j = 0; j < COLS; j++)
                {
                    int right = (j + 1) % COLS;
                    int left = (j - 1 + COLS) % COLS;
                    int up = (i - 1 + ROWS) % ROWS;
                    int down = (i + 1) % ROWS;
                    // add 8 neighboring cells
                    int life = mat[up][left] + mat[up][j] + mat[up][right] +
                        mat[i][left] + mat[i][right] +
                        mat[down][left] + mat[down][j] + mat[down][right];
                    if (mat[i][j] == 1 && (life < 2 || life > 3))
                    {
                        buffer[i][j] = 0;
                    }
                    else if (mat[i][j] == 1 && (life == 2 || life == 3))
                    {
                        buffer[i][j] = 1;
                    }
                    else if (mat[i][j] == 0 && life == 3)
                    {
                        buffer[i][j] = 1;
                    }
                    else
                    {
                        buffer[i][j] = 0;
                    }
                }
            }
            for (int i = 0; i < ROWS; i++)
            {
                for (int j = 0; j < COLS; j++)
                {
                    mat[i][j] = buffer[i][j];
                }
            }
            empty_runs = frames_per_sec / runs_per_sec;
        }
        // redraw the screen
        ClearBackground(WHITE);
        for (int i = 0; i < ROWS; i++)
        {
            for (int j = 0; j < COLS; j++)
            {
                if (mat[i][j] != 0)
                {
                    DrawRectangle(j * cellWidth, i * cellHeight, cellWidth, cellHeight, BLACK);
                }
                DrawRectangleLines(j * cellWidth, i * cellHeight, cellWidth, cellHeight, GRAY);
            }
        }
        EndDrawing();
    }
    CloseWindow();
    return 0;
}