Browse Source

wire up weather

master
Stephanie Gredell 3 weeks ago
parent
commit
1c639fc35b
  1. BIN
      Gemini_Generated_Image_60ejy60ejy60ejy6.png
  2. BIN
      cloudy.png
  3. BIN
      cold.png
  4. 2
      game.js
  5. BIN
      hot.png
  6. 46
      index.html
  7. 48
      index.js
  8. 256
      style.css
  9. BIN
      sunny.png

BIN
Gemini_Generated_Image_60ejy60ejy60ejy6.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 846 KiB

BIN
cloudy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

BIN
cold.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

2
game.js

@ -180,7 +180,7 @@ const WeatherChance = [ @@ -180,7 +180,7 @@ const WeatherChance = [
*/
export function init_game() {
return {
player_money: 25.00,
player_money: 2.00,
recipe: {
lemons: 0,
sugar: 0,

BIN
hot.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 KiB

46
index.html

@ -30,6 +30,19 @@ @@ -30,6 +30,19 @@
<button class="go_shopping_btn">Go shopping</button>
</section>
<section class="game_section">
<h2 class="section_title">Recipe</h2>
<p class="section_hint">Per cup of lemonade</p>
<ul class="game_list">
<li>Lemons: <span data-bind="recipe.lemons">0</span></li>
<li>Sugar: <span data-bind="recipe.sugar">0</span></li>
<li>Ice: <span data-bind="recipe.ice">0</span></li>
</ul>
<button class="change_recipe_btn">Change Recipe</button>
</section>
<section class="game_section">
<h2 class="section_title">Total Earnings</h2>
@ -45,10 +58,10 @@ @@ -45,10 +58,10 @@
<button class="change_price_button">Change Price</button>
</section>
<section class="game_section">
<section class="game_section weather_section">
<h2 class="section_title">Weather</h2>
<p>Today's weather is: </p>
<img class="weather_icon" src="sunny.png" alt="Weather">
<p class="weather_label" data-bind="weather">sunny</p>
</section>
</div>
@ -131,6 +144,33 @@ @@ -131,6 +144,33 @@
</div>
</div>
<div class="recipe_modal">
<div class="recipe_modal_content">
<div class="recipe_modal_header">
<h2 class="recipe_modal_title">Set Your Recipe</h2>
<button class="recipe_modal_close">&times;</button>
</div>
<div class="recipe_modal_body">
<p class="recipe_modal_hint">Ingredients per cup of lemonade</p>
<div class="recipe_grid">
<div class="recipe_item">
<label class="recipe_label">Lemons</label>
<input type="number" class="recipe_input" data-recipe="lemons" min="0" max="10" value="1">
</div>
<div class="recipe_item">
<label class="recipe_label">Sugar</label>
<input type="number" class="recipe_input" data-recipe="sugar" min="0" max="10" value="1">
</div>
<div class="recipe_item">
<label class="recipe_label">Ice</label>
<input type="number" class="recipe_input" data-recipe="ice" min="0" max="10" value="3">
</div>
</div>
<button class="recipe_save_btn">Save Recipe</button>
</div>
</div>
</div>
<canvas id="scene" width="1200" height="500"></canvas>
<script type="module" src="index.js"></script>
</body>

48
index.js

@ -11,6 +11,19 @@ import { createReactiveState, updateBindings } from './binding.js'; @@ -11,6 +11,19 @@ import { createReactiveState, updateBindings } from './binding.js';
let gameState = createReactiveState(init_game());
updateBindings(gameState);
// Weather icon element
const weatherIcon = document.querySelector('.weather_icon');
function updateWeatherIcon() {
if (weatherIcon) {
weatherIcon.src = `${gameState.weather}.png`;
weatherIcon.alt = gameState.weather;
}
}
// Initial weather icon update
updateWeatherIcon();
// Wait for all sprites to load, then render once
whenSpritesReady(() => {
render();
@ -35,6 +48,11 @@ const priceInput = document.querySelector('.price_input'); @@ -35,6 +48,11 @@ const priceInput = document.querySelector('.price_input');
const priceSaveBtn = document.querySelector('.price_change_save_btn');
const changeRecipeBtn = document.querySelector('.change_recipe_btn');
const recipeModal = document.querySelector('.recipe_modal');
const recipeModalClose = document.querySelector('.recipe_modal_close');
const recipeSaveBtn = document.querySelector('.recipe_save_btn');
// Shopping modal - quantity inputs and dynamic pricing
const shopQtyInputs = document.querySelectorAll('.shop_qty_input');
const shopBuyBtns = document.querySelectorAll('.shop_item_btn');
@ -110,6 +128,33 @@ if (changePriceBtn) { @@ -110,6 +128,33 @@ if (changePriceBtn) {
priceModal.classList.remove('open');
})
}
// Recipe modal handlers
if (changeRecipeBtn) {
changeRecipeBtn.addEventListener('click', () => {
// Set inputs to current recipe values
document.querySelector('.recipe_input[data-recipe="lemons"]').value = gameState.recipe.lemons;
document.querySelector('.recipe_input[data-recipe="sugar"]').value = gameState.recipe.sugar;
document.querySelector('.recipe_input[data-recipe="ice"]').value = gameState.recipe.ice;
recipeModal.classList.add('open');
});
recipeModalClose.addEventListener('click', () => {
recipeModal.classList.remove('open');
});
recipeSaveBtn.addEventListener('click', () => {
const lemons = parseInt(document.querySelector('.recipe_input[data-recipe="lemons"]').value) || 0;
const sugar = parseInt(document.querySelector('.recipe_input[data-recipe="sugar"]').value) || 0;
const ice = parseInt(document.querySelector('.recipe_input[data-recipe="ice"]').value) || 0;
setState({
recipe: { lemons, sugar, ice }
});
recipeModal.classList.remove('open');
});
}
// Export for debugging in console
window.gameState = gameState;
window.sprites = sprites;
@ -117,4 +162,7 @@ window.cups = cups; @@ -117,4 +162,7 @@ window.cups = cups;
function setState(newState) {
Object.assign(gameState, newState);
if (newState.weather) {
updateWeatherIcon();
}
}

256
style.css

@ -17,8 +17,8 @@ body { @@ -17,8 +17,8 @@ body {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 10px;
}
.game_header_title {
@ -41,14 +41,80 @@ body { @@ -41,14 +41,80 @@ body {
border-radius: 20px;
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
color: #7A6146;
display: flex;
flex-direction: column;
}
.game_section button {
margin-top: auto;
}
/* Weather Section */
.weather_section {
text-align: center;
}
.weather_icon {
width: 80px;
height: 80px;
object-fit: contain;
margin: 8px auto;
display: block;
}
.weather_label {
font-family: 'Fredoka', sans-serif;
font-size: 18px;
font-weight: 500;
color: #5C4632;
text-transform: capitalize;
margin: 0;
}
.game_list {
list-style: none;
margin: 0;
margin: 8px 0;
padding: 0;
}
.game_list li {
display: flex;
justify-content: space-between;
align-items: center;
font-family: 'Inter', sans-serif;
font-size: 14px;
color: #7A6146;
padding: 8px 12px;
margin-bottom: 4px;
background: rgba(255, 255, 255, 0.5);
border-radius: 8px;
}
.game_list li:last-child {
margin-bottom: 0;
}
.game_list li span {
font-family: 'Fredoka', sans-serif;
font-size: 16px;
font-weight: 600;
color: #5C4632;
}
.game_section>p {
font-family: 'Fredoka', sans-serif;
font-size: 28px;
font-weight: 600;
color: #5C4632;
margin: 12px 0;
text-align: center;
}
.game_section .section_hint {
font-size: 11px;
margin: 2px 0 8px;
}
.section_title {
font-family: 'Fredoka', sans-serif;
margin: 0;
@ -57,6 +123,65 @@ body { @@ -57,6 +123,65 @@ body {
letter-spacing: 1px;
}
.section_hint {
font-family: 'Inter', sans-serif;
font-size: 12px;
color: #9a8a7a;
margin: 4px 0 12px;
}
/* Recipe Section */
.recipe_grid {
display: flex;
gap: 12px;
}
.recipe_item {
flex: 1;
text-align: center;
}
.recipe_label {
display: block;
font-family: 'Fredoka', sans-serif;
font-size: 14px;
color: #7A6146;
margin-bottom: 6px;
}
.recipe_input {
font-family: 'Fredoka', sans-serif;
font-size: 20px;
font-weight: 600;
color: #5C4632;
background: linear-gradient(180deg, #fff 0%, #f9f9f5 100%);
border: 2px solid #c5e8a8;
border-radius: 10px;
padding: 10px;
width: 100%;
box-sizing: border-box;
text-align: center;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.06);
transition: all 0.15s ease;
-moz-appearance: textfield;
}
.recipe_input::-webkit-outer-spin-button,
.recipe_input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.recipe_input:hover {
border-color: #8fd16a;
}
.recipe_input:focus {
outline: none;
border-color: #3f7a33;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.06), 0 0 0 3px rgba(143, 209, 106, 0.25);
}
canvas {
width: 1200px;
height: 500px;
@ -451,3 +576,128 @@ canvas { @@ -451,3 +576,128 @@ canvas {
transform: translateY(2px);
box-shadow: 0 2px 0 #3f7a33;
}
/* Change Recipe Button */
.change_recipe_btn {
font-family: 'Fredoka', sans-serif;
font-size: 16px;
font-weight: 600;
background: linear-gradient(180deg, #FDB813 0%, #f5a800 100%);
color: #5C4632;
border: 3px solid #3f7a33;
border-radius: 12px;
padding: 10px 20px;
cursor: pointer;
box-shadow: 0 4px 0 #3f7a33;
transition: all 0.1s ease;
margin: 12px auto 0;
display: block;
}
.change_recipe_btn:hover {
background: linear-gradient(180deg, #ffe066 0%, #FDB813 100%);
transform: translateY(-2px);
box-shadow: 0 6px 0 #3f7a33;
}
.change_recipe_btn:active {
transform: translateY(2px);
box-shadow: 0 2px 0 #3f7a33;
}
/* Recipe Modal */
.recipe_modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 100;
align-items: center;
justify-content: center;
}
.recipe_modal.open {
display: flex;
}
.recipe_modal_content {
background-color: #FFF9E6;
border: 4px solid #8fd16a;
border-radius: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
width: 360px;
max-width: 90%;
}
.recipe_modal_header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
border-bottom: 2px solid #8fd16a;
}
.recipe_modal_title {
font-family: 'Fredoka', sans-serif;
font-size: 24px;
color: #5C4632;
margin: 0;
}
.recipe_modal_close {
font-size: 28px;
font-weight: bold;
color: #7A6146;
background: none;
border: none;
cursor: pointer;
line-height: 1;
padding: 0;
}
.recipe_modal_close:hover {
color: #5C4632;
}
.recipe_modal_body {
padding: 20px;
}
.recipe_modal_hint {
font-family: 'Inter', sans-serif;
font-size: 14px;
color: #7A6146;
margin: 0 0 16px;
text-align: center;
}
.recipe_save_btn {
font-family: 'Fredoka', sans-serif;
font-size: 16px;
font-weight: 600;
background: linear-gradient(180deg, #8fd16a 0%, #7bc256 100%);
color: #fff;
border: 3px solid #3f7a33;
border-radius: 12px;
padding: 10px 32px;
cursor: pointer;
box-shadow: 0 4px 0 #3f7a33;
transition: all 0.1s ease;
margin-top: 16px;
display: block;
width: 100%;
}
.recipe_save_btn:hover {
background: linear-gradient(180deg, #a5e07a 0%, #8fd16a 100%);
transform: translateY(-2px);
box-shadow: 0 6px 0 #3f7a33;
}
.recipe_save_btn:active {
transform: translateY(2px);
box-shadow: 0 2px 0 #3f7a33;
}

BIN
sunny.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Loading…
Cancel
Save