Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Survival Simulation</title>
- <style>
- body {
- margin: 0;
- overflow: hidden;
- background: #000000; /* Black background for the canvas */
- }
- canvas {
- display: block; /* Removes scrollbars */
- }
- </style>
- </head>
- <body>
- <canvas id="canvas" width="1000" height="700"></canvas>
- <script>
- // Get the canvas context
- const canvas = document.getElementById('canvas');
- const ctx = canvas.getContext('2d');
- // Utility functions to generate random values and calculate distance
- function random(min, max) {
- return Math.random() * (max - min) + min;
- }
- function distance(ax, ay, bx, by) {
- return Math.hypot(ax - bx, ay - by);
- }
- // The Food class - Represents food objects that creatures can eat
- class Food {
- constructor(x, y) {
- this.x = x;
- this.y = y;
- this.radius = 4;
- this.color = 'green';
- }
- // Draw the food on the canvas
- draw() {
- ctx.beginPath();
- ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
- ctx.fillStyle = this.color;
- ctx.fill();
- }
- }
- // The Creature class - Represents creatures that move, eat, reproduce, and die
- class Creature {
- constructor(x, y, species) {
- this.x = x;
- this.y = y;
- this.radius = 10;
- this.species = species;
- this.color = species.color;
- this.speed = species.speed;
- this.sight = species.sight;
- this.energy = 100;
- this.age = 0;
- this.maxAge = 1200; // Maximum age (2 minutes)
- this.target = null;
- this.matingCooldown = 0;
- this.isFemale = Math.random() > 0.5; // Randomly assign gender
- this.isNewborn = true;
- }
- // Update the creature's status each frame (movement, energy, etc.)
- update(foodArray, creatures) {
- this.age++;
- this.energy -= 0.05; // Gradually lose energy
- if (this.matingCooldown > 0) this.matingCooldown--; // Handle mating cooldown
- // Handle food search behavior
- if (!this.target) {
- this.target = foodArray.find(f => distance(this.x, this.y, f.x, f.y) < this.sight);
- }
- if (this.target) {
- this.moveTowards(this.target);
- if (distance(this.x, this.y, this.target.x, this.target.y) < this.radius + this.target.radius) {
- this.energy += 40; // Gain energy from food
- foodArray.splice(foodArray.indexOf(this.target), 1); // Remove food
- this.target = null;
- }
- } else {
- this.exploreRandomly();
- }
- // Keep the creature within bounds
- this.x = Math.max(this.radius, Math.min(canvas.width - this.radius, this.x));
- this.y = Math.max(this.radius, Math.min(canvas.height - this.radius, this.y));
- }
- // Move the creature towards its target (food)
- moveTowards(target) {
- const angle = Math.atan2(target.y - this.y, target.x - this.x);
- this.x += Math.cos(angle) * this.speed;
- this.y += Math.sin(angle) * this.speed;
- }
- // If no food is found, explore randomly in the area
- exploreRandomly() {
- this.x += random(-1, 1) * this.speed;
- this.y += random(-1, 1) * this.speed;
- }
- // Check if the creature should die based on energy or age
- shouldDie() {
- return this.energy <= 0 || this.age >= this.maxAge;
- }
- // Check if the creature is ready to reproduce
- shouldReproduce() {
- return this.energy >= 160 && this.matingCooldown === 0 && !this.isNewborn;
- }
- // Reproduce a new creature with mutated traits
- reproduce() {
- this.energy -= 80;
- this.matingCooldown = 100; // Cooldown period after mating
- const mutationFactor = 0.1;
- const newSpeed = Math.max(0.5, this.speed + random(-mutationFactor, mutationFactor));
- const newSight = Math.max(40, this.sight + random(-mutationFactor * 100, mutationFactor * 100));
- const childSpecies = {
- name: this.species.name,
- color: this.color,
- speed: newSpeed,
- sight: newSight
- };
- // Create a new creature with slightly modified traits
- return new Creature(this.x + random(-10, 10), this.y + random(-10, 10), childSpecies);
- }
- // Draw the creature on the canvas
- draw() {
- ctx.beginPath();
- ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
- ctx.fillStyle = this.color;
- ctx.fill();
- // Draw sight radius for visualization
- ctx.beginPath();
- ctx.arc(this.x, this.y, this.sight, 0, Math.PI * 2);
- ctx.strokeStyle = this.color;
- ctx.lineWidth = 0.2;
- ctx.stroke();
- // Draw indicator if the creature is a newborn
- if (this.isNewborn) {
- ctx.strokeStyle = 'yellow';
- ctx.lineWidth = 2;
- ctx.stroke();
- }
- }
- }
- // Species definition (e.g., red and blue creatures with different stats)
- const speciesList = [
- { name: 'Red', color: 'red', speed: 1.2, sight: 100 },
- { name: 'Blue', color: 'blue', speed: 1.0, sight: 120 }
- ];
- const creatures = [];
- const food = [];
- // Spawn initial creatures based on species
- function spawnInitialCreatures() {
- for (let species of speciesList) {
- creatures.push(new Creature(random(100, 900), random(100, 600), species));
- creatures.push(new Creature(random(100, 900), random(100, 600), species));
- }
- }
- // Spawn a specified amount of food at random locations
- function spawnFood(amount = 20) {
- for (let i = 0; i < amount; i++) {
- food.push(new Food(random(0, canvas.width), random(0, canvas.height)));
- }
- }
- // Handle the main simulation loop
- function loop() {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- // Update and draw each creature
- for (let i = creatures.length - 1; i >= 0; i--) {
- const creature = creatures[i];
- creature.update(food, creatures);
- // Remove creatures that should die
- if (creature.shouldDie()) {
- creatures.splice(i, 1);
- } else if (creature.shouldReproduce()) {
- creatures.push(creature.reproduce());
- }
- // Draw the creature
- creature.draw();
- }
- // Draw food objects
- for (let f of food) f.draw();
- // Spawn new food occasionally
- if (Math.random() < 0.02) spawnFood(1);
- // Update the population counter (number of creatures)
- document.getElementById('population').innerText = `Population: ${creatures.length}`;
- requestAnimationFrame(loop);
- }
- // Initial setup and start the simulation
- spawnInitialCreatures();
- spawnFood(50);
- loop();
- // Display population
- const populationDiv = document.createElement('div');
- populationDiv.id = 'population';
- populationDiv.style.position = 'absolute';
- populationDiv.style.color = 'white';
- populationDiv.style.fontSize = '20px';
- populationDiv.style.top = '10px';
- populationDiv.style.left = '10px';
- document.body.appendChild(populationDiv);
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement