我正在创建一个生态系统,其代码由植物,草食动物和食肉动物组成,并用圆圈表示。出于某种原因,我的代码在经过30秒到8分钟(但不超过此时间)的一定时间后一直崩溃。
进行了一些挖掘之后,我发现崩溃是由于我的对象的.rad属性由于某种原因而变得未定义的结果。可能是由于我不正确地设置函数而导致的,但是我找不到解决方法。
var plantSpawn = 5;
var herbSpawn = 3;
var carnSpawn = 2;
var myPlants = new Array();
var myCarns = new Array();
var myHerbs = new Array();
//////////////PLANTS//////////////////
function createPlants() {
reproducePlants();
setInterval(reproducePlants, 5000);
}
function reproducePlants() {
for(var p=0; p<plantSpawn; p++){
var rr = Math.round(Math.random() * 150);
var gg = Math.round(Math.random() * 255);
var bb = Math.round(Math.random() * 150);
var plant = new Object();
plant.x = Math.random() * canvas.width;
plant.y = Math.random() * canvas.height;
plant.rad = 2 + Math.random()*2;
plant.skin = 'rgba('+rr+','+gg+','+bb+', 1)';
myPlants.push(plant);
}
}
function drawPlants(){
var plantAmt = myPlants.length;
for(var j=0; j<plantAmt; j++) {
if (myPlants[j].x + myPlants[j].rad >= canvas.width) {
myPlants[j].x -= 10;
}
if (myPlants[j].y + myPlants[j].rad >= canvas.height) {
myPlants[j].y -= 10;
}
context.beginPath();
context.arc(myPlants[j].x, myPlants[j].y, myPlants[j].rad, 0, Math.PI*2, false);
context.closePath();
context.fillStyle = myPlants[j].skin;
context.fill();
}
}
function killPlants() {
plantDeath();
setInterval(plantDeath, 30000); //play with inc
}
function plantDeath() {
myPlants.splice(0,5);
}
//////////////HERBS//////////////////
function herbsLife(){
reproduceHerbs();
setInterval(reproduceHerbs, 10000);
herbsDeath();
setInterval(herbsDeath, 90000); //1.5 minutes
setInterval(herbsStarve, 10000); //10 seconds
}
function reproduceHerbs() {
for (var h=0; h<herbSpawn; h++){
var gg = Math.round(Math.random() * 100);
var bb = Math.round(Math.random() * 255);
var herbivore = new Object();
herbivore.x = Math.random() * canvas.width;
herbivore.y = Math.random() * canvas.height;
herbivore.rad = 5 + Math.random()*3;
herbivore.skin = 'rgba(0,'+gg+','+bb+', 1)';
herbivore.speedH = -3 + Math.random()*1.2;
herbivore.speedV = -3 + Math.random()*1.2;
herbivore.dirH = 1;
herbivore.dirV = 1;
myHerbs.push(herbivore);
}
}
function drawHerbs() {
var herbAmt = myHerbs.length;
for(var j=0; j<herbAmt; j++) {
var hX = myHerbs[j].x;
var hY = myHerbs[j].y;
//HERB MOVEMENT//
myHerbs[j].x += myHerbs[j].dirH * myHerbs[j].speedH;
if (myHerbs[j].x > canvas.width + myHerbs[j].rad || myHerbs[j].x < 0){
myHerbs[j].dirH *= -1;
}
myHerbs[j].y += myHerbs[j].dirV * myHerbs[j].speedV;
if (myHerbs[j].y > canvas.height + myHerbs[j].rad || myHerbs[j].y < 0){
myHerbs[j].dirV *= -1;
}
context.beginPath();
context.arc(myHerbs[j].x, myHerbs[j].y, myHerbs[j].rad, 0, Math.PI*2, false);
context.closePath();
context.fillStyle = myHerbs[j].skin;
context.fill();
}
}
function herbsDeath() {
myHerbs.splice(0,3);
}
function herbsEat() {
for (var k=0; k<myPlants.length; k++){
var pX = myPlants[k].x;
var pY = myPlants[k].y;
for (var h=0; h<myHerbs.length; h++){
var hX = myHerbs[h].x;
var hY = myHerbs[h].y;
var eX = hX - pX;
var eY = hY - pY;
var dist = Math.sqrt(Math.pow(eX,2) + Math.pow(eY,2));
if (dist < myPlants[k].rad*2) {
myPlants.splice(k,1);
myHerbs[h].rad += 1;
}
}
}
}
function herbsStarve() {
for (var s=0; s<myPlants.length; s++){
myHerbs[s].rad -= 1;
if (myHerbs[s].rad <= 2) {
myHerbs.splice(s,1);
}
}
}
//////////////CARNS//////////////////
function carnsLife() {
reproduceCarns();
setInterval(reproduceCarns, 20000); //20 seconds
carnsDeath();
setInterval(carnsDeath, 60000); //50 seconds
setInterval(carnsStarve, 7500); //10 seconds
}
function reproduceCarns() {
for (var c=0; c<carnSpawn; c++){
var rr = Math.round(Math.random() * 255);
var gg = Math.round(Math.random() * 100);
var carnivore = new Object();
carnivore.x = Math.random() * canvas.width;
carnivore.y = Math.random() * canvas.height;
carnivore.rad = 7 + Math.random()*3;
carnivore.skin = 'rgba('+rr+','+gg+',0, 1)';
//bigger random = slower//
carnivore.speedH = -3 + Math.random()*2;
carnivore.speedV = -3 + Math.random()*2;
carnivore.dirH = 1;
carnivore.dirV = 1;
myCarns.push(carnivore);
}
}
function drawCarns() {
var carnAmt = myCarns.length;
for(var j=0; j<carnAmt; j++) {
//CARN MOVEMENT//
myCarns[j].x += myCarns[j].dirH * myCarns[j].speedH;
if (myCarns[j].x > canvas.width + myCarns[j].rad || myCarns[j].x < 0){
myCarns[j].dirH *= -1;
}
myCarns[j].y += myCarns[j].dirV * myCarns[j].speedV;
if (myCarns[j].y > canvas.height + myCarns[j].rad || myCarns[j].y < 0){
myCarns[j].dirV *= -1;
}
context.beginPath();
context.arc(myCarns[j].x, myCarns[j].y, myCarns[j].rad, 0, Math.PI*2, false);
context.closePath();
context.fillStyle = myCarns[j].skin;
context.fill();
}
}
function carnsDeath() {
myCarns.splice(0,2);
}
function carnsEat() {
for (var k=0; k<myCarns.length; k++){
var cX = myCarns[k].x;
var cY = myCarns[k].y;
for (var h=0; h<myHerbs.length; h++){
var hX = myHerbs[h].x;
var hY = myHerbs[h].y;
var eX = cX - hX;
var eY = cY - hY;
var dist = Math.sqrt(Math.pow(eX,2) + Math.pow(eY,2));
if (dist < myCarns[k].rad*1.2 && myCarns[k].rad > myHerbs[h].rad) {
myHerbs.splice(h,1);
myCarns[k].rad += 1;
}
}
}
}
function carnsStarve() {
for (var q=0; q<myPlants.length; q++){
myCarns[q].rad = myCarns[q].rad - 1;
if (myCarns[q].rad <= 5) {
myCarns.splice(q,1);
}
}
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title> Ecosystem </title>
<!-- import external .js scripts here -->
<script type="text/javascript" src="Creatures.js" ></script>
<!-- modify CSS properties here -->
<style type="text/css">
body,td,th {
font-family: Monaco, "Courier New", "monospace";
font-size: 14px;
color: rgba(255,255,255,1);
}
body {
background-color: rgba(0,0,0,1);
}
#container {
position: relative;
text-align: left;
width: 95%;
height: 800px;
}
#fmxCanvas {
position: relative;
background-color:rgba(255,255,255,1);
border: rgba(255,255,255,1) thin dashed;
cursor: crosshair;
display: inline-block;
}
</style>
</head>
<body>
<div id="container">
<!-- START HTML CODE HERE -->
<canvas id="fmxCanvas" width="800" height="800"></canvas>
<div id="display"></div>
<!-- FINISH HTML CODE HERE -->
</div>
<script>
///////////////////////////////////////////////////////////////////////
// DECLARE requestAnimFrame
var rAF = window.requestAnimFrame ||
window.mozRequestAnimFrame ||
window.webkitRequestAnimFrame ||
window.msRequestAnimFrame;
var fps = 30;
window.requestAnimFrame = (
function(callback) {
return rAF ||
function(callback) {
window.setTimeout(callback, 1000 / fps);
};
})();
///////////////////////////////////////////////////////////////////////
// DEFINE GLOBAL VARIABLES HERE
var canvas;
var context;
canvas = document.getElementById("fmxCanvas");
context = canvas.getContext("2d");
var canvas1;
var context1;
canvas1 = document.createElement("canvas");
context1 = canvas1.getContext("2d");
canvas1.width = canvas.width;
canvas1.height = canvas.height;
var display;
display = document.getElementById('display');
var counter;
///////////////////////////////////////////////////////////////////////
// DEFINE YOUR GLOBAL VARIABLES HERE
///////////////////////////////////////////////////////////////////////
// CALL THE EVENT LISTENERS
window.addEventListener("load", setup, false);
//////////////////////////////////////////////////////////////////////
// ADD EVENT LISTENERS
canvas.addEventListener("mousemove", mousePos, false);
//////////////////////////////////////////////////////////////////////
// MOUSE COORDINATES
var stage, mouseX, mouseY;
function mousePos(event) {
stage = canvas.getBoundingClientRect();
mouseX = event.clientX - stage.left;
mouseY = event.clientY - stage.top;
}
/////////////////////////////////////////////////////////////////////
// INITIALIZE THE STARTING FUNCTION
function setup() {
/////////////////////////////////////////////////////////////////////
// DECLARE STARTING VALUES OF GLOBAL VARIABLES
counter = 0;
mouseX = canvas.width/2;
mouseY = canvas.height/2;
/////////////////////////////////////////////////////////////////////
// CALL SUBSEQUENT FUNCTIONS, as many as you need
createPlants();
killPlants();
herbsLife();
carnsLife();
clear(); // COVER TRANSPARENT CANVAS OR CLEAR CANVAS
draw(); // THIS IS WHERE EVERYTHING HAPPENS
}
////////////////////////////////////////////////////////////////////
// CLEAR THE CANVAS FOR ANIMATION
// USE THIS AREA TO MODIFY BKGD
function clear() {
context.clearRect(0,0,canvas.width, canvas.height);
context1.clearRect(0,0,canvas.width, canvas.height);
// clear additional contexts here if you have more than canvas1
}
////////////////////////////////////////////////////////////////////
// THIS IS WHERE EVERYTHING HAPPENS
function draw() {
counter += 0.1; // EASIER FOR SINE COSINE FUNCTIONS
//if (counter > Math.PI*200) { counter = 0; } // RESET COUNTER
clear(); // USE THIS TO REFRESH THE FRAME AND CLEAR CANVAS
////////////////////////////////////////////////////////////////////
// >>>START HERE>>>START HERE>>>START HERE>>>START HERE>>>START HERE
drawPlants();
drawHerbs();
drawCarns();
herbsEat();
carnsEat();
// <<<END HERE<<<END HERE<<<END HERE<<<END HERE<<<END HERE<<<END HERE
///////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// HTML DISPLAY FIELD FOR TESTING PURPOSES
display.innerHTML =
// mouseX + " || " + mouseY +
" || Minutes = " + Math.trunc(counter/180) +
" || Seconds = " + Math.round(counter/3) +
"<br><br>" +
"Plants = " + myPlants.length +
"<br>" +
"Herbivores = " + myHerbs.length +
"<br>" +
"Carnivores = " + myCarns.length;
/////////////////////////////////////////////////////////////////
// LAST LINE CREATES THE ANIMATION
requestAnimFrame(draw); // CALLS draw() every nth of a second
}
</script>
</body>
</html>