feat: Remove wolves, add markets, hospitals, schools, and new citizen types
This commit is contained in:
215
game.js
Normal file
215
game.js
Normal file
@@ -0,0 +1,215 @@
|
||||
/**********************************************************************
|
||||
* GAME CORE
|
||||
**********************************************************************/
|
||||
let frameCount = 0;
|
||||
let money = 5000; // Start with 5000
|
||||
let purchaseMode = null;
|
||||
|
||||
// Shared city storage (wood, etc.)
|
||||
const cityStorage = {
|
||||
wood: 0,
|
||||
food: 0,
|
||||
medicine: 0,
|
||||
knowledge: 0
|
||||
};
|
||||
|
||||
// Arrays
|
||||
let resources = []; // Trees, FruitTrees
|
||||
let buildings = []; // House, Road, Market, Hospital, School
|
||||
let citizens = [];
|
||||
let animals = [];
|
||||
|
||||
/**********************************************************************
|
||||
* COSTS & EARNINGS
|
||||
**********************************************************************/
|
||||
const COST_HOUSE = 300;
|
||||
const COST_ROAD = 150;
|
||||
const COST_BUILDER = 100;
|
||||
const COST_FARMER = 100;
|
||||
const COST_MERCHANT = 150;
|
||||
const COST_DOCTOR = 200;
|
||||
const COST_TEACHER = 180;
|
||||
const COST_MARKET = 400;
|
||||
const COST_HOSPITAL = 500;
|
||||
const COST_SCHOOL = 450;
|
||||
const COST_SPAWNER = 500;
|
||||
const COST_TREE = 50;
|
||||
|
||||
// Earn money
|
||||
const REWARD_DELIVER_WOOD = 5;
|
||||
const REWARD_BUILD_COMPLETE = 20;
|
||||
const REWARD_MARKET_INCOME = 15;
|
||||
const REWARD_EDUCATION = 10;
|
||||
|
||||
/**********************************************************************
|
||||
* STATS & CONSTANTS
|
||||
**********************************************************************/
|
||||
// Hunger & energy
|
||||
const HUNGER_MAX = 100;
|
||||
const ENERGY_MAX = 100;
|
||||
const HEALTH_MAX = 100;
|
||||
const EDUCATION_MAX = 100;
|
||||
|
||||
const HUNGER_INCREMENT = 0.005;
|
||||
const ENERGY_DECREMENT_WORK = 0.02;
|
||||
const ENERGY_INCREMENT_REST = 0.05;
|
||||
const HUNGER_THRESHOLD = 50;
|
||||
const ENERGY_THRESHOLD = 30;
|
||||
const HEALTH_THRESHOLD = 40;
|
||||
|
||||
// Trees
|
||||
const FRUIT_TREE_START_AMOUNT = 20;
|
||||
const FRUIT_GATHER_RATE = 1;
|
||||
const FRUIT_PLANT_COST = 1;
|
||||
|
||||
// House & Road
|
||||
const HOUSE_WOOD_REQUIRED = 50;
|
||||
const HOUSE_BUILD_RATE = 0.2;
|
||||
const HOUSE_MAX_FRUIT = 30;
|
||||
|
||||
const ROAD_WOOD_REQUIRED = 10;
|
||||
const ROAD_BUILD_RATE = 0.3;
|
||||
|
||||
// Market, Hospital, School
|
||||
const MARKET_WOOD_REQUIRED = 60;
|
||||
const MARKET_BUILD_RATE = 0.15;
|
||||
|
||||
const HOSPITAL_WOOD_REQUIRED = 70;
|
||||
const HOSPITAL_BUILD_RATE = 0.1;
|
||||
|
||||
const SCHOOL_WOOD_REQUIRED = 65;
|
||||
const SCHOOL_BUILD_RATE = 0.12;
|
||||
|
||||
// Professions
|
||||
const PROFESSIONS = ["Farmer", "Builder", "Merchant", "Doctor", "Teacher"];
|
||||
|
||||
// Rabbits
|
||||
const STARTING_RABBITS = 10;
|
||||
const RABBIT_HUNGER_INCREMENT = 0.003;
|
||||
const RABBIT_REPRO_COOLDOWN = 3000;
|
||||
const RABBIT_REPRO_CHANCE = 0.0005;
|
||||
|
||||
/**********************************************************************
|
||||
* INIT WORLD
|
||||
**********************************************************************/
|
||||
function initWorld() {
|
||||
// Normal trees
|
||||
for(let i=0; i<15; i++) {
|
||||
resources.push(createResource("Tree", randInt(-1000,1000), randInt(-1000,1000), 100));
|
||||
}
|
||||
// Fruit trees
|
||||
for(let i=0; i<10; i++) {
|
||||
resources.push(createResource("FruitTree", randInt(-1000,1000), randInt(-1000,1000), FRUIT_TREE_START_AMOUNT));
|
||||
}
|
||||
|
||||
// Start with 1 citizen => always a "Builder"
|
||||
let c = createCitizen(randomName(), randInt(-200,200), randInt(-200,200), "Builder");
|
||||
citizens.push(c);
|
||||
logAction(`Initial Citizen joined: ${c.name} [Builder]`);
|
||||
|
||||
// Spawn some rabbits
|
||||
for(let i=0; i<STARTING_RABBITS; i++) {
|
||||
animals.push(createAnimal("Rabbit", randInt(-1000,1000), randInt(-1000,1000)));
|
||||
}
|
||||
|
||||
requestAnimationFrame(update);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* UPDATE LOOP
|
||||
**********************************************************************/
|
||||
function update() {
|
||||
frameCount++;
|
||||
|
||||
// Citizens
|
||||
citizens.forEach((cit) => updateCitizen(cit));
|
||||
|
||||
// Animals
|
||||
animals.forEach((ani) => {
|
||||
if(!ani.dead) updateAnimal(ani);
|
||||
});
|
||||
animals = animals.filter(a => !a.dead);
|
||||
|
||||
// Automatic new citizen every 3000 frames
|
||||
if(frameCount % 3000 === 0) {
|
||||
let baby = createCitizen(randomName(), randInt(-200,200), randInt(-200,200));
|
||||
citizens.push(baby);
|
||||
logAction(`A new citizen is born: ${baby.name} [${baby.profession}]`);
|
||||
}
|
||||
|
||||
// Buildings
|
||||
buildings.forEach((b) => {
|
||||
if(!b.completed && b.deliveredWood >= b.requiredWood) {
|
||||
let buildRate;
|
||||
switch(b.buildingType) {
|
||||
case "Road": buildRate = ROAD_BUILD_RATE; break;
|
||||
case "House": buildRate = HOUSE_BUILD_RATE; break;
|
||||
case "Market": buildRate = MARKET_BUILD_RATE; break;
|
||||
case "Hospital": buildRate = HOSPITAL_BUILD_RATE; break;
|
||||
case "School": buildRate = SCHOOL_BUILD_RATE; break;
|
||||
default: buildRate = HOUSE_BUILD_RATE;
|
||||
}
|
||||
|
||||
b.buildProgress += buildRate;
|
||||
if(b.buildProgress >= 100) {
|
||||
b.completed = true;
|
||||
addMoney(REWARD_BUILD_COMPLETE, `Complete ${b.buildingType}`);
|
||||
if(b.buildingType === "House") {
|
||||
logAction(`A new House completed @(${Math.floor(b.x)},${Math.floor(b.y)})!`);
|
||||
maybeBuildRoad(b);
|
||||
} else if(b.buildingType === "Road") {
|
||||
logAction(`A Road has been completed!`);
|
||||
} else if(b.buildingType === "Market") {
|
||||
logAction(`A Market has been completed! Will generate income.`);
|
||||
} else if(b.buildingType === "Hospital") {
|
||||
logAction(`A Hospital has been completed! Citizens can heal here.`);
|
||||
} else if(b.buildingType === "School") {
|
||||
logAction(`A School has been completed! Citizens can learn here.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special building functions
|
||||
if(b.completed) {
|
||||
if(b.buildingType === "Market" && frameCount % 500 === 0) {
|
||||
addMoney(REWARD_MARKET_INCOME, "Market income");
|
||||
}
|
||||
if(b.buildingType === "School" && frameCount % 800 === 0) {
|
||||
addMoney(REWARD_EDUCATION, "Education benefits");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
drawWorld();
|
||||
updateHUD();
|
||||
requestAnimationFrame(update);
|
||||
}
|
||||
|
||||
function updateHUD() {
|
||||
// Update money and citizen count
|
||||
moneyDisplay.textContent = `Money: $${money}`;
|
||||
citizenCountDisplay.textContent = `Citizens: ${citizens.length}`;
|
||||
|
||||
// Update resource counts
|
||||
woodDisplay.textContent = `Wood: ${cityStorage.wood}`;
|
||||
foodDisplay.textContent = `Food: ${cityStorage.food}`;
|
||||
medicineDisplay.textContent = `Medicine: ${cityStorage.medicine}`;
|
||||
knowledgeDisplay.textContent = `Knowledge: ${cityStorage.knowledge}`;
|
||||
|
||||
// Update building counts
|
||||
const houseCount = buildings.filter(b => b.buildingType === "House" && b.completed).length;
|
||||
const marketCount = buildings.filter(b => b.buildingType === "Market" && b.completed).length;
|
||||
const hospitalCount = buildings.filter(b => b.buildingType === "Hospital" && b.completed).length;
|
||||
const schoolCount = buildings.filter(b => b.buildingType === "School" && b.completed).length;
|
||||
|
||||
buildingCountsDisplay.textContent = `Buildings: 🏠${houseCount} 🏪${marketCount} 🏥${hospitalCount} 🏫${schoolCount}`;
|
||||
|
||||
// Update profession counts
|
||||
const builderCount = citizens.filter(c => c.profession === "Builder").length;
|
||||
const farmerCount = citizens.filter(c => c.profession === "Farmer").length;
|
||||
const merchantCount = citizens.filter(c => c.profession === "Merchant").length;
|
||||
const doctorCount = citizens.filter(c => c.profession === "Doctor").length;
|
||||
const teacherCount = citizens.filter(c => c.profession === "Teacher").length;
|
||||
|
||||
professionCountsDisplay.textContent = `Citizens: 👷${builderCount} 🌾${farmerCount} 💰${merchantCount} 💉${doctorCount} 📚${teacherCount}`;
|
||||
}
|
||||
Reference in New Issue
Block a user