Ответ 1
Будем предупреждать, что для рендеринга используется Raphael и underscore для семантического сахара.
Я написал очень маленькую программу, которая соответствует вашим требованиям. (Это было весело).
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;
})
Создайте функцию-конструктор для вашего члена популяции, затем заполните массив этих парней. Я сопоставил массив длины с массивом тварей. (Cheeky for loop).
Каждый созданный вами твари будет похож, но имеет разные навыки (на основе 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);
Для каждого критерия вы вызываете свой метод запуска.
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 Только один организм может достичь пищевого продукта. По достижении этого, окружающая среда reset, за исключением организма, который нашел продукт питания в предыдущее время, теперь получает выгоду, и его уровень скорости может увеличиваться, в то время как другие, особенно ужасные, могут становиться еще медленнее или прекращаться
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 Что дальше:
- Изменение глобальных номеров и других жестко закодированных номеров
- Внедрить некоторые AI в функции
logic
. - Пройдите все jsfiddles от /1 до/180 и посмотрите, как он был создан.
- Пожаловаться на комментарии недостаточно детально
- Бросьте мой код и начинайте с нуля теперь, когда вы видели пример.
- Код рождения просто создает "базового" критерия. Он не размножается из двух существующих тварей и не обладает повышенными навыками. Это означает отсутствие эволюции.
Bonus:
Предупреждение:. Вышеупомянутая ссылка действительно путешествует по еде, но она делает что-то неправильно, там есть хитроумная ошибка. Я не думаю, что закончу это.
Я объясню логику движения к пище
// 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])