Merge: Incorporate Session 2 statistics panel feature
This commit is contained in:
@@ -1,36 +1,39 @@
|
|||||||
# Cosmic Garden 🌌🌱
|
# Cosmic Garden 🌌🌱
|
||||||
|
|
||||||
An idle/clicker game where you grow a cosmic garden in space!
|
A space gardening idle game built with vanilla HTML, CSS, and JavaScript.
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- **Click to harvest** stardust
|
|
||||||
- **12 unique plants** to grow across 4 tiers
|
|
||||||
- **15+ upgrades** to boost your production
|
|
||||||
- **20 achievements** to unlock
|
|
||||||
- **Auto-save** with offline progress
|
|
||||||
- **Export/Import** saves
|
|
||||||
- **Responsive design** - works on desktop and mobile
|
|
||||||
|
|
||||||
## How to Play
|
## How to Play
|
||||||
|
|
||||||
1. Click the "Collect Stardust" button to earn ✨
|
1. Open `index.html` in your browser
|
||||||
2. Buy plants to generate stardust automatically
|
2. Click the "Collect Stardust" button to earn stardust
|
||||||
3. Purchase upgrades to boost production
|
3. Buy plants to auto-generate stardust
|
||||||
4. Unlock achievements as you progress
|
4. Purchase upgrades to boost production
|
||||||
5. Watch your cosmic garden grow!
|
5. Unlock achievements as you progress
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **12 Unique Plants** across 4 tiers (Star Sprout → Void Fern)
|
||||||
|
- **15+ Upgrades** with requirements and bonuses
|
||||||
|
- **20 Achievements** to unlock
|
||||||
|
- **Core Mechanics**: Click harvesting, auto-production, cost scaling (1.15x per level)
|
||||||
|
- **Save System**: Auto-save every 30s, offline progress (50% efficiency), export/import
|
||||||
|
- **Statistics Panel**: Track your progress with detailed metrics
|
||||||
|
- **UI**: Dark cosmic theme with purple/gold accents, responsive layout, animations
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
This is an ongoing project. Check `JOURNAL.md` for development logs.
|
This project is being developed incrementally. Check `dev-journal.md` for the latest updates.
|
||||||
|
|
||||||
## Running Locally
|
### Current Version
|
||||||
|
- Statistics panel added (2026-08-19)
|
||||||
|
|
||||||
Just open `index.html` in any modern browser. No build step required!
|
### Planned Features
|
||||||
|
- Visual effects (particle effects on click)
|
||||||
|
- Mobile touch optimizations
|
||||||
|
- Prestige/reset system
|
||||||
|
- Sound effects and music
|
||||||
|
- Save game slot system
|
||||||
|
|
||||||
## Tech Stack
|
## License
|
||||||
|
|
||||||
- Vanilla JavaScript (no frameworks)
|
Private project - owned by lullu
|
||||||
- CSS Grid/Flexbox for layout
|
|
||||||
- localStorage for persistence
|
|
||||||
- Base64 export/import for sharing saves
|
|
||||||
|
|||||||
@@ -336,6 +336,47 @@ h2, h3 {
|
|||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Stats Panel */
|
||||||
|
#stats-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
background: var(--bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--accent-gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-bar {
|
||||||
|
height: 8px;
|
||||||
|
background: var(--bg-dark);
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-bar-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, var(--accent-purple), var(--accent-gold));
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
/* Footer */
|
/* Footer */
|
||||||
#game-footer {
|
#game-footer {
|
||||||
background: var(--bg-panel);
|
background: var(--bg-panel);
|
||||||
|
|||||||
+25
-49
@@ -1,55 +1,31 @@
|
|||||||
# Cosmic Garden - Development Journal
|
# Dev Journal - Cosmic Garden
|
||||||
|
|
||||||
## Session Log
|
## 2026-08-19 - Statistics Panel Added
|
||||||
|
|
||||||
---
|
### What was done:
|
||||||
|
- Recreated the full Cosmic Garden game foundation (workspace was cleared between sessions)
|
||||||
|
- Added a new **Statistics tab** to the side panel with detailed game metrics
|
||||||
|
- Fixed global production bonus calculation in `game.js`
|
||||||
|
|
||||||
### Session 1 - August 18, 2026 (Initial Build)
|
### New Feature: Statistics Panel
|
||||||
**Time:** Morning
|
The stats panel tracks and displays:
|
||||||
**Status:** ✅ Foundation Complete
|
- Total Stardust Earned
|
||||||
|
- Current Production Rate (✨/sec)
|
||||||
|
- Total Clicks
|
||||||
|
- Click Power
|
||||||
|
- Time Played (formatted as HH:MM:SS)
|
||||||
|
- Buildings Owned
|
||||||
|
- Upgrades Purchased (with total count)
|
||||||
|
- Achievements Unlocked (with total count)
|
||||||
|
- Game Progress bar (percentage based on total stardust milestones)
|
||||||
|
|
||||||
#### What was done:
|
### Files Modified/Created:
|
||||||
- Created complete game structure with HTML/CSS/JS architecture
|
- `index.html` - Added Stats tab button and content area
|
||||||
- Theme: **"Cosmic Garden"** - a space gardening idle game
|
- `js/stats.js` - New file for statistics tracking and rendering
|
||||||
- Built core game engine (`game.js`) with:
|
- `js/game.js` - Fixed global bonus calculation in `getProductionPerSecond()`
|
||||||
- Game state management
|
- `css/game.css` - Added styles for stats panel elements
|
||||||
- Click harvesting mechanic
|
|
||||||
- Building purchase system with scaling costs (1.15x per level)
|
|
||||||
- Upgrade system with requirements
|
|
||||||
- Achievement tracking
|
|
||||||
- Auto-save every 30 seconds
|
|
||||||
- Offline progress calculation (50% efficiency)
|
|
||||||
- Export/Import save functionality
|
|
||||||
- Designed 12 buildings across 4 tiers:
|
|
||||||
- Tier 1: Star Sprout, Moon Bloom, Solar Leaf
|
|
||||||
- Tier 2: Nebula Vine, Comet Rose, Asteroid Cactus
|
|
||||||
- Tier 3: Pulsar Palm, Black Hole Orchid, Galaxy Tree
|
|
||||||
- Tier 4: Cosmic Lotus, Supernova Tulip, Void Fern
|
|
||||||
- Added 15+ upgrades with click bonuses, building multipliers, and global boosts
|
|
||||||
- Created 20 achievements tracking clicks, stardust earned, buildings owned, and production rates
|
|
||||||
- Built responsive dark-themed UI with purple/gold cosmic aesthetic
|
|
||||||
- Implemented floating text animations on clicks
|
|
||||||
- Added notification system for purchases and achievements
|
|
||||||
|
|
||||||
#### Files created:
|
### Next Up:
|
||||||
- `index.html` - Main HTML structure
|
- Visual effects (particle effects on click)
|
||||||
- `css/game.css` - Complete styling (10KB+)
|
|
||||||
- `js/game.js` - Core game engine
|
|
||||||
- `js/buildings.js` - Building definitions
|
|
||||||
- `js/upgrades.js` - Upgrade definitions
|
|
||||||
- `js/achievements.js` - Achievement system
|
|
||||||
- `js/ui.js` - UI management
|
|
||||||
- `js/saveSystem.js` - Save/load/export/import
|
|
||||||
- `js/main.js` - Entry point
|
|
||||||
|
|
||||||
#### Next sessions planned:
|
|
||||||
- Add visual polish (animations, particles)
|
|
||||||
- Implement prestige/reset system
|
|
||||||
- Add more buildings and upgrades
|
|
||||||
- Sound effects and music
|
|
||||||
- Mobile touch optimizations
|
- Mobile touch optimizations
|
||||||
- Statistics page
|
- Prestige/reset system
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Journal auto-updated by Hermes Agent cron job*
|
|
||||||
|
|||||||
+8
-1
@@ -49,6 +49,7 @@
|
|||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<button class="tab-btn active" data-tab="upgrades">Upgrades</button>
|
<button class="tab-btn active" data-tab="upgrades">Upgrades</button>
|
||||||
<button class="tab-btn" data-tab="achievements">Achievements</button>
|
<button class="tab-btn" data-tab="achievements">Achievements</button>
|
||||||
|
<button class="tab-btn" data-tab="stats">Stats</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="upgrades-tab" class="tab-content active">
|
<div id="upgrades-tab" class="tab-content active">
|
||||||
@@ -57,9 +58,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="achievements-tab" class="tab-content">
|
<div id="achievements-tab" class="tab-content">
|
||||||
<h3>Achievements</h3>
|
<h3>Achievements (0/20)</h3>
|
||||||
<div id="achievements-list"></div>
|
<div id="achievements-list"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="stats-tab" class="tab-content">
|
||||||
|
<h3>Statistics</h3>
|
||||||
|
<div id="stats-content"></div>
|
||||||
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -95,6 +101,7 @@
|
|||||||
<script src="js/upgrades.js"></script>
|
<script src="js/upgrades.js"></script>
|
||||||
<script src="js/achievements.js"></script>
|
<script src="js/achievements.js"></script>
|
||||||
<script src="js/ui.js"></script>
|
<script src="js/ui.js"></script>
|
||||||
|
<script src="js/stats.js"></script>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+5
-1
@@ -33,6 +33,7 @@ const Game = {
|
|||||||
this.startGameLoop();
|
this.startGameLoop();
|
||||||
this.startAutoSave();
|
this.startAutoSave();
|
||||||
UI.init();
|
UI.init();
|
||||||
|
Stats.init();
|
||||||
console.log('🌌 Cosmic Garden initialized!');
|
console.log('🌌 Cosmic Garden initialized!');
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -115,7 +116,7 @@ const Game = {
|
|||||||
* Get current click power
|
* Get current click power
|
||||||
*/
|
*/
|
||||||
getClickPower() {
|
getClickPower() {
|
||||||
let power = this.config.baseClickPower || 1;
|
let power = 1;
|
||||||
|
|
||||||
// Apply upgrade bonuses
|
// Apply upgrade bonuses
|
||||||
for (const upgradeId of this.state.upgrades) {
|
for (const upgradeId of this.state.upgrades) {
|
||||||
@@ -148,6 +149,9 @@ const Game = {
|
|||||||
if (upgrade && upgrade.buildingBonus && upgrade.buildingBonus[buildingId]) {
|
if (upgrade && upgrade.buildingBonus && upgrade.buildingBonus[buildingId]) {
|
||||||
production *= upgrade.buildingBonus[buildingId];
|
production *= upgrade.buildingBonus[buildingId];
|
||||||
}
|
}
|
||||||
|
if (upgrade && upgrade.globalBonus) {
|
||||||
|
production *= upgrade.globalBonus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
total += production;
|
total += production;
|
||||||
|
|||||||
+160
@@ -0,0 +1,160 @@
|
|||||||
|
/**
|
||||||
|
* Cosmic Garden - Statistics Panel
|
||||||
|
* Tracks and displays game statistics
|
||||||
|
*/
|
||||||
|
|
||||||
|
const Stats = {
|
||||||
|
/**
|
||||||
|
* Initialize the stats panel
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
this.render();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the stats panel
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
const container = document.getElementById('stats-content');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
container.innerHTML = `
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">Total Stardust Earned</div>
|
||||||
|
<div class="stat-value" id="stat-total-stardust">0 ✨</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">Current Production</div>
|
||||||
|
<div class="stat-value" id="stat-production">0 ✨/sec</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">Total Clicks</div>
|
||||||
|
<div class="stat-value" id="stat-clicks">0</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">Click Power</div>
|
||||||
|
<div class="stat-value" id="stat-click-power">1 ✨</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">Time Played</div>
|
||||||
|
<div class="stat-value" id="stat-time-played">0:00:00</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">Buildings Owned</div>
|
||||||
|
<div class="stat-value" id="stat-buildings">0</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">Upgrades Purchased</div>
|
||||||
|
<div class="stat-value" id="stat-upgrades">0/${Object.keys(UPGRADES).length}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">Achievements Unlocked</div>
|
||||||
|
<div class="stat-value" id="stat-achievements">0/${Object.keys(ACHIEVEMENTS).length}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">Game Progress</div>
|
||||||
|
<div class="stat-bar">
|
||||||
|
<div class="stat-bar-fill" id="stat-progress-bar" style="width: 0%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update stats display
|
||||||
|
*/
|
||||||
|
update() {
|
||||||
|
// Total stardust
|
||||||
|
const totalStardustEl = document.getElementById('stat-total-stardust');
|
||||||
|
if (totalStardustEl) {
|
||||||
|
totalStardustEl.textContent = `${Game.formatNumber(Game.state.totalStardust)} ✨`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current production
|
||||||
|
const productionEl = document.getElementById('stat-production');
|
||||||
|
if (productionEl) {
|
||||||
|
productionEl.textContent = `${Game.formatNumber(Game.getProductionPerSecond())} ✨/sec`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total clicks
|
||||||
|
const clicksEl = document.getElementById('stat-clicks');
|
||||||
|
if (clicksEl) {
|
||||||
|
clicksEl.textContent = Game.formatNumber(Game.state.totalClicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click power
|
||||||
|
const clickPowerEl = document.getElementById('stat-click-power');
|
||||||
|
if (clickPowerEl) {
|
||||||
|
clickPowerEl.textContent = `${Game.formatNumber(Game.getClickPower())} ✨`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time played
|
||||||
|
const timePlayedEl = document.getElementById('stat-time-played');
|
||||||
|
if (timePlayedEl) {
|
||||||
|
const elapsed = Math.floor((Date.now() - Game.state.startTime) / 1000);
|
||||||
|
timePlayedEl.textContent = this.formatTime(elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buildings owned
|
||||||
|
const buildingsEl = document.getElementById('stat-buildings');
|
||||||
|
if (buildingsEl) {
|
||||||
|
const total = Object.values(Game.state.buildings).reduce((a, b) => a + b, 0);
|
||||||
|
buildingsEl.textContent = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upgrades purchased
|
||||||
|
const upgradesEl = document.getElementById('stat-upgrades');
|
||||||
|
if (upgradesEl) {
|
||||||
|
upgradesEl.textContent = `${Game.state.upgrades.length}/${Object.keys(UPGRADES).length}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Achievements unlocked
|
||||||
|
const achievementsEl = document.getElementById('stat-achievements');
|
||||||
|
if (achievementsEl) {
|
||||||
|
achievementsEl.textContent = `${Achievements.getCount()}/${Achievements.getTotal()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Game progress (based on total stardust milestones)
|
||||||
|
const progressBarEl = document.getElementById('stat-progress-bar');
|
||||||
|
if (progressBarEl) {
|
||||||
|
const progress = this.calculateProgress();
|
||||||
|
progressBarEl.style.width = `${progress}%`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format elapsed time as HH:MM:SS
|
||||||
|
*/
|
||||||
|
formatTime(seconds) {
|
||||||
|
const hours = Math.floor(seconds / 3600);
|
||||||
|
const minutes = Math.floor((seconds % 3600) / 60);
|
||||||
|
const secs = seconds % 60;
|
||||||
|
|
||||||
|
if (hours > 0) {
|
||||||
|
return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
return `${minutes}:${secs.toString().padStart(2, '0')}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate game progress percentage
|
||||||
|
* Based on total stardust earned vs all building costs combined
|
||||||
|
*/
|
||||||
|
calculateProgress() {
|
||||||
|
let totalCost = 0;
|
||||||
|
for (const building of Object.values(BUILDINGS)) {
|
||||||
|
// Approximate cost to buy one of each building
|
||||||
|
totalCost += building.baseCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add upgrade costs
|
||||||
|
for (const upgrade of Object.values(UPGRADES)) {
|
||||||
|
totalCost += upgrade.cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
const progress = Math.min(100, (Game.state.totalStardust / totalCost) * 100);
|
||||||
|
return Math.round(progress);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.Stats = Stats;
|
||||||
Reference in New Issue
Block a user