Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions src/iframe/life-game.html
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
<html lang="ja">
<html lang="ja" style="height: 90%">
<head>
<meta charset="utf-8" />
<title>Title</title>
</head>
<body>
<h1>
<div id="generation">第0世代</div>
</h1>
ボードのサイズ<span id="sizeLabel"></span>:
<input type="number" id="sizeInput" style="width: 50px" />
<button id="sizeChangeButton">サイズ変更</button>

<body
style="
height: 100%;
display: flex;
align-items: flex-start;
justify-content: center;
padding-top: 10px;
"
>
<table id="game-board" style="border-collapse: collapse"></table>
<button id="randombutton">RANDOM</button>
<button id="resetbutton">RESET</button>

<button id="saveButton">SAVE</button>
<button id="loadButton">LOAD</button>
<div id="pattern-button-container"></div>

<script src="./life-game.js"></script>
</body>
</html>
107 changes: 54 additions & 53 deletions src/iframe/life-game.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ let timerId = 0;
let generationFigure = 0;
let timerTime = 1000;

//変数設定
const defaultBoardSize = 20;
const defaultCellSize = 22;
let boardSize = defaultBoardSize;
let CELL_SIZE = defaultCellSize;
const BOARD_MIN = 100;
const BOARD_MAX = 10;
const defaultCellSize = 30;

//変数設定
let boardSize = 20;
let CELL_SIZE = 30;

// around: 周囲の生きたセル数 self: 自身が生きているかどうか
function isNextAlive(around, self) {
Expand All @@ -26,22 +25,8 @@ function isNextAlive(around, self) {
return false;
}

const generation = document.getElementById("generation"); //世代を表す文(第+数字+世代)
//BUTTON
const randomButton = document.getElementById("randombutton");
const resetButton = document.getElementById("resetbutton");
const sizeChangeButton = document.getElementById("sizeChangeButton");
const saveButton = document.getElementById("saveButton");
const loadButton = document.getElementById("loadButton");
//サイズ入力欄
const sizeInput = document.getElementById("sizeInput");
const sizeLabel = document.getElementById("sizeLabel");

// サイズ入力欄の設定
sizeInput.min = BOARD_MAX;
sizeInput.max = BOARD_MIN;
sizeInput.value = defaultBoardSize;
sizeLabel.textContent = `(${BOARD_MAX}〜${BOARD_MIN})`;

//Boardの初期化
let board = Array.from({ length: boardSize }, () => Array.from({ length: boardSize }, () => false));
Expand Down Expand Up @@ -80,28 +65,16 @@ function renderBoard() {
renderBoard();
progressBoard();

randomButton.onclick = () => {
//白黒ランダムにBoardを変更
board = Array.from({ length: boardSize }, () =>
Array.from({ length: boardSize }, () => Math.random() > 0.5),
);
renderBoard();
generationChange(0);
stop();
};

resetButton.onclick = () => {
//すべて白にBoardを変更
board = Array.from({ length: boardSize }, () => Array.from({ length: boardSize }, () => false));
renderBoard();
generationChange(0);
stop();
};

function generationChange(num) {
//現在の世代を表すgenerationFigureを変更し、文章も変更
generationFigure = num;
generation.textContent = "第" + generationFigure + "世代";
window.parent.postMessage(
{
type: "generation_change",
data: generationFigure,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これしようとすると大変になってくるので、外側で世代とかの情報を管理して、「世代交代」だけを iframe に渡すのがいいんじゃないかな。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intervalの間隔は編集可能にしておきたいのでその辺のコードは外に置きたくないってのがあります。
この先似たようなのが増えるわけではない(はず)なので複雑さもそこまでひどくならないとは思いますが...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interval ってこっちで編集機能を用意しておくんじゃなかったっけ?

それならそれでもいいと思う

},
"*",
);
}

function progressBoard() {
Expand Down Expand Up @@ -166,6 +139,34 @@ on.resize = (newBoardSize) => {
boardSize = newBoardSize;
};

on.boardreset = () => {
//すべて白にBoardを変更
board = Array.from({ length: boardSize }, () => Array.from({ length: boardSize }, () => false));
renderBoard();
generationChange(0);
on.pause();
};

on.boardrandom = () => {
//白黒ランダムにBoardを変更
board = Array.from({ length: boardSize }, () =>
Array.from({ length: boardSize }, () => Math.random() > 0.5),
);
renderBoard();
generationChange(0);
on.pause();
};

on.sizechange = (newSizenum) => {
const newSize = parseInt(newSizenum, 10);
boardSize = newSize;
CELL_SIZE = Math.floor(defaultCellSize * (defaultBoardSize / newSize));
board = Array.from({ length: boardSize }, () => Array.from({ length: boardSize }, () => false));
renderBoard();
generationChange(0);
on.pause();
};

on.timer_change = (ms) => {
timerTime = ms;
if (timer === "start") {
Expand All @@ -174,22 +175,22 @@ on.timer_change = (ms) => {
}
};

sizeChangeButton.onclick = () => {
const newSize = parseInt(sizeInput.value, 10);
if (isNaN(newSize) || newSize < BOARD_MAX || BOARD_MIN < newSize) {
alert(`サイズは ${BOARD_MAX} から ${BOARD_MIN} の間で入力してください。`);
sizeInput.value = boardSize;
return;
}
boardSize = newSize;
CELL_SIZE = Math.floor(defaultCellSize * (defaultBoardSize / newSize));
board = Array.from({ length: boardSize }, () => Array.from({ length: boardSize }, () => false));
renderBoard();
generationChange(0);
stop();
updatePatternButtons();
on.stateupdate = () => {
window.parent.postMessage(
{
type: "stateupdate",
data: {
generationFigure: generationFigure,
boardSize: boardSize,
},
},
"*",
);
console.log("generationFigure:", generationFigure, "boardSize:", boardSize);
};

on.sizechange(boardSize);

saveButton.onclick = async () => {
window.parent.postMessage({ type: "save_board", data: board }, "*");
};
Expand Down
112 changes: 88 additions & 24 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
import { onMount } from "svelte";
import { loadBoard, saveBoard } from "./api.ts";

let code = $state(lifeGameJS);
let editingcode = $state(lifeGameJS);
let appliedCode = $state(lifeGameJS);

let previewDoc = $derived(
lifeGameHTML.replace(
/<script src="\.\/life-game\.js"><\/script>/,
`<script>
\n${event}\n
\n${lifeGameJS}\n
\n${appliedCode}\n
\n${placetemplate}\n
<\/script>`,
),
Expand All @@ -25,17 +26,32 @@
let showEditor = $state(true);
let preview_iframe: HTMLIFrameElement | undefined = $state();
let isProgress = $state(false);
let intervalMs = 1000;
let drawerOpen = $state(false);
let resetModalOpen = $state(false);
let bottomDrawerOpen = $state(false);

let intervalMs = $state(1000);
let generationFigure = $state(0);
let sizeInputValue = $state(20);

onMount(() => {
window.addEventListener("message", (event) => {
const handleMessage = (event: MessageEvent) => {
if (event.data.type === "patternError") {
alert(event.data.message);
}
});
if (event.data.type === "generation_change") {
generationFigure = event.data.data;
}
if (event.data.type === "stateupdate") {
generationFigure = event.data.data.generationFigure;
sizeInputValue = event.data.data.boardSize;
}
};

window.addEventListener("message", handleMessage);

return () => {
window.removeEventListener("message", handleMessage);
};
});

function sendEvent(event: string, message?: unknown) {
Expand Down Expand Up @@ -71,20 +87,11 @@
</script>

<div class="navbar bg-[#E0E0E0] shadow-sm">
<button
class="btn btn-sm btn-ghost btn-circle bg-[#E0E0E0] mx-5 w-8 rounded border-none"
onclick={() => {
drawerOpen = !drawerOpen;
}}
>
<img src={icons.bars_3} alt="settings" />
</button>

<div class="mx-5 avatar w-8 rounded">
<div class="ml-15 avatar w-8 rounded">
<img src={icons.utcode} alt="ut.code();_Logo" />
</div>

<div class="font-semibold text-black text-[20px]">Life code</div>
<div class="font-semibold text-black text-[20px] ml-5">Life code</div>

<button
class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] ml-auto"
Expand Down Expand Up @@ -158,7 +165,7 @@
</div>
</div>

<div class="flex h-screen box-border">
<div class="flex box-border h-screen" style="height: calc(100vh - 4rem - 3rem);">
<div
class={[
"flex overflow-hidden bg-[rgb(202,202,202)] shrink-0 transition-[flex-basis] duration-300 ease-in-out",
Expand All @@ -170,7 +177,13 @@
srcdoc={previewDoc}
title="Preview"
sandbox="allow-scripts"
class="w-[90%] h-[80%] rounded-lg m-auto shadow-lg"
class="w-[80%] h-[90%] rounded-lg mx-auto my-5 shadow-lg"
onload={() => {
setTimeout(() => {
sendEvent("stateupdate");
console.log("generationFigure onload:", generationFigure);
}, 50);
}}
></iframe>
</div>

Expand All @@ -180,19 +193,42 @@
showEditor ? "basis-[40%] opacity-100" : "basis-0 opacity-0",
]}
>
<textarea bind:value={code} class="w-full h-full border-none p-4 font-mono bg-black text-[#0f0]"
<textarea
bind:value={editingcode}
class="w-full h-full border-none p-4 font-mono bg-black text-[#0f0]"
></textarea>
</div>
</div>

<div class="bg-[#E0E0E0] shadow-sm fixed bottom-0 left-0 right-0 z-50 h-12 p-0">
<div class="bg-[#E0E0E0] shadow-sm fixed bottom-0 left-0 right-0 z-50 h-12 p-0 flex items-center">
<button
class="btn rounded-none h-12 justify-start"
onclick={() => (bottomDrawerOpen = !bottomDrawerOpen)}
>
{bottomDrawerOpen ? "▼" : "▲ テンプレート"}
</button>

<div class="font-bold text-black ml-10">
第 {generationFigure} 世代
</div>

<p class="ml-10 text-black">ボードのサイズ(10~100):</p>
<input type="number" bind:value={sizeInputValue} class="w-10 text-black bg-white ml-2" />

<button
class="btn btn-ghost hover:bg-[rgb(220,220,220)] text-black ml-2"
onclick={() => {
isProgress = false;
if (isNaN(sizeInputValue) || sizeInputValue < 10 || sizeInputValue > 100) {
alert("サイズは10から100の間で指定してください。");
return;
}
sendEvent("sizechange", sizeInputValue.toString());
}}
>
Change
</button>

<div
class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] swap fixed left-1/2 !-translate-x-1/2 -ml-15 bottom-1"
>
Expand All @@ -219,7 +255,35 @@
</div>

<button
class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] swap ml-2"
class="btn btn-ghost hover:bg-[rgb(220,220,220)] ml-100 text-black"
onclick={() => {
isProgress = false;
sendEvent("boardreset");
}}
>
Reset
</button>

<button
class="btn btn-ghost hover:bg-[rgb(220,220,220)] text-black"
onclick={() => {
isProgress = false;
sendEvent("boardrandom");
}}
>
Random
</button>

<button
class="btn btn-ghost hover:bg-[rgb(220,220,220)] ml-5 text-black"
onclick={() => {
appliedCode = editingcode;
}}
>
Apply Code
</button>
<button
class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] text-black ml-2"
onclick={() => {
intervalMs = intervalMs / 2;
sendEvent("timer_change", intervalMs);
Expand All @@ -229,7 +293,7 @@
</button>

<button
class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] swap ml-2"
class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] text-black ml-2"
onclick={() => {
intervalMs = intervalMs * 2;
sendEvent("timer_change", intervalMs);
Expand All @@ -239,7 +303,7 @@
</button>

<button
class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] swap ml-2"
class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] text-black ml-2"
onclick={() => {
intervalMs = 1000;
sendEvent("timer_change", intervalMs);
Expand Down