现场示例
请注意,这使用Raphael进行渲染,并使用下划线表示语义糖。
我写了一个非常小的程序来满足你的要求。(好玩)。
1 产生了一个群体,每个群体最初似乎都具有相同的表型属性,但他们的技能不同(为此,速度)。
var Critter = function() {
// default the speed to something random.
this.speed = SPEED + Math.random()*SPEED;
// logic module
var logic = function() { ... }
}
...
// initialize an array of critters.
critters: _.map(_.range(0,COUNT), function() {
return new Critter;
})
为您的人口成员创建一个构造函数,然后填充这些人的数组。我已经将一个长度计数数组映射到一个小动物数组。(厚颜无耻的循环)。
您创建的每个小动物都将相似但具有不同的技能(基于Math.random()
),但它们将包含相同的逻辑单元。
2 生成单一食物来源(每次都相同)
// trivial Food object.
var Food = function() {
// rectangle with random x, random y, and SIZE as width / height
this.el = paper.rect(Math.random()*WIDTH, Math.random()*HEIGHT, SIZE, SIZE);
};
食物对象构造函数只是在屏幕上随机放置一个正方形
3 在环境建立约 5 秒后(步骤 1 和 2),生物种群需要找到一种竞争性地到达食物来源的方法
设置环境:
_.invoke(this.critters, "start", this.food.el.getBBox(), out_of_bounds);
对于每个小动物,您调用它们的 start 方法。
this.start = function(food) {
// create a player (circle);
this.el = paper.circle(Math.random()*WIDTH, Math.random()*HEIGHT, SIZE / 2);
// set an interval to run the logic over and over.
loop = setInterval(_.bind(logic, this, food), 25);
};
每个小动物只是将自己随机放置在屏幕上,然后在循环中一遍又一遍地调用自己的逻辑。
4 只有一种生物可以接触到食品。到达它后,环境被重置,除了上次找到食物的生物现在受益并且它的速度等级可能会增加,而其他做得特别糟糕的生物可能会变得更慢或被终止
var logic = function(food) {
// if you hit food you win
if (this.el.collision(food)) {
this.win();
}
}
// you won
this.win = function() {
console.log("win");
// increase speed
this.speed += Math.random()*5;
// end round
Game.end();
};
小动物将在逻辑循环中检测它是否有食物。一旦它有了食物,它就会调用自己的获胜方法。这结束了当前的游戏回合。
当小动物获胜时,它会获得速度提升。
当你打电话时游戏会自动重启.end
(在移除所有当前的小动物之后)
end: function () {
// tell all critters to end their round
_.invoke(this.critters, "remove");
// remove the food
this.food.el.remove();
// start again !
this.start();
},
5 过程重复;用户可以观察种群的特征并查看哪些特征在进化上取得了成功等。
观看现场示例 :)
6 下一步:
- 调整全局数字和其他硬编码数字
- 在
logic
函数中实现一些 AI。
- 浏览从 /1 到 /180 的所有 jsfiddles,看看它是如何构建的。
- 抱怨评论不够详细
- 既然您已经看到了一个示例,请扔掉我的代码并从头开始。
- 出生代码只是创建了一个“基本”小动物。它不是从两个现有的小动物中繁殖出来的,也没有增加技能。这意味着没有进化。
奖金:
走向食物
警告:上面的链接确实指向食物,但它做错了,我认为那里有一个狡猾的错误。我不认为我会解决这个问题。
我将解释前往食物的逻辑
// angle between critter and food
var angle = Raphael.angle(
this.el.getBBox().x,
this.el.getBBox().y,
food.x,
food.y) - 135; // the 135 is the default direction (bottom right)
// get a random speed
var rand = Math.random()*this.speed;
// travel towards the food box by rotating your vector by the angle
var points = this.rotateVector([rand, rand], angle);
// move towards the box
this.el.translate(points[0], points[1]);
首先rand
创建一个如下所示的随机向量:

Math.random()
决定了小动物移动的距离/速度。这是指向右下角。
因为它指向右下角,所以我们必须135
从这个向量的角度移除度数

然后我们必须计算小动物和食物之间的角度。我们通过传入两个点来做到这一点Raphael.angle
,它会为我们计算角度。

现在我们有了角度,我们想将我们的运动矢量旋转该角度。运动矢量当前指向上方(黑色),我们希望将其旋转一定角度到新位置(红色)。在代码中这是this.rotateVector

现在正指向正确的方向!我们可以打电话this.el.translate(points[0], points[1])