feat: add sample content and styling
This commit is contained in:
parent
5fa72ed63e
commit
f68fc049ea
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -22,3 +22,4 @@ pnpm-debug.log*
|
||||||
|
|
||||||
# jetbrains setting folder
|
# jetbrains setting folder
|
||||||
.idea/
|
.idea/
|
||||||
|
TODO
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<div>
|
<div>
|
||||||
<ul class="nav-links undecorated-anchor">
|
<ul class="nav-links undecorated-anchor">
|
||||||
<li><a href="#">Teknik</a></li>
|
<li><a href="#">Teknik</a></li>
|
||||||
<li><a href="#">Felsefi</a></li>
|
<li><a href="#">Fikir</a></li>
|
||||||
<li><a href="#">Babür'ün Serüvenleri</a></li>
|
<li><a href="#">Babür'ün Serüvenleri</a></li>
|
||||||
<li><a href="#">Ansiklopedi</a></li>
|
<li><a href="#">Ansiklopedi</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
---
|
---
|
||||||
title: "Atatürk ve Demokratik Türkiye"
|
title: "Atatürk ve Demokratik Türkiye"
|
||||||
summary: Halil İnalcık'ın kaleminden Türkiye Cumhuriyet'nin kuruluş hikayesi ve inkılapların toplumdaki akisleri.
|
summary: Halil İnalcık'ın kaleminden Türkiye Cumhuriyet'nin kuruluş hikayesi ve Atatürk inkılaplarının toplumdaki akisleri.
|
||||||
|
category: Kitap İncelemesi
|
||||||
|
date: 2024-03-15
|
||||||
tags:
|
tags:
|
||||||
- kitap
|
- kitap
|
||||||
- atatürk
|
- atatürk
|
|
@ -1,6 +1,8 @@
|
||||||
---
|
---
|
||||||
title: "5. Bölüm: Kaptan ile Mücadele"
|
title: "5. Bölüm: Kaptan ile Mücadele"
|
||||||
summary: "Babür'ün önünde yalnızca tek bir engel kalmıştır: Komutan."
|
summary: "Babür'ün önünde yalnızca tek bir engel kalmıştır: Komutan."
|
||||||
|
category: Öykü
|
||||||
|
date: 2024-03-03
|
||||||
tags:
|
tags:
|
||||||
- babür
|
- babür
|
||||||
---
|
---
|
|
@ -1,6 +1,8 @@
|
||||||
---
|
---
|
||||||
title: "Bir Komponentin Serüveni: Astro"
|
title: "Bir Komponentin Serüveni: Astro"
|
||||||
summary: Yazdığınız komponentlere ne olur? Bu yazıda Astro komponentlerinin serüvenlerin bir göz atıyoruz!
|
summary: Yazdığınız komponentlere ne olur? Bu yazıda Astro komponentlerinin serüvenlerin bir göz atıyoruz!
|
||||||
|
category: Teknik Yazı
|
||||||
|
date: 2024-04-01
|
||||||
tags:
|
tags:
|
||||||
- astro
|
- astro
|
||||||
- javascript
|
- javascript
|
|
@ -1,15 +1,16 @@
|
||||||
// 1. Import utilities from `astro:content`
|
|
||||||
import { z, defineCollection } from "astro:content";
|
import { z, defineCollection } from "astro:content";
|
||||||
// 2. Define your collection(s)
|
|
||||||
const teknikCollection = defineCollection({
|
const blogCollection = defineCollection({
|
||||||
type: "content",
|
type: "content",
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
summary: z.string(),
|
|
||||||
tags: z.array(z.string()),
|
tags: z.array(z.string()),
|
||||||
|
summary: z.string(),
|
||||||
|
date: z.date(),
|
||||||
|
category: z.enum(["Kitap İncelemesi", "Teknik Yazı", "Öykü"]),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const collections = {
|
export const collections = {
|
||||||
teknik: teknikCollection,
|
blog: blogCollection,
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,11 +23,16 @@ const { title } = Astro.props;
|
||||||
<style is:global>
|
<style is:global>
|
||||||
:root {
|
:root {
|
||||||
--h1-desktop: 3.815rem;
|
--h1-desktop: 3.815rem;
|
||||||
|
--h2-desktop: 3.052rem;
|
||||||
|
--h3-desktop: 2.441rem;
|
||||||
|
--h4-desktop: 1.953rem;
|
||||||
|
--h5-desktop: 1.563rem;
|
||||||
--h6-desktop: 1.25rem;
|
--h6-desktop: 1.25rem;
|
||||||
--small-desktop: 0.8rem;
|
--small-desktop: 0.8rem;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS",
|
font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS",
|
||||||
sans-serif;
|
sans-serif;
|
||||||
|
background-color: #f5fffa;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -2,17 +2,37 @@
|
||||||
import Header from "../components/Header.astro";
|
import Header from "../components/Header.astro";
|
||||||
import Footer from "../components/Footer.astro";
|
import Footer from "../components/Footer.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
import "../styles/gol.css";
|
import "../styles/header.css";
|
||||||
|
import "../styles/home.css";
|
||||||
|
|
||||||
import { getCollection, getEntry } from 'astro:content';
|
import { getCollection, getEntry } from "astro:content";
|
||||||
|
|
||||||
const allTeknikPosts = await getCollection('teknik')
|
const allTeknikPosts = await getCollection("blog");
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="log101">
|
<Layout title="log101">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Header />
|
<Header />
|
||||||
{allTeknikPosts.map(p => <p>{p.data.summary}</p>)}
|
<div class="posts">
|
||||||
|
{
|
||||||
|
allTeknikPosts
|
||||||
|
.sort((p1, p2) => p2.data.date.getTime() - p1.data.date.getTime())
|
||||||
|
.map((p) => (
|
||||||
|
<div class="post">
|
||||||
|
<p class="post-category">{p.data.category}</p>
|
||||||
|
<h4 class="post-title">{p.data.title}</h4>
|
||||||
|
<p class="post-date">
|
||||||
|
{p.data.date.toLocaleDateString("tr-TR", {
|
||||||
|
day: "numeric",
|
||||||
|
month: "long",
|
||||||
|
year: "numeric",
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
<p class="post-summary">{p.data.summary}</p>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
@ -1,392 +1,418 @@
|
||||||
import { heavyWeightSpaceshipCell } from './utils'
|
import { heavyWeightSpaceshipCell } from "./utils";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A wrapper for an HTML <canvas> based visualizatiuon of Conway's Game of Life.
|
A wrapper for an HTML <canvas> based visualizatiuon of Conway's Game of Life.
|
||||||
*/
|
*/
|
||||||
export default class ConwaySimulator {
|
export default class ConwaySimulator {
|
||||||
|
/*
|
||||||
/*
|
|
||||||
Create a new simulation. A simulation is comprised of a
|
Create a new simulation. A simulation is comprised of a
|
||||||
2D data grid (rows-by-cols) of ConwayPixels, a canvas element,
|
2D data grid (rows-by-cols) of ConwayPixels, a canvas element,
|
||||||
and a canvas context.
|
and a canvas context.
|
||||||
*/
|
*/
|
||||||
constructor(rows, cols, pixelSize, interRoundDelay) {
|
constructor(rows, cols, pixelSize, interRoundDelay) {
|
||||||
this.rows = rows;
|
this.rows = rows;
|
||||||
this.cols = cols;
|
this.cols = cols;
|
||||||
this.pixelSize = pixelSize;
|
this.pixelSize = pixelSize;
|
||||||
this.interRoundDelay = interRoundDelay;
|
this.interRoundDelay = interRoundDelay;
|
||||||
this.mouseIsDown = false;
|
this.mouseIsDown = false;
|
||||||
this.paused = false;
|
this.paused = false;
|
||||||
this.intervalId = null;
|
this.intervalId = null;
|
||||||
|
|
||||||
// Make the grid
|
// Make the grid
|
||||||
this.grid = [];
|
this.grid = [];
|
||||||
for (let i = 0; i < rows; i++) {
|
for (let i = 0; i < rows; i++) {
|
||||||
this.grid.push([]);
|
this.grid.push([]);
|
||||||
for (let j = 0; j < cols; j++) {
|
for (let j = 0; j < cols; j++) {
|
||||||
let alive = heavyWeightSpaceshipCell(j, i)
|
let alive = heavyWeightSpaceshipCell(j, i);
|
||||||
this.grid[i].push(new ConwayPixel(alive));
|
this.grid[i].push(new ConwayPixel(alive));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Inform each pixel who it's neighbors are (performance optimization)
|
|
||||||
for (let i = 0; i < this.rows; i++) {
|
|
||||||
for (let j = 0; j < this.cols; j++) {
|
|
||||||
this.grid[i][j].neighbors = this.getNeighbors(i, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the canvas
|
|
||||||
let width = this.pixelSize * this.cols
|
|
||||||
let height = this.pixelSize * this.rows
|
|
||||||
this.canvas = document.createElement('canvas');
|
|
||||||
this.canvas.width = width;
|
|
||||||
this.canvas.height = height;
|
|
||||||
this.canvasCtx = this.canvas.getContext('2d', { alpha: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Inform each pixel who it's neighbors are (performance optimization)
|
||||||
|
for (let i = 0; i < this.rows; i++) {
|
||||||
|
for (let j = 0; j < this.cols; j++) {
|
||||||
|
this.grid[i][j].neighbors = this.getNeighbors(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the canvas
|
||||||
|
let width = this.pixelSize * this.cols;
|
||||||
|
let height = this.pixelSize * this.rows;
|
||||||
|
this.canvas = document.createElement("canvas");
|
||||||
|
this.canvas.width = width;
|
||||||
|
this.canvas.height = height;
|
||||||
|
this.canvasCtx = this.canvas.getContext("2d", { alpha: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Starts the simulation via setInterval if it's not running
|
Starts the simulation via setInterval if it's not running
|
||||||
*/
|
*/
|
||||||
start() {
|
start() {
|
||||||
if (this.intervalId) {
|
if (this.intervalId) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
this.intervalId = setInterval(() => {
|
|
||||||
this.advanceRound();
|
|
||||||
this.repaint();
|
|
||||||
}, this.interRoundDelay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
this.intervalId = setInterval(() => {
|
||||||
|
this.advanceRound();
|
||||||
|
this.repaint();
|
||||||
|
}, this.interRoundDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
If the simulation is running, stop it using clearInterval
|
If the simulation is running, stop it using clearInterval
|
||||||
*/
|
*/
|
||||||
stop() {
|
stop() {
|
||||||
if (this.intervalId) {
|
if (this.intervalId) {
|
||||||
clearInterval(this.intervalId);
|
clearInterval(this.intervalId);
|
||||||
this.intervalId = null;
|
this.intervalId = null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return the neighbors of a particular grid location
|
Return the neighbors of a particular grid location
|
||||||
*/
|
*/
|
||||||
getNeighbors(row, col) {
|
getNeighbors(row, col) {
|
||||||
let neighbors = [];
|
let neighbors = [];
|
||||||
for (let i = row - 1; i <= row + 1; i++) {
|
for (let i = row - 1; i <= row + 1; i++) {
|
||||||
for (let j = col - 1; j <= col + 1; j++) {
|
for (let j = col - 1; j <= col + 1; j++) {
|
||||||
if (i === row && j === col) continue;
|
if (i === row && j === col) continue;
|
||||||
if (this.grid[i] && this.grid[i][j]) {
|
if (this.grid[i] && this.grid[i][j]) {
|
||||||
neighbors.push(this.grid[i][j]);
|
neighbors.push(this.grid[i][j]);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return neighbors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
return neighbors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Update the grid according to the rules for each SimEntity
|
Update the grid according to the rules for each SimEntity
|
||||||
*/
|
*/
|
||||||
advanceRound() {
|
advanceRound() {
|
||||||
if (this.mouseIsDown) return;
|
if (this.mouseIsDown) return;
|
||||||
|
|
||||||
// First prepare each pixel (give it a next state)
|
// First prepare each pixel (give it a next state)
|
||||||
for (let i = 0; i < this.rows; i++) {
|
for (let i = 0; i < this.rows; i++) {
|
||||||
for (let j = 0; j < this.cols; j++) {
|
for (let j = 0; j < this.cols; j++) {
|
||||||
this.grid[i][j].prepareUpdate();
|
this.grid[i][j].prepareUpdate();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Then actually advance them, once all the new states are computed
|
|
||||||
for (let i = 0; i < this.rows; i++) {
|
|
||||||
for (let j = 0; j < this.cols; j++) {
|
|
||||||
this.grid[i][j].update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Then actually advance them, once all the new states are computed
|
||||||
|
for (let i = 0; i < this.rows; i++) {
|
||||||
|
for (let j = 0; j < this.cols; j++) {
|
||||||
|
this.grid[i][j].update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Optimized repaint that only updates pixels that have changed, and paints
|
Optimized repaint that only updates pixels that have changed, and paints
|
||||||
in batches by color. Using force will repaint all pixels regardless of their
|
in batches by color. Using force will repaint all pixels regardless of their
|
||||||
state/previousState/nextState, which is slower.
|
state/previousState/nextState, which is slower.
|
||||||
*/
|
*/
|
||||||
repaint(force = false) {
|
repaint(force = false) {
|
||||||
if (this.mouseIsDown && !force) return;
|
if (this.mouseIsDown && !force) return;
|
||||||
|
|
||||||
// Canvas optimization -- it's faster to paint by color than placement.
|
// Canvas optimization -- it's faster to paint by color than placement.
|
||||||
let byColor = {};
|
let byColor = {};
|
||||||
for (let i = 0; i < this.rows; i++) {
|
for (let i = 0; i < this.rows; i++) {
|
||||||
for (let j = 0; j < this.cols; j++) {
|
for (let j = 0; j < this.cols; j++) {
|
||||||
let pixel = this.grid[i][j];
|
let pixel = this.grid[i][j];
|
||||||
|
|
||||||
if (!force && !pixel.forceRepaint && pixel.alive === pixel.previousState) {
|
if (
|
||||||
continue; // No need to repaint if the pixel didn't change
|
!force &&
|
||||||
}
|
!pixel.forceRepaint &&
|
||||||
|
pixel.alive === pixel.previousState
|
||||||
let color = pixel.alive ? pixel.lifeStyle : pixel.deathStyle;
|
) {
|
||||||
if (byColor[color] === undefined) {
|
continue; // No need to repaint if the pixel didn't change
|
||||||
byColor[color] = []
|
|
||||||
}
|
|
||||||
|
|
||||||
byColor[color].push([i, j]);
|
|
||||||
pixel.forceRepaint = false; // Once a pixel is painted, reset it's forced state
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let color in byColor) {
|
let color = pixel.alive ? pixel.lifeStyle : pixel.deathStyle;
|
||||||
this.canvasCtx.fillStyle = color;
|
if (byColor[color] === undefined) {
|
||||||
for (let [row, col] of byColor[color]) {
|
byColor[color] = [];
|
||||||
this.canvasCtx.fillRect(
|
|
||||||
col * this.pixelSize,
|
|
||||||
row * this.pixelSize,
|
|
||||||
this.pixelSize,
|
|
||||||
this.pixelSize
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byColor[color].push([i, j]);
|
||||||
|
pixel.forceRepaint = false; // Once a pixel is painted, reset it's forced state
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
for (let color in byColor) {
|
||||||
|
this.canvasCtx.fillStyle = color;
|
||||||
|
for (let [row, col] of byColor[color]) {
|
||||||
|
this.canvasCtx.fillRect(
|
||||||
|
col * this.pixelSize,
|
||||||
|
row * this.pixelSize,
|
||||||
|
this.pixelSize,
|
||||||
|
this.pixelSize,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Paint an individual pixel. This is not used by repaint because of a batch
|
Paint an individual pixel. This is not used by repaint because of a batch
|
||||||
optimziation. painting an individual pixel does take place when click events
|
optimziation. painting an individual pixel does take place when click events
|
||||||
happen.
|
happen.
|
||||||
*/
|
*/
|
||||||
paintPixel(row, col) {
|
paintPixel(row, col) {
|
||||||
this.grid[row][col].setPaintStyles(this.canvasCtx);
|
this.grid[row][col].setPaintStyles(this.canvasCtx);
|
||||||
this.canvasCtx.fillRect(
|
this.canvasCtx.fillRect(
|
||||||
col * this.pixelSize,
|
col * this.pixelSize,
|
||||||
row * this.pixelSize,
|
row * this.pixelSize,
|
||||||
this.pixelSize,
|
this.pixelSize,
|
||||||
this.pixelSize
|
this.pixelSize,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =============
|
/* =============
|
||||||
Visualizatiuon Modifiers
|
Visualizatiuon Modifiers
|
||||||
================ */
|
================ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Give each entity in the grid an alive style such that when all pixels are alive
|
Give each entity in the grid an alive style such that when all pixels are alive
|
||||||
the grid would be a rainbow gradient.
|
the grid would be a rainbow gradient.
|
||||||
*/
|
*/
|
||||||
setRainbowScheme() {
|
setRainbowScheme() {
|
||||||
let rows = this.grid.length;
|
let rows = this.grid.length;
|
||||||
let cols = this.grid[0].length;
|
let cols = this.grid[0].length;
|
||||||
let diagonalLength = Math.sqrt((this.rows * this.rows) + (this.cols * this.cols));
|
let diagonalLength = Math.sqrt(
|
||||||
let hueIncrement = 360 / diagonalLength;
|
this.rows * this.rows + this.cols * this.cols,
|
||||||
|
);
|
||||||
|
let hueIncrement = 360 / diagonalLength;
|
||||||
|
|
||||||
for (let i = 0; i < this.rows; i++) {
|
for (let i = 0; i < this.rows; i++) {
|
||||||
for (let j = 0; j < this.cols; j++) {
|
for (let j = 0; j < this.cols; j++) {
|
||||||
let h = Math.floor(Math.sqrt((i * i) + (j * j)) * hueIncrement);
|
let h = Math.floor(Math.sqrt(i * i + j * j) * hueIncrement);
|
||||||
let px = this.grid[i][j];
|
let px = this.grid[i][j];
|
||||||
px.lifeStyle = `hsl(${h}, 100%, 60%)`;
|
px.lifeStyle = `hsl(${h}, 100%, 60%)`;
|
||||||
px.deathStyle = `#000000`;
|
px.deathStyle = `#000000`;
|
||||||
px.forceRepaint = true;
|
px.forceRepaint = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Give each entity in the specified area of the grid an alive style
|
Give each entity in the specified area of the grid an alive style
|
||||||
such that when all pixels are alive the area would be a rainbow gradient.
|
such that when all pixels are alive the area would be a rainbow gradient.
|
||||||
*/
|
*/
|
||||||
setRainbowSchemeWithin(startRow, stopRow, startCol, stopCol) {
|
setRainbowSchemeWithin(startRow, stopRow, startCol, stopCol) {
|
||||||
let rows = stopRow - startRow;
|
let rows = stopRow - startRow;
|
||||||
let cols = stopCol - startCol;
|
let cols = stopCol - startCol;
|
||||||
let diagonalLength = Math.sqrt((rows * rows) + (cols * cols));
|
let diagonalLength = Math.sqrt(rows * rows + cols * cols);
|
||||||
let hueIncrement = 360 / diagonalLength;
|
let hueIncrement = 360 / diagonalLength;
|
||||||
|
|
||||||
for (let i = startRow; i < stopRow; i++) {
|
for (let i = startRow; i < stopRow; i++) {
|
||||||
for (let j = startCol; j < stopCol; j++) {
|
for (let j = startCol; j < stopCol; j++) {
|
||||||
let h = Math.floor(Math.sqrt((i * i) + (j * j)) * hueIncrement);
|
let h = Math.floor(Math.sqrt(i * i + j * j) * hueIncrement);
|
||||||
let px = this.grid[i][j];
|
let px = this.grid[i][j];
|
||||||
px.lifeStyle = `hsl(${h}, 100%, 60%)`;
|
px.lifeStyle = `hsl(${h}, 100%, 60%)`;
|
||||||
px.deathStyle = `#000000`;
|
px.deathStyle = `#000000`;
|
||||||
px.forceRepaint = true;
|
px.forceRepaint = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
set colors to the provided parameters
|
set colors to the provided parameters
|
||||||
*/
|
*/
|
||||||
setPixelColors(lifeStyle, deathStyle) {
|
setPixelColors(lifeStyle, deathStyle) {
|
||||||
this.grid.forEach((row) => {
|
this.grid.forEach((row) => {
|
||||||
row.forEach((entity) => {
|
row.forEach((entity) => {
|
||||||
entity.lifeStyle = lifeStyle;
|
entity.lifeStyle = lifeStyle;
|
||||||
entity.deathStyle = deathStyle;
|
entity.deathStyle = deathStyle;
|
||||||
entity.forceRepaint = true;
|
entity.forceRepaint = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Give the board random semi-complementary colors.
|
Give the board random semi-complementary colors.
|
||||||
*/
|
*/
|
||||||
setRandomPixelColors() {
|
setRandomPixelColors() {
|
||||||
let baseHue = randomInteger(1, 360);
|
let baseHue = randomInteger(1, 360);
|
||||||
let complementaryHue = (baseHue + randomInteger(90, 270) % 360);
|
let complementaryHue = baseHue + (randomInteger(90, 270) % 360);
|
||||||
this.setPixelColors(`hsl(${baseHue}, 100%, 60%)`, `hsl(${complementaryHue}, 100%, 60%)`)
|
this.setPixelColors(
|
||||||
}
|
`hsl(${baseHue}, 100%, 60%)`,
|
||||||
|
`hsl(${complementaryHue}, 100%, 60%)`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Given a bounding box, apply the currently selected rules to ONLY the
|
Given a bounding box, apply the currently selected rules to ONLY the
|
||||||
pixels within the provided box.
|
pixels within the provided box.
|
||||||
*/
|
*/
|
||||||
applyColorsWithin(rowStart, rowStop, colStart, colStop, lifeStyle, deathStyle) {
|
applyColorsWithin(
|
||||||
for (let i = rowStart; i < rowStop; i++) {
|
rowStart,
|
||||||
for (let j = colStart; j < colStop; j++) {
|
rowStop,
|
||||||
let pixel = this.grid[i][j];
|
colStart,
|
||||||
pixel.lifeStyle = lifeStyle;
|
colStop,
|
||||||
pixel.deathStyle = deathStyle;
|
lifeStyle,
|
||||||
pixel.forceRepaint = true;
|
deathStyle,
|
||||||
}
|
) {
|
||||||
}
|
for (let i = rowStart; i < rowStop; i++) {
|
||||||
|
for (let j = colStart; j < colStop; j++) {
|
||||||
|
let pixel = this.grid[i][j];
|
||||||
|
pixel.lifeStyle = lifeStyle;
|
||||||
|
pixel.deathStyle = deathStyle;
|
||||||
|
pixel.forceRepaint = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Give a sopecific area of the board random semi-complementary colors.
|
Give a sopecific area of the board random semi-complementary colors.
|
||||||
*/
|
*/
|
||||||
applyRandomColorsWithin(rowStart, rowStop, colStart, colStop) {
|
applyRandomColorsWithin(rowStart, rowStop, colStart, colStop) {
|
||||||
let baseHue = randomInteger(1, 360);
|
let baseHue = randomInteger(1, 360);
|
||||||
let complementaryHue = (baseHue + randomInteger(90, 270) % 360);
|
let complementaryHue = baseHue + (randomInteger(90, 270) % 360);
|
||||||
this.applyColorsWithin(rowStart, rowStop, colStart, `hsl(${baseHue}, 100%, 60%)`, `hsl(${complementaryHue}, 100%, 60%)`)
|
this.applyColorsWithin(
|
||||||
}
|
rowStart,
|
||||||
|
rowStop,
|
||||||
|
colStart,
|
||||||
|
`hsl(${baseHue}, 100%, 60%)`,
|
||||||
|
`hsl(${complementaryHue}, 100%, 60%)`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set all the pixels to alive=false
|
Set all the pixels to alive=false
|
||||||
*/
|
*/
|
||||||
resetLife(chanceOfLife) {
|
resetLife(chanceOfLife) {
|
||||||
this.grid.forEach((row) => {
|
this.grid.forEach((row) => {
|
||||||
row.forEach((pixel) => {
|
row.forEach((pixel) => {
|
||||||
pixel.previousState = pixel.alive;
|
pixel.previousState = pixel.alive;
|
||||||
pixel.alive = Math.random() < chanceOfLife;
|
pixel.alive = Math.random() < chanceOfLife;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.repaint();
|
this.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/*
|
|
||||||
Given a bounding box, apply the currently selected rules to ONLY the
|
Given a bounding box, apply the currently selected rules to ONLY the
|
||||||
pixels within the provided box.
|
pixels within the provided box.
|
||||||
*/
|
*/
|
||||||
resetLifeWithin(rowStart, rowStop, colStart, colStop, chanceOfLife = .1) {
|
resetLifeWithin(rowStart, rowStop, colStart, colStop, chanceOfLife = 0.1) {
|
||||||
for (let i = rowStart; i < rowStop; i++) {
|
for (let i = rowStart; i < rowStop; i++) {
|
||||||
for (let j = colStart; j < colStop; j++) {
|
for (let j = colStart; j < colStop; j++) {
|
||||||
let pixel = this.grid[i][j];
|
let pixel = this.grid[i][j];
|
||||||
if (pixel) {
|
if (pixel) {
|
||||||
pixel.previousState = pixel.alive;
|
pixel.previousState = pixel.alive;
|
||||||
pixel.alive = Math.random() < chanceOfLife;
|
pixel.alive = Math.random() < chanceOfLife;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
this.repaint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
this.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Update the rules for all the pixels
|
Update the rules for all the pixels
|
||||||
*/
|
*/
|
||||||
setRules(underpopulation, overpopulation, reproductionMin, reproductionMax) {
|
setRules(underpopulation, overpopulation, reproductionMin, reproductionMax) {
|
||||||
this.grid.forEach((row) => {
|
this.grid.forEach((row) => {
|
||||||
row.forEach((pixel) => {
|
row.forEach((pixel) => {
|
||||||
pixel.underpopulation = underpopulation;
|
pixel.underpopulation = underpopulation;
|
||||||
pixel.overpopulation = overpopulation;
|
pixel.overpopulation = overpopulation;
|
||||||
pixel.reproductionMin = reproductionMin;
|
pixel.reproductionMin = reproductionMin;
|
||||||
pixel.reproductionMax = reproductionMax;
|
pixel.reproductionMax = reproductionMax;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Swap life and death styles across the center of the grid.
|
Swap life and death styles across the center of the grid.
|
||||||
*/
|
*/
|
||||||
setYinYangMode() {
|
setYinYangMode() {
|
||||||
for (let i = 0; i < this.rows; i++) {
|
for (let i = 0; i < this.rows; i++) {
|
||||||
for (let j = 0; j < this.cols / 2; j++) {
|
for (let j = 0; j < this.cols / 2; j++) {
|
||||||
let t = this.grid[i][j].lifeStyle;
|
let t = this.grid[i][j].lifeStyle;
|
||||||
this.grid[i][j].lifeStyle = this.grid[i][j].deathStyle;
|
this.grid[i][j].lifeStyle = this.grid[i][j].deathStyle;
|
||||||
this.grid[i][j].deathStyle = t;
|
this.grid[i][j].deathStyle = t;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.repaint(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
this.repaint(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Given a bounding box, apply the currently selected rules to ONLY the
|
Given a bounding box, apply the currently selected rules to ONLY the
|
||||||
pixels within the provided box.
|
pixels within the provided box.
|
||||||
*/
|
*/
|
||||||
setRulesWithin(rowStart, rowStop, colStart, colStop, underpopulation, overpopulation, reproductionMin, reproductionMax) {
|
setRulesWithin(
|
||||||
for (let i = rowStart; i < rowStop; i++) {
|
rowStart,
|
||||||
for (let j = colStart; j < colStop; j++) {
|
rowStop,
|
||||||
let pixel = this.grid[i][j];
|
colStart,
|
||||||
pixel.underpopulation = underpopulation;
|
colStop,
|
||||||
pixel.overpopulation = overpopulation;
|
underpopulation,
|
||||||
pixel.reproductionMin = reproductionMin;
|
overpopulation,
|
||||||
pixel.reproductionMax = reproductionMax;
|
reproductionMin,
|
||||||
pixel.forceRepaint = true;
|
reproductionMax,
|
||||||
}
|
) {
|
||||||
}
|
for (let i = rowStart; i < rowStop; i++) {
|
||||||
|
for (let j = colStart; j < colStop; j++) {
|
||||||
|
let pixel = this.grid[i][j];
|
||||||
|
pixel.underpopulation = underpopulation;
|
||||||
|
pixel.overpopulation = overpopulation;
|
||||||
|
pixel.reproductionMin = reproductionMin;
|
||||||
|
pixel.reproductionMax = reproductionMax;
|
||||||
|
pixel.forceRepaint = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The grid has click, and click-and-drag functionality. Entities define their
|
The grid has click, and click-and-drag functionality. Entities define their
|
||||||
own behavior when clicked, and this function ensures the proper entity is
|
own behavior when clicked, and this function ensures the proper entity is
|
||||||
updated when it is clicked (or dragged-over)
|
updated when it is clicked (or dragged-over)
|
||||||
*/
|
*/
|
||||||
registerMouseListeners() {
|
registerMouseListeners() {
|
||||||
bindMultipleEventListener(this.canvas, ['mousemove', 'touchmove'], (e) => {
|
bindMultipleEventListener(this.canvas, ["mousemove", "touchmove"], (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this.mouseIsDown) {
|
if (this.mouseIsDown) {
|
||||||
let x, y;
|
let x, y;
|
||||||
if (e.touches) {
|
if (e.touches) {
|
||||||
let rect = e.target.getBoundingClientRect();
|
let rect = e.target.getBoundingClientRect();
|
||||||
x = Math.floor((e.touches[0].pageX - rect.left) / this.pixelSize);
|
x = Math.floor((e.touches[0].pageX - rect.left) / this.pixelSize);
|
||||||
y = Math.floor((e.touches[0].pageY - rect.top) / this.pixelSize);
|
y = Math.floor((e.touches[0].pageY - rect.top) / this.pixelSize);
|
||||||
}
|
} else {
|
||||||
else {
|
x = Math.floor(e.offsetX / this.pixelSize);
|
||||||
x = Math.floor(e.offsetX / this.pixelSize);
|
y = Math.floor(e.offsetY / this.pixelSize);
|
||||||
y = Math.floor(e.offsetY / this.pixelSize);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.grid[y][x].handleClick();
|
this.grid[y][x].handleClick();
|
||||||
this.paintPixel(y, x);
|
this.paintPixel(y, x);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Capture mouse state for click and drag features
|
// Capture mouse state for click and drag features
|
||||||
bindMultipleEventListener(this.canvas, ['mousedown', 'touchstart'], (e) => {
|
bindMultipleEventListener(this.canvas, ["mousedown", "touchstart"], (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
let rect = e.target.getBoundingClientRect();
|
let rect = e.target.getBoundingClientRect();
|
||||||
let x, y;
|
let x, y;
|
||||||
if (e.touches) {
|
if (e.touches) {
|
||||||
let rect = e.target.getBoundingClientRect();
|
let rect = e.target.getBoundingClientRect();
|
||||||
x = Math.floor((e.touches[0].pageX - rect.left) / this.pixelSize);
|
x = Math.floor((e.touches[0].pageX - rect.left) / this.pixelSize);
|
||||||
y = Math.floor((e.touches[0].pageY - rect.top) / this.pixelSize);
|
y = Math.floor((e.touches[0].pageY - rect.top) / this.pixelSize);
|
||||||
}
|
} else {
|
||||||
else {
|
x = Math.floor(e.offsetX / this.pixelSize);
|
||||||
x = Math.floor(e.offsetX / this.pixelSize);
|
y = Math.floor(e.offsetY / this.pixelSize);
|
||||||
y = Math.floor(e.offsetY / this.pixelSize);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.grid[y][x].handleClick();
|
this.grid[y][x].handleClick();
|
||||||
this.paintPixel(y, x);
|
this.paintPixel(y, x);
|
||||||
this.mouseIsDown = true;
|
this.mouseIsDown = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
bindMultipleEventListener(this.canvas, ['mouseup', 'touchend'], (e) => {
|
bindMultipleEventListener(this.canvas, ["mouseup", "touchend"], (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.mouseIsDown = false;
|
this.mouseIsDown = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A single pixel within a greater ConwaySimulator. Each ConwayPixel has it's own rules for evolution,
|
A single pixel within a greater ConwaySimulator. Each ConwayPixel has it's own rules for evolution,
|
||||||
and for performance reason's maintains a list of it's neighbors inside of it's simulator.
|
and for performance reason's maintains a list of it's neighbors inside of it's simulator.
|
||||||
|
@ -395,32 +421,31 @@ export default class ConwaySimulator {
|
||||||
ConwayPixels outside of the ConwaySimulator class is not advised.
|
ConwayPixels outside of the ConwaySimulator class is not advised.
|
||||||
*/
|
*/
|
||||||
class ConwayPixel {
|
class ConwayPixel {
|
||||||
|
/*
|
||||||
/*
|
|
||||||
Constuct a default ConwayPixel, which follows the original Game of Life rules.
|
Constuct a default ConwayPixel, which follows the original Game of Life rules.
|
||||||
*/
|
*/
|
||||||
constructor(alive) {
|
constructor(alive) {
|
||||||
this.alive = alive;
|
this.alive = alive;
|
||||||
this.lifeStyle = '#000000';
|
this.lifeStyle = "#000000";
|
||||||
this.deathStyle = '#FFFFFF';
|
this.deathStyle = "#F5FFFA";
|
||||||
this.underpopulation = 2;
|
this.underpopulation = 2;
|
||||||
this.overpopulation = 3;
|
this.overpopulation = 3;
|
||||||
this.reproductionMin = 3;
|
this.reproductionMin = 3;
|
||||||
this.reproductionMax = 3;
|
this.reproductionMax = 3;
|
||||||
|
|
||||||
// Experimental improvement...
|
// Experimental improvement...
|
||||||
this.neighbors = [];
|
this.neighbors = [];
|
||||||
this.nextState = null;
|
this.nextState = null;
|
||||||
this.previousState = null;
|
this.previousState = null;
|
||||||
this.forceRepaint = true;
|
this.forceRepaint = true;
|
||||||
|
|
||||||
// Reproduction min cannot be more than reproduction max
|
// Reproduction min cannot be more than reproduction max
|
||||||
if (this.reproductionMax < this.reproductionMin) {
|
if (this.reproductionMax < this.reproductionMin) {
|
||||||
this.reproductionMin = this.reproductionMax
|
this.reproductionMin = this.reproductionMax;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In order to process whole rounds at a time, update returns
|
In order to process whole rounds at a time, update returns
|
||||||
a replacement entity, it does not edit the entity in place.
|
a replacement entity, it does not edit the entity in place.
|
||||||
|
|
||||||
|
@ -438,48 +463,50 @@ class ConwayPixel {
|
||||||
a live cell, as if by reproduction.
|
a live cell, as if by reproduction.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
prepareUpdate() {
|
prepareUpdate() {
|
||||||
let sum = 0;
|
let sum = 0;
|
||||||
let nextState = this.alive;
|
let nextState = this.alive;
|
||||||
|
|
||||||
for (let n of this.neighbors) {
|
for (let n of this.neighbors) {
|
||||||
if (n.alive && n !== this) sum++;
|
if (n.alive && n !== this) sum++;
|
||||||
}
|
|
||||||
|
|
||||||
if (nextState && sum < this.underpopulation) {
|
|
||||||
nextState = false;
|
|
||||||
}
|
|
||||||
else if (nextState && sum > this.overpopulation) {
|
|
||||||
nextState = false;
|
|
||||||
}
|
|
||||||
else if (!nextState && sum >= this.reproductionMin && sum <= this.reproductionMax) {
|
|
||||||
nextState = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.nextState = nextState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (nextState && sum < this.underpopulation) {
|
||||||
|
nextState = false;
|
||||||
|
} else if (nextState && sum > this.overpopulation) {
|
||||||
|
nextState = false;
|
||||||
|
} else if (
|
||||||
|
!nextState &&
|
||||||
|
sum >= this.reproductionMin &&
|
||||||
|
sum <= this.reproductionMax
|
||||||
|
) {
|
||||||
|
nextState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.nextState = nextState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Advance this pixel to it's nextState.
|
Advance this pixel to it's nextState.
|
||||||
*/
|
*/
|
||||||
update() {
|
update() {
|
||||||
this.previousState = this.alive;
|
this.previousState = this.alive;
|
||||||
this.alive = this.nextState;
|
this.alive = this.nextState;
|
||||||
this.nextState = null;
|
this.nextState = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The calling context infers that a click HAS occured, this is not a mouse;
|
The calling context infers that a click HAS occured, this is not a mouse;
|
||||||
this is not an event listener.
|
this is not an event listener.
|
||||||
*/
|
*/
|
||||||
handleClick() {
|
handleClick() {
|
||||||
this.alive = true;
|
this.alive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Provided with a canvas context, paint ourselves!
|
Provided with a canvas context, paint ourselves!
|
||||||
*/
|
*/
|
||||||
setPaintStyles(canvasCtx) {
|
setPaintStyles(canvasCtx) {
|
||||||
canvasCtx.fillStyle = this.alive ? this.lifeStyle : this.deathStyle;
|
canvasCtx.fillStyle = this.alive ? this.lifeStyle : this.deathStyle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
.container {
|
.container {
|
||||||
width: 710px;
|
width: 710px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
margin: 24px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
@ -49,9 +53,14 @@
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title-and-nav hr {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.title-and-gol {
|
.title-and-gol {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
gap: 16px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 110px;
|
height: 110px;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +71,7 @@
|
||||||
max-width: 250;
|
max-width: 250;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
padding-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
35
src/styles/home.css
Normal file
35
src/styles/home.css
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
.posts {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-category {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: #2f4f4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-title {
|
||||||
|
font-size: var(--h4-desktop);
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-summary {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-date {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: gray;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user