more ui fixes
This commit is contained in:
parent
f88acb2182
commit
e7623335d3
143
index.html
143
index.html
|
|
@ -7,16 +7,17 @@
|
|||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Wrap canvas in a scalable container -->
|
||||
<div id="simCanvasWrapper">
|
||||
<canvas id="simCanvas"></canvas>
|
||||
</div>
|
||||
|
||||
<!-- Loading Overlay -->
|
||||
<div id="loadingOverlay">
|
||||
<div class="sinewave">Fast Forwarding...</div>
|
||||
</div>
|
||||
|
||||
<!-- Small "?" Help Button -->
|
||||
<button id="helpButton" class="help-button">?</button>
|
||||
|
||||
<!-- Help Modal (Hidden By Default) -->
|
||||
<div id="helpModal" class="help-modal">
|
||||
<div class="help-content">
|
||||
|
|
@ -45,6 +46,8 @@
|
|||
<div id="controlPanel" class="control-panel">
|
||||
<div class="header">
|
||||
Simulation Controls
|
||||
<!-- Move the help button here -->
|
||||
<button id="helpButton" class="help-button">?</button>
|
||||
<button class="minimize">–</button>
|
||||
</div>
|
||||
<div class="content">
|
||||
|
|
@ -54,8 +57,8 @@
|
|||
<button class="tabBtn active" data-tab="rewardTab">Reward</button>
|
||||
<button class="tabBtn" data-tab="foodTab">Food</button>
|
||||
<button class="tabBtn" data-tab="snakesTab">Snakes</button>
|
||||
<button class="tabBtn" data-tab="evolutionTab">Evolution</button>
|
||||
<button class="tabBtn" data-tab="environmentTab">Environment</button>
|
||||
<!-- Combine Evolution + Environment => 'World' main tab -->
|
||||
<button class="tabBtn" data-tab="worldTab">World</button>
|
||||
</div>
|
||||
|
||||
<!-- REWARD TAB (with 2 sub-tabs) -->
|
||||
|
|
@ -159,10 +162,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SNAKES TAB -->
|
||||
<!-- SNAKES TAB (now subdivided) -->
|
||||
<div id="snakesTab" class="tab-content">
|
||||
<div class="tab-buttons snakes-subtabs">
|
||||
<button class="tabBtn active" data-subtab="snakesGeneralSubTab">General</button>
|
||||
<button class="tabBtn" data-subtab="snakesBoostSubTab">Boost & Turn</button>
|
||||
</div>
|
||||
|
||||
<!-- Sub-tab 1: General -->
|
||||
<div id="snakesGeneralSubTab" class="snakes-sub-content active">
|
||||
<div class="tab-description">
|
||||
Control the number of snakes and their intelligence or speed.
|
||||
Control the basic snake population, speed, and brain size.
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="snakeCountSlider">Snake Count:</label>
|
||||
|
|
@ -180,37 +190,6 @@
|
|||
Snakes turn at a rate up to 0.15 / (lengthFactor) * speed; higher is more agile.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Slider: Base Turn Rate -->
|
||||
<div class="control-group">
|
||||
<label for="turnRateSlider">Base Turn Rate:</label>
|
||||
<input type="range" id="turnRateSlider" min="0.01" max="0.3" step="0.01" value="0.15">
|
||||
<span id="turnRateVal">0.15</span>
|
||||
<div class="setting-description">
|
||||
Controls how sharply snakes can turn (before factoring in size).
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Slider: Boost Cost (length/sec) -->
|
||||
<div class="control-group">
|
||||
<label for="boostCostSlider">Boost Cost (length/sec):</label>
|
||||
<input type="range" id="boostCostSlider" min="0" max="5" step="0.1" value="1">
|
||||
<span id="boostCostVal">1</span>
|
||||
<div class="setting-description">
|
||||
How many body length units are spent per second while boosting.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Slider: Boost Speed Multiplier -->
|
||||
<div class="control-group">
|
||||
<label for="boostMultiplierSlider">Boost Speed Multiplier:</label>
|
||||
<input type="range" id="boostMultiplierSlider" min="1" max="3" step="0.1" value="2">
|
||||
<span id="boostMultiplierVal">2</span>
|
||||
<div class="setting-description">
|
||||
How much faster the snake goes when boosting.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label for="brainSizeSlider">Brain Size:</label>
|
||||
<input type="range" id="brainSizeSlider" min="5" max="50" value="15" step="1">
|
||||
|
|
@ -221,8 +200,70 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- EVOLUTION TAB -->
|
||||
<div id="evolutionTab" class="tab-content">
|
||||
<!-- Sub-tab 2: Boost & Turn -->
|
||||
<div id="snakesBoostSubTab" class="snakes-sub-content">
|
||||
<div class="tab-description">
|
||||
Manage the base turn rate and boosting parameters.
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="turnRateSlider">Base Turn Rate:</label>
|
||||
<input type="range" id="turnRateSlider" min="0.01" max="0.3" step="0.01" value="0.15">
|
||||
<span id="turnRateVal">0.15</span>
|
||||
<div class="setting-description">
|
||||
Controls how sharply snakes can turn (before factoring in size).
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="boostCostSlider">Boost Cost (length/sec):</label>
|
||||
<input type="range" id="boostCostSlider" min="0" max="5" step="0.1" value="1">
|
||||
<span id="boostCostVal">1</span>
|
||||
<div class="setting-description">
|
||||
How many body length units are spent per second while boosting.
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="boostMultiplierSlider">Boost Speed Multiplier:</label>
|
||||
<input type="range" id="boostMultiplierSlider" min="1" max="3" step="0.1" value="2">
|
||||
<span id="boostMultiplierVal">2</span>
|
||||
<div class="setting-description">
|
||||
How much faster the snake goes when boosting.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- COMBINED "WORLD" TAB with 2 sub-tabs (Environment + Evolution) -->
|
||||
<div id="worldTab" class="tab-content">
|
||||
<div class="tab-buttons world-subtabs">
|
||||
<button class="tabBtn active" data-subtab="worldEnvSubTab">Environment</button>
|
||||
<button class="tabBtn" data-subtab="worldEvoSubTab">Evolution</button>
|
||||
</div>
|
||||
|
||||
<!-- Sub-tab 1: Environment (old environmentTab content) -->
|
||||
<div id="worldEnvSubTab" class="world-sub-content active">
|
||||
<div class="tab-description">
|
||||
Adjust environmental parameters that affect food and snake respawning.
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="foodDecayTimeSlider">Food Decay Time:</label>
|
||||
<input type="range" id="foodDecayTimeSlider" min="500" max="5000" value="2000" step="100">
|
||||
<span id="foodDecayTimeVal">2000</span>
|
||||
<div class="setting-description">
|
||||
Time (ms) before dropped food disappears.
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="respawnDelaySlider">Respawn Delay:</label>
|
||||
<input type="range" id="respawnDelaySlider" min="0" max="5" value="0" step="0.5">
|
||||
<span id="respawnDelayVal">0</span>
|
||||
<div class="setting-description">
|
||||
Delay (sec) before a new snake spawns after one dies.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sub-tab 2: Evolution (old evolutionTab content) -->
|
||||
<div id="worldEvoSubTab" class="world-sub-content">
|
||||
<div class="tab-description">
|
||||
Adjust evolutionary parameters to influence genetic changes.
|
||||
</div>
|
||||
|
|
@ -243,28 +284,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ENVIRONMENT TAB -->
|
||||
<div id="environmentTab" class="tab-content">
|
||||
<div class="tab-description">
|
||||
Adjust environmental parameters that affect food and snake respawning.
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="foodDecayTimeSlider">Food Decay Time:</label>
|
||||
<input type="range" id="foodDecayTimeSlider" min="500" max="5000" value="2000" step="100">
|
||||
<span id="foodDecayTimeVal">2000</span>
|
||||
<div class="setting-description">
|
||||
Time (ms) before dropped food disappears.
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="respawnDelaySlider">Respawn Delay:</label>
|
||||
<input type="range" id="respawnDelaySlider" min="0" max="5" value="0" step="0.5">
|
||||
<span id="respawnDelayVal">0</span>
|
||||
<div class="setting-description">
|
||||
Delay (sec) before a new snake spawns after one dies.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-buttons">
|
||||
|
|
|
|||
70
script.js
70
script.js
|
|
@ -9,7 +9,7 @@ let lastFrameTime = null;
|
|||
|
||||
/* Updated defaults */
|
||||
const DEFAULT_BRAIN_SIZE = 15;
|
||||
const DEFAULT_SNAKE_SPEED = 3.5;
|
||||
const DEFAULT_SNAKE_SPEED = 1;
|
||||
const DEFAULT_MAX_FOOD = 120;
|
||||
const DEFAULT_SPAWN_CHANCE = 3;
|
||||
const DEFAULT_FOOD_POINTS = 3;
|
||||
|
|
@ -17,9 +17,9 @@ const DEFAULT_DROPPED_FOOD_POINTS = 10;
|
|||
const DEFAULT_SURVIVAL_BONUS = 2;
|
||||
const DEFAULT_BODY_LENGTH_INCREMENT = 10;
|
||||
const DEFAULT_THICKNESS_INCREMENT = 0.05;
|
||||
const DEFAULT_SNAKE_COUNT = 30;
|
||||
const DEFAULT_LENGTH_BONUS = 1;
|
||||
const DEFAULT_KILL_BONUS = 0;
|
||||
const DEFAULT_SNAKE_COUNT = 15;
|
||||
const DEFAULT_LENGTH_BONUS = 3;
|
||||
const DEFAULT_KILL_BONUS = 3;
|
||||
|
||||
/* Evolution & Environment Defaults */
|
||||
const DEFAULT_MUTATION_RATE = 0.1;
|
||||
|
|
@ -188,6 +188,11 @@ function removeDraggable(panel) {
|
|||
attachMinimizeLogic(clone);
|
||||
attachTopLevelTabLogic(clone);
|
||||
attachRewardSubTabLogic(clone);
|
||||
|
||||
// new calls for sub-tabs:
|
||||
attachSnakesSubTabLogic(clone);
|
||||
attachWorldSubTabLogic(clone);
|
||||
|
||||
wireUIEvents();
|
||||
}
|
||||
|
||||
|
|
@ -284,6 +289,48 @@ function attachRewardSubTabLogic(panel) {
|
|||
});
|
||||
});
|
||||
}
|
||||
/* NEW: Attach snakes sub-tab logic */
|
||||
function attachSnakesSubTabLogic(panel) {
|
||||
const snakesTab = panel.querySelector('#snakesTab');
|
||||
if (!snakesTab) return;
|
||||
|
||||
const subTabButtons = snakesTab.querySelectorAll('.snakes-subtabs .tabBtn');
|
||||
subTabButtons.forEach(subBtn => {
|
||||
subBtn.addEventListener('click', () => {
|
||||
subTabButtons.forEach(b => b.classList.remove('active'));
|
||||
const allSubContents = snakesTab.querySelectorAll('.snakes-sub-content');
|
||||
allSubContents.forEach(s => s.classList.remove('active'));
|
||||
|
||||
subBtn.classList.add('active');
|
||||
const subId = subBtn.getAttribute('data-subtab');
|
||||
const targetSub = snakesTab.querySelector('#' + subId);
|
||||
if (targetSub) {
|
||||
targetSub.classList.add('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
/* NEW: Attach world sub-tab logic */
|
||||
function attachWorldSubTabLogic(panel) {
|
||||
const worldTab = panel.querySelector('#worldTab');
|
||||
if (!worldTab) return;
|
||||
|
||||
const subTabButtons = worldTab.querySelectorAll('.world-subtabs .tabBtn');
|
||||
subTabButtons.forEach(subBtn => {
|
||||
subBtn.addEventListener('click', () => {
|
||||
subTabButtons.forEach(b => b.classList.remove('active'));
|
||||
const allSubContents = worldTab.querySelectorAll('.world-sub-content');
|
||||
allSubContents.forEach(s => s.classList.remove('active'));
|
||||
|
||||
subBtn.classList.add('active');
|
||||
const subId = subBtn.getAttribute('data-subtab');
|
||||
const targetSub = worldTab.querySelector('#' + subId);
|
||||
if (targetSub) {
|
||||
targetSub.classList.add('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* Wire up UI events (sliders, etc.) */
|
||||
function wireUIEvents() {
|
||||
|
|
@ -1107,8 +1154,23 @@ function init() {
|
|||
|
||||
attachTopLevelTabLogic(document.getElementById("controlPanel"));
|
||||
attachRewardSubTabLogic(document.getElementById("controlPanel"));
|
||||
attachSnakesSubTabLogic(document.getElementById("controlPanel"));
|
||||
attachWorldSubTabLogic(document.getElementById("controlPanel"));
|
||||
attachTopLevelTabLogic(document.getElementById("timeAndLeaderboardPanel"));
|
||||
|
||||
wireUIEvents();
|
||||
|
||||
// Wire up the help button to open the modal
|
||||
const helpBtn = document.getElementById('helpButton');
|
||||
const helpModal = document.getElementById('helpModal');
|
||||
const helpClose = document.getElementById('helpClose');
|
||||
if (helpBtn && helpModal && helpClose) {
|
||||
helpBtn.onclick = () => {
|
||||
helpModal.style.display = 'flex';
|
||||
};
|
||||
helpClose.onclick = () => {
|
||||
helpModal.style.display = 'none';
|
||||
};
|
||||
}
|
||||
}
|
||||
init();
|
||||
|
|
|
|||
92
styles.css
92
styles.css
|
|
@ -10,11 +10,24 @@ html, body {
|
|||
color: #FFF;
|
||||
}
|
||||
|
||||
/* Canvas covers the entire window */
|
||||
/* Wrap the canvas so we can scale the entire simulation if desired */
|
||||
#simCanvasWrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* Default scale for desktop */
|
||||
transform: scale(1.0);
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
/* On mobile (below 1000px), scale differently. Adjust as desired. */
|
||||
@media (max-width: 1000px) {
|
||||
#simCanvasWrapper {
|
||||
transform: scale(0.85); /* Or scale(1.2) if you want larger on mobile */
|
||||
}
|
||||
}
|
||||
|
||||
/* The canvas inside the wrapper */
|
||||
canvas {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
|
|
@ -34,7 +47,7 @@ canvas {
|
|||
background: linear-gradient(135deg, rgba(20,0,40,0.8), rgba(0,0,0,0.6));
|
||||
}
|
||||
|
||||
/* widths: make both 420px to match each other in desktop */
|
||||
/* widths: make both 420px for desktop */
|
||||
.control-panel {
|
||||
width: 420px;
|
||||
left: 50%;
|
||||
|
|
@ -165,6 +178,60 @@ canvas {
|
|||
display: block;
|
||||
}
|
||||
|
||||
/* Sub-tabs for Snakes */
|
||||
.snakes-subtabs {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.snakes-subtabs .tabBtn {
|
||||
flex: 1;
|
||||
margin: 0 2px;
|
||||
background: #444;
|
||||
border: none;
|
||||
color: #FFF;
|
||||
cursor: pointer;
|
||||
padding: 4px 8px;
|
||||
font-weight: bold;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.snakes-subtabs .tabBtn.active {
|
||||
background: linear-gradient(90deg, #8000ff 0%, #ff00ff 100%);
|
||||
box-shadow: 0 0 5px rgba(255,0,255,0.4);
|
||||
}
|
||||
.snakes-sub-content {
|
||||
display: none;
|
||||
}
|
||||
.snakes-sub-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Sub-tabs for 'World' (Environment + Evolution) */
|
||||
.world-subtabs {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.world-subtabs .tabBtn {
|
||||
flex: 1;
|
||||
margin: 0 2px;
|
||||
background: #444;
|
||||
border: none;
|
||||
color: #FFF;
|
||||
cursor: pointer;
|
||||
padding: 4px 8px;
|
||||
font-weight: bold;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.world-subtabs .tabBtn.active {
|
||||
background: linear-gradient(90deg, #8000ff 0%, #ff00ff 100%);
|
||||
box-shadow: 0 0 5px rgba(255,0,255,0.4);
|
||||
}
|
||||
.world-sub-content {
|
||||
display: none;
|
||||
}
|
||||
.world-sub-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* .tab-content is used for top-level content areas */
|
||||
.tab-content {
|
||||
display: none; /* hidden by default */
|
||||
|
|
@ -219,20 +286,16 @@ canvas {
|
|||
animation: sinewave 1s infinite;
|
||||
}
|
||||
|
||||
/* Center the "?" help button on the right edge */
|
||||
/* Help Button style (no longer absolutely positioned) */
|
||||
.help-button {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 10px;
|
||||
transform: translateY(-50%);
|
||||
z-index: 3;
|
||||
margin-left: 8px;
|
||||
background: #444;
|
||||
border: 1px solid #555;
|
||||
color: #FFF;
|
||||
font-size: 16px;
|
||||
padding: 4px 8px;
|
||||
font-size: 14px;
|
||||
padding: 2px 6px;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 8px rgba(255,0,255,0.5);
|
||||
}
|
||||
.help-button:hover {
|
||||
|
|
@ -295,6 +358,7 @@ canvas {
|
|||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
/* Stack the leaderboards vertically in mobile to avoid overflow */
|
||||
.leaderboardColumn {
|
||||
width: 100% !important;
|
||||
|
|
|
|||
Loading…
Reference in New Issue