Hormiguero con jQuery (parte 1)

No es mi primera ni segunda implementación de un autómata celular, he implementado este hormiguero en varios lenguajes (en JAVA, en Objective-C para iOS, …) pero dado que estaba repasando jQuery, me decidí a implementarlo para web usando sólo HTML, CSS y jQuery.

En esta primera entrega implementaré una versión básica del hormiguero, dónde las hormigas (puntos azules) se mueven sin chocarse con otras hormigas y con las larvas (puntos blancos).



Como podéis observar el mundo del hormiguero es toroide, es decir cuándo una hormiga sale por la izquierda reaparece por la derecha y viceversa, lo mismo ocurre hacia arriba y hacia abajo.

Código HTML:

[html]
< !doctype html>






[/html]

Código CSS:

[css]
.anthill {
background-color: black;
position: relative;
}

.cell {
position: absolute;
}

.ant {
background-color: blue;
}

.grub {
background-color: white;
}
[/css]

Código JS:

[javascript]
var Cell = {
Empty: 0,
Wall: 1,
Ant: 2,
Grub: 3
}
var anthill = {};

// Return a free position in the array.
function FreePosition(cells) {
var position = {x: 0, y: 0};
do {
position.y = Math.floor(Math.random() * cells.length);
position.x = Math.floor(Math.random() * cells[position.y].length);
} while (cells[position.y][position.x] != Cell.Empty);
return position;
}

// Fill an array of elements.
function FillCells(countOfElements, anthillDiv, cells, elements, cellType, cellClass) {
for (var i = 0; i < countOfElements; i++) { var position = FreePosition(cells); var element = $(document.createElement("div")); element.addClass("cell " + cellClass); element.css({"width": ("" + anthill.cell + "px"), "height": ("" + anthill.cell + "px"), "left": ("" + (position.x * anthill.cell) + "px"), "top": ("" + (position.y * anthill.cell) + "px")}); anthillDiv.append(element); elements[i] = {position: position, element: element}; cells[position.y][position.x] = cellType; } } function ChangeDirection(ant) { do { ant.incX = Math.floor(Math.random() * 3) - 1; ant.incY = Math.floor(Math.random() * 3) - 1; } while ((ant.incX == 0) && (ant.incY == 0)); } function ChangePosition(ant, anthill) { var newPosition = {x: ant.position.x + ant.incX, y: ant.position.y + ant.incY}; if (newPosition.x < 0) { newPosition.x = anthill.width - 1; } else if (newPosition.x >= anthill.width) {
newPosition.x = 0;
}
if (newPosition.y < 0) { newPosition.y = anthill.height - 1; } else if (newPosition.y >= anthill.height) {
newPosition.y = 0;
}
if (anthill.cells[newPosition.y][newPosition.x] == Cell.Empty) {
anthill.cells[ant.position.y][ant.position.x] = Cell.Empty;
anthill.cells[newPosition.y][newPosition.x] = Cell.Ant;
ant.position = newPosition;
ant.element.css({“left”: (“” + (newPosition.x * anthill.cell) + “px”),
“top”: (“” + (newPosition.y * anthill.cell) + “px”)});
} else {
ChangeDirection(ant);
}
}

$(document).ready(function() {
$(“.anthill”).each(function() {
// Get the DIV element.
anthill.div = $(this);
// Get DIV attributes.
anthill.width = anthill.div.attr(“width”) || 50;
anthill.height = anthill.div.attr(“height”) || 30;
anthill.cell = anthill.div.attr(“cell”) || 15;
// Protect DIV attribute values.
anthill.width = (anthill.width < 10) ? 10 : anthill.width; anthill.width = (anthill.width > 100) ? 100 : anthill.width;
anthill.height = (anthill.height < 10) ? 10 : anthill.height; anthill.height = (anthill.height > 100) ? 100 : anthill.height;
anthill.cell = (anthill.cell < 1) ? 1 : anthill.cell; anthill.cell = (anthill.cell > 100) ? 100 : anthill.cell;
// Set DIV dimensions.
anthill.div.css({“width”: (“” + (anthill.width * anthill.cell) + “px”),
“height”: (“” + (anthill.height * anthill.cell) + “px”)});
// Fill the cells array.
anthill.cells = [];
for (var y = 0; y < anthill.height; y++) { anthill.cells[y] = []; for (var x = 0; x < anthill.width; x++) { anthill.cells[y][x] = Cell.Empty; } } // Calculate how many cell types we should generate. var countOfAnts = (anthill.width * anthill.height) * 0.01; var countOfGrubs = (anthill.width * anthill.height) * 0.1; // Fill the ants array. anthill.ants = []; FillCells(countOfAnts, anthill.div, anthill.cells, anthill.ants, Cell.Ant, "ant"); for (var i = 0; i < anthill.ants.length; i++) { ChangeDirection(anthill.ants[i]); } // Fill the grubs array. anthill.grubs = []; FillCells(countOfGrubs, anthill.div, anthill.cells, anthill.grubs, Cell.Grub, "grub"); }); }); window.setInterval(function() { for (var i = 0; i < anthill.ants.length; i++) { var ant = anthill.ants[i]; if (Math.floor(Math.random() * 20) == 0) { ChangeDirection(ant); } ChangePosition(ant, anthill); } }, 100); [/javascript] Os dejo los enlaces a los ficheros con el código fuente:

  • anthill-1.html
  • anthill-1.css
  • jquery.min_.1.10.1.js
  • anthill-1.js
  • En próximas entregas añadiré funcionalidad adicional como:

    • Añadir paredes al hormiguero.
    • Que las hormigas puedan recoger larvas.
    • Y que las depositen si cerca hay otras larvas.

    Con esto se conseguirán agrupaciones automáticas sin que las hormigas tengan visión global del hormiguero, sólo de las celdas de alrededor.

Deja un comentario