Skip to content

Commit

Permalink
feat(game-of-life): base game
Browse files Browse the repository at this point in the history
  • Loading branch information
blurk committed Apr 30, 2024
1 parent a4d8a22 commit 2bb33be
Show file tree
Hide file tree
Showing 2 changed files with 252 additions and 59 deletions.
193 changes: 193 additions & 0 deletions game-of-life/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Conway's game of life</title>
</head>
<style>
html,
body {
display: flex;
margin: 0;
padding: 0;
border: none;
max-height: 100vh;
height: 100%;
}
</style>
<body>
<canvas id="canvas"></canvas>

<script>
class Cell {
#isAlive = false;
#neighbors = 0;

constructor(ctx, x, y, size) {
/** @type {CanvasRenderingContext2D} */
this.ctx = ctx;
this.x = x;
this.y = y;
this.size = size;
}

draw() {
if (this.#isAlive) {
this.ctx.fillStyle = `rgba(
${Math.max(50, this.x * 4)},
${Math.max(100, this.y * 4)},
${Math.max(200, (this.x + this.y) * 2)},
1)`;
this.ctx.fillRect(
this.x * this.size,
this.y * this.size,
this.size,
this.size
);
}
}

nextGeneration() {
if (!this.#isAlive && this.#neighbors === 3) {
this.#isAlive = true;
} else {
this.#isAlive =
this.#isAlive && (this.#neighbors === 2 || this.#neighbors === 3);
}

this.draw();
}

get isAlive() {
return this.#isAlive;
}

set isAlive(isAlive) {
this.#isAlive = isAlive;
}

set neighbors(count) {
this.#neighbors = count;
}

get neighbors() {
return this.#neighbors;
}
}

class Game {
#cellSize = 10;
/** @type {Cell[][]} */ #cells = [];

constructor(/** @type {HTMLCanvasElement} */ canvas) {
this.canvas = canvas;
this.ctx = this.canvas.getContext("2d");
this.canvas.width = document.documentElement.offsetWidth;
this.canvas.height = document.documentElement.offsetHeight;
}

get size() {
return {
rows: Math.ceil(this.canvas.width / this.#cellSize),
cols: Math.ceil(this.canvas.height / this.#cellSize),
cellSize: this.#cellSize,
};
}

drawBoard() {
this.ctx.fillStyle = "rgba(0,0,0,1)";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
}

generateCells() {
for (let i = 0; i < this.size.rows; i++) {
this.#cells[i] = [];

for (let j = 0; j < this.size.cols; j++) {
this.#cells[i][j] = new Cell(this.ctx, i, j, this.size.cellSize);
this.#cells[i][j].isAlive = Math.random() > 0.9;
this.#cells[i][j].draw();
}
}
}

updateNeighborCells(x, y) {
let count = 0;

const neighborCoordinates = [
[x, y + 1],
[x, y - 1],
[x - 1, y - 1],
[x + 1, y - 1],
[x - 1, y],
[x + 1, y],
[x - 1, y + 1],
[x + 1, y + 1],
];

for (let [x, y] of neighborCoordinates) {
const xOutOfBound = x < 0 || x >= this.size.rows;
const yOutOfBound = y < 0 || y >= this.size.cols;

if (x < 0) {
x = this.size.rows - 1;
}

if (y < 0) {
y = this.size.cols - 1;
}

if (x >= this.size.rows) {
x = 0;
}

if (y >= this.size.cols) {
y = 0;
}

if (this.#cells[x][y].isAlive) {
count++;
}
}

this.#cells[x][y].neighbors = count;
}

updateCells() {
for (let i = 0; i < this.size.rows; i++) {
for (let j = 0; j < this.size.cols; j++) {
this.updateNeighborCells(i, j);
}
}

for (let i = 0; i < this.size.rows; i++) {
for (let j = 0; j < this.size.cols; j++) {
this.#cells[i][j].nextGeneration();
}
}
}

run() {
this.drawBoard();
this.updateCells();

setTimeout(() => {
requestAnimationFrame(() => {
this.run();
});
}, 1000 / 60);
}

init() {
this.drawBoard();
this.generateCells();

this.run();
}
}
const game = new Game(document.getElementById("canvas"));
game.init();
</script>
</body>
</html>
118 changes: 59 additions & 59 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,64 +1,64 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Main page of pet projects</title>
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
<style>
.container {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
padding: 20px 40px;
}
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Main page of pet projects</title>
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
<style>
.container {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
padding: 20px 40px;
}

.container a {
text-decoration: none;
padding: 10px 15px;
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
margin: 10px;
border: 0px solid;
border-radius: 10px;
display: block;
color: #fff;
background-color: #3b9aff;
transition: all 0.2s ease-in-out;
}
.container a {
text-decoration: none;
padding: 10px 15px;
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
margin: 10px;
border: 0px solid;
border-radius: 10px;
display: block;
color: #fff;
background-color: #3b9aff;
transition: all 0.2s ease-in-out;
}

.container a:hover {
background-color: #6eb3f8;
}
</style>
</head>
<body>
<div class="container">
<a href="./full-screen-video-background/index.html"
>Full screen video background</a
>
<a href="./Multiplejs Inspiration/index.html" target="_blank"
>Multiplejs inspiration</a
>
<a href="./One Page Wedding/index.html" target="_blank"
>One Page Wedding</a
>
<a href="./typeEffect/index.html" target="_blank">
Simple Typing Effect</a
>
<a href="./Slide Transition/index.html" target="_blank">
Slice Transition</a
>
<a href="./Blurry Overlay/index.html" target="_blank"> Blurry Overlay</a>
<a href="./MineweeperJS/index.html" target="_blank">
Mineweeper With JS</a
>
<a href="./Breath and relax web app/index.html" target="_blank"
>Breath and relax</a
>
<a href="./Pyramid/index.html" target="_blank">Pyramid</a>
<a href="./2048/index.html" target="_blank">2048 </a>
<a href="./elastic/index.html" target="_blank">Elastic</a>
</div>
</body>
.container a:hover {
background-color: #6eb3f8;
}
</style>
</head>
<body>
<div class="container">
<a href="./full-screen-video-background/index.html"
>Full screen video background</a
>
<a href="./Multiplejs Inspiration/index.html" target="_blank"
>Multiplejs inspiration</a
>
<a href="./One Page Wedding/index.html" target="_blank"
>One Page Wedding</a
>
<a href="./typeEffect/index.html" target="_blank">
Simple Typing Effect</a
>
<a href="./Slide Transition/index.html" target="_blank">
Slice Transition</a
>
<a href="./Blurry Overlay/index.html" target="_blank"> Blurry Overlay</a>
<a href="./MineweeperJS/index.html" target="_blank">
Mineweeper With JS</a
>
<a href="./Breath and relax web app/index.html" target="_blank"
>Breath and relax</a
>
<a href="./Pyramid/index.html" target="_blank">Pyramid</a>
<a href="./2048/index.html" target="_blank">2048 </a>
<a href="./game-of-life/index.html" target="_blank">Game of life: base</a>
</div>
</body>
</html>

0 comments on commit 2bb33be

Please sign in to comment.