A main interface written in C++ and raylib.
Code: Select all
#include <raylib.h>
const char title[] = "Conway's Story Mode[INDEV]";
const char maintitle[] = "Conway's Story Mode";
const char start[] = "Start";
const char sandbox[] = "Sandbox";
const char settings[] = "Settings";
const char credits[] = "Credits";
void drawCenterText(Font font, const char* text, Vector2 position, int fontSize, int spacing, Color color) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
DrawTextEx(font, text, {position.x - size.x / 2, position.y - size.y / 2}, fontSize, spacing, color);
}
void drawBorder(Rectangle rect, float width, Color color) {
DrawLineEx({rect.x, rect.y}, {rect.x, rect.y + rect.height}, width, color);
DrawLineEx({rect.x, rect.y}, {rect.x + rect.width, rect.y}, width, color);
DrawLineEx({rect.x, rect.y + rect.height}, {rect.x + rect.width, rect.y + rect.height}, width, color);
DrawLineEx({rect.x + rect.width, rect.y}, {rect.x + rect.width, rect.y + rect.height}, width, color);
}
Rectangle getTextRect(Font font, const char* text, Vector2 position, int fontSize, int spacing, float outer_size) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
return (Rectangle){position.x - size.x / 2 - outer_size, position.y - size.y / 2 - outer_size, size.x + outer_size * 2, size.y + outer_size * 2};
}
int main() {
const int width = 1000, height = 600, fontSize = 24, spacing = 0;
InitWindow(width, height, title);
Font font = LoadFont("C:\\Windows\\Fonts\\courbd.ttf");
if (!IsFontValid(font)) {
font = LoadFont("C:\\Windows\\Fonts\\cour.ttf");
if (!IsFontValid(font)) {
font = LoadFont("C:\\Windows\\Fonts\\arial.ttf");
if (!IsFontValid(font)) {
font = GetFontDefault();
}
}
}
Rectangle startRect = getTextRect(font, start, {width / 2.f, 3 * height / 7.f}, fontSize, spacing, 5);
Rectangle sandboxRect = getTextRect(font, sandbox, {width / 2.f, 4 * height / 7.f}, fontSize, spacing, 5);
Rectangle settingsRect = getTextRect(font, settings, {width / 2.f, 5 * height / 7.f}, fontSize, spacing, 5);
Rectangle creditsRect = getTextRect(font, credits, {width / 2.f, 6 * height / 7.f}, fontSize, spacing, 5);
while (!WindowShouldClose()) {
Vector2 mouse = GetMousePosition();
bool mouse_on_start = false, mouse_on_sandbox = false, mouse_on_settings = false, mouse_on_credits = false;
if (CheckCollisionPointRec(mouse, getTextRect(font, start, {width / 2.f, 3 * height / 7.f}, fontSize, spacing, 5))) {
mouse_on_start = true;
}
if (CheckCollisionPointRec(mouse, getTextRect(font, sandbox, {width / 2.f, 4 * height / 7.f}, fontSize, spacing, 5))) {
mouse_on_sandbox = true;
}
if (CheckCollisionPointRec(mouse, getTextRect(font, settings, {width / 2.f, 5 * height / 7.f}, fontSize, spacing, 5))) {
mouse_on_settings = true;
}
if (CheckCollisionPointRec(mouse, getTextRect(font, credits, {width / 2.f, 6 * height / 7.f}, fontSize, spacing, 5))) {
mouse_on_credits = true;
}
BeginDrawing();
ClearBackground({0, 0, 0});
if (mouse_on_start) {
DrawRectangleRec(startRect, DARKGRAY);
}
if (mouse_on_sandbox) {
DrawRectangleRec(sandboxRect, DARKGRAY);
}
if (mouse_on_settings) {
DrawRectangleRec(settingsRect, DARKGRAY);
}
if (mouse_on_credits) {
DrawRectangleRec(creditsRect, DARKGRAY);
}
drawCenterText(font, maintitle, {width / 2.f, height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, start, {width / 2.f, 3 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, sandbox, {width / 2.f, 4 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, settings, {width / 2.f, 5 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, credits, {width / 2.f, 6 * height / 7.f}, fontSize, spacing, WHITE);
drawBorder(startRect, 2, WHITE);
drawBorder(sandboxRect, 2, WHITE);
drawBorder(settingsRect, 2, WHITE);
drawBorder(creditsRect, 2, WHITE);
EndDrawing();
}
}
It is named "Another Game of Life".
Code: Select all
#include <raylib.h>
const char title[] = "Another Game of Life [INDEV]";
const char maintitle[] = "Another Game of Life";
const char subtitle[] = "A Puzzle Collection in Conway's Game of Life";
const char start[] = "Start";
const char sandbox[] = "Sandbox";
const char settings[] = "Settings";
const char credits[] = "Credits";
const char exit[] = "Press the ESC key to exit";
const char mainInterface[] = "Press the ESC key to return to the main screen";
void drawCenterText(Font font, const char* text, Vector2 position, int fontSize, int spacing, Color color) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
DrawTextEx(font, text, {position.x - size.x / 2, position.y - size.y / 2}, fontSize, spacing, color);
}
void drawBottomRightText(Font font, const char* text, Vector2 position, int fontSize, int spacing, Color color) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
DrawTextEx(font, text, {position.x - size.x, position.y - size.y}, fontSize, spacing, color);
}
void drawBorder(Rectangle rect, float width, Color color) {
DrawLineEx({rect.x, rect.y}, {rect.x, rect.y + rect.height}, width, color);
DrawLineEx({rect.x, rect.y}, {rect.x + rect.width, rect.y}, width, color);
DrawLineEx({rect.x, rect.y + rect.height}, {rect.x + rect.width, rect.y + rect.height}, width, color);
DrawLineEx({rect.x + rect.width, rect.y}, {rect.x + rect.width, rect.y + rect.height}, width, color);
}
Rectangle getTextRect(Font font, const char* text, Vector2 position, int fontSize, int spacing, float outer_size) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
return (Rectangle){position.x - size.x / 2 - outer_size, position.y - size.y / 2 - outer_size, size.x + outer_size * 2, size.y + outer_size * 2};
}
enum Mode {EXIT, MAIN, GAME, SANDBOX, SETTINGS, CREDITS};
int main() {
const int width = 1000, height = 600, fontSize = 24, spacing = 0;
InitWindow(width, height, title);
SetExitKey(KEY_NULL);
Font font = LoadFont("C:\\Windows\\Fonts\\courbd.ttf");
if (!IsFontValid(font)) {
font = LoadFont("C:\\Windows\\Fonts\\cour.ttf");
if (!IsFontValid(font)) {
font = LoadFont("C:\\Windows\\Fonts\\arial.ttf");
if (!IsFontValid(font)) {
font = GetFontDefault();
}
}
}
Rectangle startRect = getTextRect(font, start, {width / 2.f, 3 * height / 7.f}, fontSize, spacing, 5);
Rectangle sandboxRect = getTextRect(font, sandbox, {width / 2.f, 4 * height / 7.f}, fontSize, spacing, 5);
Rectangle settingsRect = getTextRect(font, settings, {width / 2.f, 5 * height / 7.f}, fontSize, spacing, 5);
Rectangle creditsRect = getTextRect(font, credits, {width / 2.f, 6 * height / 7.f}, fontSize, spacing, 5);
Mode mode = MAIN;
while (mode != EXIT && !WindowShouldClose()) {
switch (mode) {
case EXIT: break;
case MAIN: {
Vector2 mouse = GetMousePosition();
bool mouse_on_start = false, mouse_on_sandbox = false, mouse_on_settings = false, mouse_on_credits = false;
if (CheckCollisionPointRec(mouse, getTextRect(font, start, {width / 2.f, 3 * height / 7.f}, fontSize, spacing, 5))) {
mouse_on_start = true;
}
if (CheckCollisionPointRec(mouse, getTextRect(font, sandbox, {width / 2.f, 4 * height / 7.f}, fontSize, spacing, 5))) {
mouse_on_sandbox = true;
}
if (CheckCollisionPointRec(mouse, getTextRect(font, settings, {width / 2.f, 5 * height / 7.f}, fontSize, spacing, 5))) {
mouse_on_settings = true;
}
if (CheckCollisionPointRec(mouse, getTextRect(font, credits, {width / 2.f, 6 * height / 7.f}, fontSize, spacing, 5))) {
mouse_on_credits = true;
}
bool click = IsMouseButtonPressed(MOUSE_BUTTON_LEFT), down = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
if (IsKeyPressed(KEY_ESCAPE)) {
mode = EXIT;
}
if (click && mouse_on_start) {
mode = GAME;
}
if (click && mouse_on_sandbox) {
mode = SANDBOX;
}
if (click && mouse_on_settings) {
mode = SETTINGS;
}
if (click && mouse_on_credits) {
mode = CREDITS;
}
BeginDrawing();
ClearBackground({0, 0, 0});
if (!down) {
if (mouse_on_start) {
DrawRectangleRec(startRect, DARKGRAY);
}
if (mouse_on_sandbox) {
DrawRectangleRec(sandboxRect, DARKGRAY);
}
if (mouse_on_settings) {
DrawRectangleRec(settingsRect, DARKGRAY);
}
if (mouse_on_credits) {
DrawRectangleRec(creditsRect, DARKGRAY);
}
}
drawCenterText(font, maintitle, {width / 2.f, height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, subtitle, {width / 2.f, height / 5.f}, 2 * fontSize / 3, spacing, WHITE);
drawCenterText(font, start, {width / 2.f, 3 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, sandbox, {width / 2.f, 4 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, settings, {width / 2.f, 5 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, credits, {width / 2.f, 6 * height / 7.f}, fontSize, spacing, WHITE);
drawBorder(startRect, 2, WHITE);
drawBorder(sandboxRect, 2, WHITE);
drawBorder(settingsRect, 2, WHITE);
drawBorder(creditsRect, 2, WHITE);
drawBottomRightText(font, exit, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
case GAME: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
drawBottomRightText(font, mainInterface, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
case SANDBOX: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
drawBottomRightText(font, mainInterface, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
case SETTINGS: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
drawBottomRightText(font, mainInterface, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
case CREDITS: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
DrawTextEx(font, "RULE INVENTER -- John H. Conway\n\nPROJECT STARTER -- g0t0\nSOFTWARE DEVELOPER -- g0t0\n\nArt -- less", {width / 7.f, height / 7.f}, fontSize, spacing, WHITE);
drawBottomRightText(font, mainInterface, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
}
}
UnloadFont(font);
CloseWindow();
}
upd:
Add an introduction of CGoL.
Do someone think the font is to small?
Code: Select all
#include <raylib.h>
const char title[] = "Another Game of Life [INDEV]";
const char maintitle[] = "Another Game of Life";
const char subtitle[] = "A Puzzle Collection in Conway's Game of Life";
const char start[] = "Start";
const char sandbox[] = "Sandbox";
const char settings[] = "Settings";
const char credits[] = "Credits";
const char exit[] = "Press the ESC key to exit";
const char mainInterface[] = "Press the ESC key to return to the main screen";
const char credits_table[] = "RULE INVENTER -- John H. Conway\n\nPROJECT STARTER -- g0t0\nSOFTWARE DEVELOPER -- g0t0\n\nArt -- less";
const char intro[] = R"END(Conway's Game of Life, also known as the Game of Life or simply Life,
is a cellular automaton devised by the British mathematician
John Horton Conway in 1970. It is the best-known example of a cellular automaton.
The "game" is actually a zero-player game, meaning that its evolution
is determined by its initial state, needing no input from human players.
One interacts with the Game of Life by creating an initial configuration
and observing how it evolves.
GoL and CGoL are commonly used acronyms.
The universe of the Game of Life is an infinite two-dimensional orthogonal
grid of square cells, each of which (at any given time) is in one of
two possible states, "live" (alternatively "on") or "dead" (alternatively "off").
Every cell interacts with its eight neighbours, which are the cells that
are directly horizontally, vertically, or diagonally adjacent.
At each step in time, the following transitions occur:)END";
const char example_1[] = R"END(Any live cell with
fewer than two live neighbours
dies (referred to as
underpopulation or exposure).)END";
const char example_2[] = R"END(Any live cell with
more than three live neighbours
dies (referred to as
overpopulation or overcrowding).)END";
const char example_3[] = R"END(Any live cell with
two or three live neighbours
lives, unchanged, to the next
generation.)END";
const char example_4[] = R"END(Any dead cell with
exactly three live neighbours
will come to life.)END";
void drawCenterText(Font font, const char* text, Vector2 position, int fontSize, int spacing, Color color) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
DrawTextEx(font, text, {position.x - size.x / 2, position.y - size.y / 2}, fontSize, spacing, color);
}
void drawBottomRightText(Font font, const char* text, Vector2 position, int fontSize, int spacing, Color color) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
DrawTextEx(font, text, {position.x - size.x, position.y - size.y}, fontSize, spacing, color);
}
void drawBorder(Rectangle rect, float width, Color color) {
DrawLineEx({rect.x, rect.y}, {rect.x, rect.y + rect.height}, width, color);
DrawLineEx({rect.x, rect.y}, {rect.x + rect.width, rect.y}, width, color);
DrawLineEx({rect.x, rect.y + rect.height}, {rect.x + rect.width, rect.y + rect.height}, width, color);
DrawLineEx({rect.x + rect.width, rect.y}, {rect.x + rect.width, rect.y + rect.height}, width, color);
}
Rectangle getTextRect(Font font, const char* text, Vector2 position, int fontSize, int spacing, float outer_size) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
return (Rectangle){position.x - size.x / 2 - outer_size, position.y - size.y / 2 - outer_size, size.x + outer_size * 2, size.y + outer_size * 2};
}
void drawGrid(int height, int width, const bool* cells, Rectangle rect, float lineWidth, Color borderColor, Color color) {
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
if (cells[i * width + j]) {
DrawRectangle(rect.x + j * rect.width / width, rect.y + i * rect.height / height, rect.width / width, rect.height / height, color);
}
}
}
for (int i = 0; i <= width; ++i) {
DrawLineEx({rect.x + i * rect.width / width, rect.y}, {rect.x + i * rect.width / width, rect.y + rect.height}, lineWidth, borderColor);
}
for (int i = 0; i <= height; ++i) {
DrawLineEx({rect.x, rect.y + i * rect.height / height}, {rect.x + rect.width, rect.y + i * rect.height / height}, lineWidth, borderColor);
}
}
enum Mode {EXIT, MAIN, GAME, SANDBOX, SETTINGS, CREDITS};
int main() {
const int width = 1500, height = 900, titleFontSize = 36, fontSize = 24, spacing = 0;
InitWindow(width, height, title);
SetExitKey(KEY_NULL);
Font font = LoadFont("C:\\Windows\\Fonts\\courbd.ttf");
if (!IsFontValid(font)) {
font = LoadFont("C:\\Windows\\Fonts\\cour.ttf");
if (!IsFontValid(font)) {
font = LoadFont("C:\\Windows\\Fonts\\arial.ttf");
if (!IsFontValid(font)) {
font = GetFontDefault();
}
}
}
Rectangle startRect = getTextRect(font, start, {width / 2.f, 3 * height / 7.f}, titleFontSize, spacing, 5);
Rectangle sandboxRect = getTextRect(font, sandbox, {width / 2.f, 4 * height / 7.f}, titleFontSize, spacing, 5);
Rectangle settingsRect = getTextRect(font, settings, {width / 2.f, 5 * height / 7.f}, titleFontSize, spacing, 5);
Rectangle creditsRect = getTextRect(font, credits, {width / 2.f, 6 * height / 7.f}, titleFontSize, spacing, 5);
Mode mode = MAIN;
while (mode != EXIT && !WindowShouldClose()) {
switch (mode) {
case EXIT: break;
case MAIN: {
Vector2 mouse = GetMousePosition();
bool mouse_on_start = false, mouse_on_sandbox = false, mouse_on_settings = false, mouse_on_credits = false;
if (CheckCollisionPointRec(mouse, getTextRect(font, start, {width / 2.f, 3 * height / 7.f}, titleFontSize, spacing, 5))) {
mouse_on_start = true;
}
if (CheckCollisionPointRec(mouse, getTextRect(font, sandbox, {width / 2.f, 4 * height / 7.f}, titleFontSize, spacing, 5))) {
mouse_on_sandbox = true;
}
if (CheckCollisionPointRec(mouse, getTextRect(font, settings, {width / 2.f, 5 * height / 7.f}, titleFontSize, spacing, 5))) {
mouse_on_settings = true;
}
if (CheckCollisionPointRec(mouse, getTextRect(font, credits, {width / 2.f, 6 * height / 7.f}, titleFontSize, spacing, 5))) {
mouse_on_credits = true;
}
bool click = IsMouseButtonPressed(MOUSE_BUTTON_LEFT), down = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
if (IsKeyPressed(KEY_ESCAPE)) {
mode = EXIT;
}
if (click && mouse_on_start) {
mode = GAME;
}
if (click && mouse_on_sandbox) {
mode = SANDBOX;
}
if (click && mouse_on_settings) {
mode = SETTINGS;
}
if (click && mouse_on_credits) {
mode = CREDITS;
}
BeginDrawing();
ClearBackground({0, 0, 0});
if (!down) {
if (mouse_on_start) {
DrawRectangleRec(startRect, DARKGRAY);
}
if (mouse_on_sandbox) {
DrawRectangleRec(sandboxRect, DARKGRAY);
}
if (mouse_on_settings) {
DrawRectangleRec(settingsRect, DARKGRAY);
}
if (mouse_on_credits) {
DrawRectangleRec(creditsRect, DARKGRAY);
}
}
drawCenterText(font, maintitle, {width / 2.f, height / 7.f}, titleFontSize, spacing, WHITE);
drawCenterText(font, subtitle, {width / 2.f, height / 5.f}, fontSize, spacing, WHITE);
drawCenterText(font, start, {width / 2.f, 3 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, sandbox, {width / 2.f, 4 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, settings, {width / 2.f, 5 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, credits, {width / 2.f, 6 * height / 7.f}, fontSize, spacing, WHITE);
drawBorder(startRect, 2, WHITE);
drawBorder(sandboxRect, 2, WHITE);
drawBorder(settingsRect, 2, WHITE);
drawBorder(creditsRect, 2, WHITE);
drawBottomRightText(font, exit, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
case GAME: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
DrawTextEx(font, intro, {width / 7.f, height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, example_1, {width / 5.f, 5 * height / 7.f}, 2 * fontSize / 3, spacing, WHITE);
drawCenterText(font, example_2, {2 * width / 5.f, 5 * height / 7.f}, 2 * fontSize / 3, spacing, WHITE);
drawCenterText(font, example_3, {3 * width / 5.f, 5 * height / 7.f}, 2 * fontSize / 3, spacing, WHITE);
drawCenterText(font, example_4, {4 * width / 5.f, 5 * height / 7.f}, 2 * fontSize / 3, spacing, WHITE);
bool a[9] = {0, 0, 0, 0, 1, 0, 0, 0, 1};
bool b[9] = {1, 1, 0, 0, 1, 0, 1, 0, 1};
bool c[9] = {1, 0, 0, 0, 1, 0, 0, 1, 0};
bool d[9] = {1, 0, 0, 1, 0, 0, 0, 0, 1};
drawGrid(3, 3, a, {width / 5.f - width / 32.f, 6 * height / 7.f - width / 32.f, width / 16.f, width / 16.f}, 2, GRAY, WHITE);
drawGrid(3, 3, b, {2 * width / 5.f - width / 32.f, 6 * height / 7.f - width / 32.f, width / 16.f, width / 16.f}, 2, GRAY, WHITE);
drawGrid(3, 3, c, {3 * width / 5.f - width / 32.f, 6 * height / 7.f - width / 32.f, width / 16.f, width / 16.f}, 2, GRAY, WHITE);
drawGrid(3, 3, d, {4 * width / 5.f - width / 32.f, 6 * height / 7.f - width / 32.f, width / 16.f, width / 16.f}, 2, GRAY, WHITE);
drawBottomRightText(font, mainInterface, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
case SANDBOX: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
drawBottomRightText(font, mainInterface, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
case SETTINGS: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
drawBottomRightText(font, mainInterface, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
case CREDITS: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
DrawTextEx(font, credits_table, {width / 7.f, height / 7.f}, fontSize, spacing, WHITE);
drawBottomRightText(font, mainInterface, {width, height}, 2 * fontSize / 3, spacing, WHITE);
EndDrawing();
} break;
}
}
UnloadFont(font);
CloseWindow();
}
Add "Next" and "Prev" button:
Code: Select all
#include <raylib.h>
const char title[] = "Another Game of Life [INDEV]";
const char maintitle[] = "Another Game of Life";
const char subtitle[] = "A Puzzle Collection in Conway's Game of Life";
const char start[] = "Start";
const char sandbox[] = "Sandbox";
const char settings[] = "Settings";
const char credits[] = "Credits";
const char exit[] = "Press the ESC key to exit";
const char mainInterface[] = "Press the ESC key to return to the main screen";
const char credits_table[] = R"(RULE INVENTER -- John H. Conway
PROJECT STARTER -- g0t0\nSOFTWARE DEVELOPER -- g0t0
Art -- less)";
const char intro_title[] = "Introduction";
const char intro[] = R"END(Conway's Game of Life, also known as the Game of Life or simply Life, is a cellular automaton devised by
the British mathematician John Horton Conway in 1970. It is the best-known example of a cellular automaton.
The "game" is actually a zero-player game, meaning that its evolution is determined by its initial state, needing no input from
human players. One interacts with the Game of Life by creating an initial configuration and observing how it evolves.
GoL and CGoL are commonly used acronyms.
The universe of the Game of Life is an infinite two-dimensional orthogonal grid of square cells, each of which (at any given time)
is in one of two possible states, "live" (alternatively "on") or "dead" (alternatively "off"). Every cell interacts with its eight
neighbours, which are the cells that are directly horizontally, vertically, or diagonally adjacent. At each step in time,
the following transitions occur:)END";
const char example_1[] = R"END(1. Any live cell with
fewer than two live neighbours
dies (referred to as
underpopulation or exposure).)END";
const char example_2[] = R"END(2. Any live cell with
more than three live neighbours
dies (referred to as
overpopulation or overcrowding).)END";
const char example_3[] = R"END(3. Any live cell with
two or three live neighbours
lives, unchanged, to the next
generation.)END";
const char example_4[] = R"END(4. Any dead cell with
exactly three live neighbours
will come to life.)END";
const char next[] = "Next";
const char prev[] = "Prev";
const char origin_title[] = "Origin";
const char origin[] = R"END(The game made its first public appearance in the October 1970 issue of Scientific American, in Martin Gardner's "Mathematical Games" column,
under the title of The fantastic combinations of John Conway's new solitaire game "life". From a theoretical point of view,
it is interesting because it has the power of a universal Turing machine: that is, anything that can be computed algorithmically
can be computed within Conway's Game of Life. Gardner wrote:
"The game made Conway instantly famous, but it also opened up a whole new field of mathematical research, the field of
cellular automata ... Because of Life's analogies with the rise, fall and alterations of a society of living organisms, it belongs to
a growing class of what are called 'simulation games' (games that resemble real life processes)"
Ever since its publication, Conway's Game of Life has attracted much interest because of the surprising ways in which the patterns
can evolve. Life is an example of emergence and self-organization. It is interesting for physicists, biologists, economists,
mathematicians, philosophers, generative scientists and others to observe the way that complex patterns can emerge from the
implementation of very simple rules. The game can also serve as a didactic analogy, used to convey the somewhat counterintuitive
notion that "design" and "organization" can spontaneously emerge in the absence of a designer. For example, philosopher and
cognitive scientist Daniel C. Dennett has used the analog of Conway's Life "universe" extensively to illustrate the possible evolution
of complex philosophical constructs, such as consciousness and free will, from the relatively simple set of deterministic physical laws
governing our own universe.
The popularity of Conway's Life was helped by its coming into being just in time for a new generation of inexpensive minicomputers
which were being released into the market, meaning that the game could be run for hours on these machines which were otherwise
unused at night. In this respect it foreshadowed the later popularity of computer-generated fractals. For many, Life was
simply a programming challenge; a fun way to waste CPU cycles. For some, however, Life had more philosophical connotations.
It developed a cult following through the 1970s and beyond; current developments have gone so far as to create theoretic emulations
of computer systems within the confines of a Life board.
Conway chose his rules carefully, after considerable experimentation, to meet three criteria:
1. There should be no initial pattern for which there is a simple proof that the population can grow without limit.
2. There should be initial patterns that apparently do grow without limit.
3. There should be simple initial patterns that grow and change for a considerable period of time before coming to an end
in the following possible ways:
- Fading away completely (from overcrowding or from becoming too sparse); or
- Settling into a stable configuration that remains unchanged thereafter, or entering an oscillating phase in which they repeat
an endless cycle of two or more periods.)END";
void drawCenterText(Font font, const char* text, Vector2 position, int fontSize, int spacing, Color color) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
DrawTextEx(font, text, {position.x - size.x / 2, position.y - size.y / 2}, fontSize, spacing, color);
}
void drawBottomRightText(Font font, const char* text, Vector2 position, int fontSize, int spacing, Color color) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
DrawTextEx(font, text, {position.x - size.x, position.y - size.y}, fontSize, spacing, color);
}
void drawBorder(Rectangle rect, float width, Color color) {
DrawLineEx({rect.x, rect.y}, {rect.x, rect.y + rect.height}, width, color);
DrawLineEx({rect.x, rect.y}, {rect.x + rect.width, rect.y}, width, color);
DrawLineEx({rect.x, rect.y + rect.height}, {rect.x + rect.width, rect.y + rect.height}, width, color);
DrawLineEx({rect.x + rect.width, rect.y}, {rect.x + rect.width, rect.y + rect.height}, width, color);
}
Rectangle getTextRect(Font font, const char* text, Vector2 position, int fontSize, int spacing, float outer_size) {
Vector2 size = MeasureTextEx(font, text, fontSize, spacing);
return (Rectangle){position.x - size.x / 2 - outer_size, position.y - size.y / 2 - outer_size, size.x + outer_size * 2, size.y + outer_size * 2};
}
void drawGrid(int height, int width, const bool* cells, Rectangle rect, float lineWidth, Color borderColor, Color color) {
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
if (cells[i * width + j]) {
DrawRectangle(rect.x + j * rect.width / width, rect.y + i * rect.height / height, rect.width / width, rect.height / height, color);
}
}
}
for (int i = 0; i <= width; ++i) {
DrawLineEx({rect.x + i * rect.width / width, rect.y}, {rect.x + i * rect.width / width, rect.y + rect.height}, lineWidth, borderColor);
}
for (int i = 0; i <= height; ++i) {
DrawLineEx({rect.x, rect.y + i * rect.height / height}, {rect.x + rect.width, rect.y + i * rect.height / height}, lineWidth, borderColor);
}
}
enum Mode {EXIT, MAIN, GAME, SANDBOX, SETTINGS, CREDITS};
int main() {
const float scale = 0.5;
const int width = 1500 * scale, height = 900 * scale, titleFontSize = 36 * scale, subtitlefontSize = 24 * scale, fontSize = 16 * scale, spacing = 0 * scale;
const float outer_size = 5 * scale;
InitWindow(width, height, title);
SetExitKey(KEY_NULL);
Font font = LoadFont("C:\\Windows\\Fonts\\courbd.ttf");
if (!IsFontValid(font)) {
font = LoadFont("C:\\Windows\\Fonts\\cour.ttf");
if (!IsFontValid(font)) {
font = LoadFont("C:\\Windows\\Fonts\\arial.ttf");
if (!IsFontValid(font)) {
font = GetFontDefault();
}
}
}
Rectangle startRect = getTextRect(font, start, {width / 2.f, 3 * height / 7.f}, 1.5 * subtitlefontSize, spacing, outer_size);
Rectangle sandboxRect = getTextRect(font, sandbox, {width / 2.f, 4 * height / 7.f}, 1.5 * subtitlefontSize, spacing, outer_size);
Rectangle settingsRect = getTextRect(font, settings, {width / 2.f, 5 * height / 7.f}, 1.5 * subtitlefontSize, spacing, outer_size);
Rectangle creditsRect = getTextRect(font, credits, {width / 2.f, 6 * height / 7.f}, 1.5 * subtitlefontSize, spacing, outer_size);
Rectangle nextRect = getTextRect(font, next, {7 * width / 8.f, 6 * height / 7.f}, fontSize, spacing, outer_size);
Rectangle prevRect = getTextRect(font, prev, {width / 8.f, 6 * height / 7.f}, fontSize, spacing, outer_size);
Mode mode = MAIN;
int game_page = 1;
while (mode != EXIT && !WindowShouldClose()) {
switch (mode) {
case EXIT: break;
case MAIN: {
Vector2 mouse = GetMousePosition();
bool mouse_on_start = false, mouse_on_sandbox = false, mouse_on_settings = false, mouse_on_credits = false;
if (CheckCollisionPointRec(mouse, startRect)) {
mouse_on_start = true;
}
if (CheckCollisionPointRec(mouse, sandboxRect)) {
mouse_on_sandbox = true;
}
if (CheckCollisionPointRec(mouse, settingsRect)) {
mouse_on_settings = true;
}
if (CheckCollisionPointRec(mouse, creditsRect)) {
mouse_on_credits = true;
}
bool click = IsMouseButtonPressed(MOUSE_BUTTON_LEFT), down = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
if (IsKeyPressed(KEY_ESCAPE)) {
mode = EXIT;
}
if (click && mouse_on_start) {
mode = GAME;
}
if (click && mouse_on_sandbox) {
mode = SANDBOX;
}
if (click && mouse_on_settings) {
mode = SETTINGS;
}
if (click && mouse_on_credits) {
mode = CREDITS;
}
BeginDrawing();
ClearBackground({0, 0, 0});
if (!down) {
if (mouse_on_start) {
DrawRectangleRec(startRect, DARKGRAY);
}
if (mouse_on_sandbox) {
DrawRectangleRec(sandboxRect, DARKGRAY);
}
if (mouse_on_settings) {
DrawRectangleRec(settingsRect, DARKGRAY);
}
if (mouse_on_credits) {
DrawRectangleRec(creditsRect, DARKGRAY);
}
}
drawCenterText(font, maintitle, {width / 2.f, height / 7.f}, titleFontSize, spacing, WHITE);
drawCenterText(font, subtitle, {width / 2.f, height / 5.f}, subtitlefontSize, spacing, WHITE);
drawCenterText(font, start, {width / 2.f, 3 * height / 7.f}, subtitlefontSize, spacing, WHITE);
drawCenterText(font, sandbox, {width / 2.f, 4 * height / 7.f}, subtitlefontSize, spacing, WHITE);
drawCenterText(font, settings, {width / 2.f, 5 * height / 7.f}, subtitlefontSize, spacing, WHITE);
drawCenterText(font, credits, {width / 2.f, 6 * height / 7.f}, subtitlefontSize, spacing, WHITE);
drawBorder(startRect, 2, WHITE);
drawBorder(sandboxRect, 2, WHITE);
drawBorder(settingsRect, 2, WHITE);
drawBorder(creditsRect, 2, WHITE);
drawBottomRightText(font, exit, {width, height}, fontSize, spacing, WHITE);
EndDrawing();
} break;
case GAME: {
Vector2 mouse = GetMousePosition();
bool mouse_on_next = CheckCollisionPointRec(mouse, nextRect);
bool mouse_on_prev = CheckCollisionPointRec(mouse, prevRect);
bool click = IsMouseButtonPressed(MOUSE_BUTTON_LEFT), down = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
if (game_page == 1) {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
if (mouse_on_next && click) {
game_page = 2;
}
BeginDrawing();
ClearBackground({0, 0, 0});
DrawTextEx(font, intro_title, {width / 7.f, height / 14.f}, subtitlefontSize, spacing, WHITE);
DrawTextEx(font, intro, {width / 7.f, height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, example_1, {width / 5.f, 4 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, example_2, {2 * width / 5.f, 4 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, example_3, {3 * width / 5.f, 4 * height / 7.f}, fontSize, spacing, WHITE);
drawCenterText(font, example_4, {4 * width / 5.f, 4 * height / 7.f}, fontSize, spacing, WHITE);
bool a[9] = {0, 0, 0, 0, 1, 0, 0, 0, 1};
bool b[9] = {1, 1, 0, 0, 1, 0, 1, 0, 1};
bool c[9] = {1, 0, 0, 0, 1, 0, 0, 1, 0};
bool d[9] = {1, 0, 0, 1, 0, 0, 0, 0, 1};
drawGrid(3, 3, a, {width / 5.f - width / 32.f, 5 * height / 7.f - width / 32.f, width / 16.f, width / 16.f}, 2, GRAY, WHITE);
drawGrid(3, 3, b, {2 * width / 5.f - width / 32.f, 5 * height / 7.f - width / 32.f, width / 16.f, width / 16.f}, 2, GRAY, WHITE);
drawGrid(3, 3, c, {3 * width / 5.f - width / 32.f, 5 * height / 7.f - width / 32.f, width / 16.f, width / 16.f}, 2, GRAY, WHITE);
drawGrid(3, 3, d, {4 * width / 5.f - width / 32.f, 5 * height / 7.f - width / 32.f, width / 16.f, width / 16.f}, 2, GRAY, WHITE);
if (!down) {
if (mouse_on_next) {
DrawRectangleRec(nextRect, DARKGRAY);
}
}
drawCenterText(font, next, {7 * width / 8.f, 6 * height / 7.f}, fontSize, spacing, WHITE);
drawBorder(nextRect, 2, WHITE);
drawBottomRightText(font, mainInterface, {width, height}, fontSize, spacing, WHITE);
} else if (game_page == 2) {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
if (mouse_on_prev && click) {
game_page = 1;
}
BeginDrawing();
ClearBackground({0, 0, 0});
DrawTextEx(font, origin_title, {width / 7.f, height / 14.f}, subtitlefontSize, spacing, WHITE);
DrawTextEx(font, origin, {width / 7.f, height / 7.f}, fontSize, spacing, WHITE);
if (!down) {
if (mouse_on_prev) {
DrawRectangleRec(prevRect, DARKGRAY);
}
}
drawCenterText(font, prev, {width / 8.f, 6 * height / 7.f}, fontSize, spacing, WHITE);
drawBorder(prevRect, 2, WHITE);
drawBottomRightText(font, mainInterface, {width, height}, fontSize, spacing, WHITE);
}
EndDrawing();
} break;
case SANDBOX: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
drawBottomRightText(font, mainInterface, {width, height}, fontSize, spacing, WHITE);
EndDrawing();
} break;
case SETTINGS: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
drawBottomRightText(font, mainInterface, {width, height}, fontSize, spacing, WHITE);
EndDrawing();
} break;
case CREDITS: {
if (IsKeyPressed(KEY_ESCAPE)) mode = MAIN;
BeginDrawing();
ClearBackground({0, 0, 0});
DrawTextEx(font, credits_table, {width / 7.f, height / 7.f}, fontSize, spacing, WHITE);
drawBottomRightText(font, mainInterface, {width, height}, fontSize, spacing, WHITE);
EndDrawing();
} break;
}
}
UnloadFont(font);
CloseWindow();
}
How to solve the problem that there is a GFDL in LifeWiki?
LLM says credits should add this:
Some descriptive content is adapted from LifeWiki,
licensed under GNU Free Documentation License 1.3.