3d array movement in p5.js? - javascript

I'm in dire need of help with a graduation project that I'm working on. What I'm trying to achieve here in the code below is -to put it very simply- to initialize a 3d array of box() objects (this works) and then introduce another box() object (the end goal is to have an array of these as well) to move about within the same 3D grid. The moving unit picks a random location for initialization and a random target for destination (both within the 3D grid).
But the problem is that I need the moving unit not to overlap with the static base units, also move orthogonally, and always move one unit size each time. If I run the code below the moving unit reaches the target but without any of the restrictions that I mentioned above. It just takes the shortest vector and goes there regardless.
PS: Since p5js doesn't support wireframe in webgl mode I tried to show them with some transparency for better visual legibility. Although, the loadImage() functions are still there and could be replaced with any image of your liking to better differentiate units from one another.
I'd sincerely appreciate help with this since I'm also very short on time. Thanks in advance.
Here's the verifiable code:
var matrixSize = 5;
var locations = new Array(matrixSize);
var locBool = new Array(matrixSize);
//unit stuff
var unitSize = 40;
var units_a = []
var units_b;
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
//3D array of location vectors & booleans
for(var i = 0; i < locations.length; i++){
locations[i] = new Array(matrixSize);
locBool[i] = new Array(matrixSize);
for(var j = 0; j < locations[i].length; j++){
locations[i][j] = new Array(matrixSize);
locBool[i][j] = new Array(matrixSize);
for(var k = 0; k < locations[i][j].length; k++){
locations[i][j][k] =
createVector(i*unitSize, j*unitSize, k*unitSize);
locBool[i][j][k] = false;
}
}
}
//base units
var threshold = 2; //decides on the percentage to be initialized
for (var i = 0; i < matrixSize; i++) {
for(var j = 0; j < matrixSize; j++){
for(var k = 0; k < matrixSize; k++){
stateRndm = random(10);
if(stateRndm <= threshold){
state = 1;
locBool[i][j][k] = true;
}else{
state = 0
}
units_a.push(new UnitOne(
i*unitSize,j*unitSize,k*unitSize, state));
}
}
}
units_b = new UnitTwo();
}
function draw() {
background(20);
ambientLight(235);
orbitControl();
rotateX(10);
rotateY(-10);
rotateZ(0);
//center the window and display the units
push();
translate(-unitSize*matrixSize/2, -unitSize*matrixSize/2, 0);
for(var i = 0; i < units_a.length; i++){
units_a[i].display();
}
units_b.display();
units_b.update();
units_b.move();
pop();
}
function UnitOne (x, y, z, state){
this.x = x;
this.y = y;
this.z = z;
this.state = state;
//this.img = loadImage("assets/tex_1.jpg");
//basic movement parameters
this.acceleration = createVector();
this.velocity = createVector();
this.location = createVector(this.x, this.y, this.z);
this.update = function(){
this.velocity.add(this.acceleration);
this.location.add(this.velocity);
this.acceleration.mult(0);
}
this.display = function(){
if(this.state == 1){
push();
scale(1);
//texture(this.img);
ambientMaterial(50, 200, 100, 20);
translate(this.x, this.y, this.z);
box(unitSize);
pop();
}
}
}
function UnitTwo() {
//assign random initial location
this.selector;
for(var i = 0; i < locations.length; i++){
for(var j = 0; j < locations[i].length; j++){
for(var k = 0; k < locations[i][j].length; k++){
this.selector = createVector(
floor(random(i))*unitSize,
floor(random(j))*unitSize,
floor(random(k))*unitSize);
}
}
}
print(this.selector);
//assign random target
this.targetSelector;
for(var i = 0; i < locations.length; i++){
for(var j = 0; j < locations[i].length; j++){
for(var k = 0; k < locations[i][j].length; k++){
this.targetSelector = createVector(
floor(random(i))*unitSize,
floor(random(j))*unitSize,
floor(random(k))*unitSize);
}
}
}
print(this.targetSelector);
//basic movement parameters
this.location = createVector(
this.selector.x,
this.selector.y,
this.selector.z);
this.acceleration = createVector();
this.velocity = createVector();
this.maxSpeed = 1;
this.maxForce = 2;
//this.img = loadImage("assets/tex_2.jpg");
this.display = function(){
push();
//texture(this.img);
ambientMaterial(200, 100, 40);
translate(this.location.x,
this.location.y, this.location.z);
scale(1);
box(unitSize);
pop();
}
this.update = function(){
this.velocity.add(this.acceleration);
this.location.add(this.velocity);
this.acceleration.mult(0);
}
}
UnitTwo.prototype.move = function(){
var target = createVector(this.targetSelector.x,
this.targetSelector.y,
this.targetSelector.z);
var desired = p5.Vector.sub(target, this.location);
var d = desired.mag();
//check the distance to slow down
if (d < unitSize/2)
desired.setMag(this.maxSpeed/2);
else
desired.setMag(this.maxSpeed);
var steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxForce);
this.acceleration.add(steer);
}

You've outlined both things you need to do. Which part of them are you stuck on?
Step 1: Make your unit move one cube at a time. You could do this by simply adding or subtracting 1 to its x, y, or z coordinate. Get this working first. Don't worry about avoiding collisions with the other cubes yet.
Step 2: When you get that working, add code that detects when the cube it's about to move to is occupied, and go in a different direction. You might have to implement a basic path finding algorithm, and Google is your friend for that.
You might also want to consider the possibility that your random generation has blocked all of the paths to the goal. What do you want to do in that case? And one more note: you don't need a triple-nested for loop just to generate a random value.
If you get stuck on one of these steps, please narrow your problem down to a MCVE showing just that step before you post again. Good luck.

Related

Enemy detection and turret animation/control in a JavaScript p5.js game

I'm making a tower defense game using JavaScript and p5.js library. My enemy follows a path and their location is always stored in a list. I have a base and a gun, the gun rotates around the base(as 1 unit) and is supposed to point towards the nearest enemy. I have a function that will allow me to make the gun point towards the enemy pointEnemy however, I'm not able to get the correct condition to make it point towards the nearest enemy in it's range. I need the correct argument for enemyx & enemyy. I'm currently spawning 100 enemies and they keep moving, their location is stored in globalenemy1position. Any help is appreciated, thank you.
Required Code
Some important variables
var numberOfEnemy1 = 100
let classenemy1 = new Enemy1(numberOfEnemy1);
var globalenemy1position = [];
var isFireTowerPressed = false;
var FireTowerPos = []; // Position of all FireTowers => [x,y]
var FireTowerRange = 300;
var FireTowerAngle = 0;
My Enemy Class
class Enemy1
{
constructor(number_of_enemies)
{
this.number_of_enemies = number_of_enemies;
this.enemy_position = [];
this.enemy1speed = 4;
}
enemy1_spawn()
{
let randomx = random(-300, -100);
for(var i=0; i<this.number_of_enemies; i++)
{
var positionx = randomx;
var positiony = 100;
this.enemy_position.push([positionx + (-i*50), positiony]);
globalenemy1position.push([positionx + (-i*50), positiony]);
image(enemy1, this.enemy_position[i][0], this.enemy_position[i][1]);
}
}
enemy1_move()
{
for(var i = 0; i < this.enemy_position.length; i++)
{
image(enemy1, this.enemy_position[i][0], this.enemy_position[i][1]);
if (this.enemy_position[i][0] >= 200 && this.enemy_position[i][1] <= 450 && this.enemy_position[i][0] < 599)
{
this.enemy_position[i][1] += this.enemy1speed;
globalenemy1position[i][1] += this.enemy1speed;
}
else if (this.enemy_position[i][1] >= 100 && this.enemy_position[i][0] >= 600)
{
this.enemy_position[i][1] -= this.enemy1speed;
globalenemy1position[i][1] -= this.enemy1speed;
}
else if (this.enemy_position[i][0] >= 750)
{
this.enemy_position[i][0] = 750;
lives --;
this.enemy_position.shift();
globalenemy1position.shift();
}
else
{
this.enemy_position[i][0] += this.enemy1speed;
globalenemy1position[i][0] += this.enemy1speed;
}
}
}
}
Draw Function - Redraws Every Frame
function draw()
{
background(60, 238, 161);
[...]
classenemy1.enemy1_move();
rect(750, 70, 50, 100);
ShowLives();
if (isFireTowerPressed == true)
{
image(firetowerbaseImg, mouseX - 28, mouseY - 28);
noFill();
stroke(0,0,0);
strokeWeight(1);
circle(mouseX, mouseY, 300);
}
for (var i = 0; i < FireTowerPos.length; i++)
{
image(firetowerbaseImg, FireTowerPos[i][0], FireTowerPos[i][1]);
if (globalenemy1position.length >= 1)
{
var gunx = FireTowerPos[i][0] +28;
var guny = FireTowerPos[i][1]+25;
var gunrange = FireTowerPos[i][3];
for (j=0; j<globalenemy1position.length; j++)
{
// Need help with this statement here
pointEnemy(globalenemy1position[j][0], globalenemy1position[j][1], gunx, guny, FireTowerPos[i][2], FireTowerPos[i][3]);
}
}
else
{
image(firetowerturretImg, FireTowerPos[i][0], FireTowerPos[i][1]-20);
}
}
}
Function to make the gun point towards Enemy - I need the proper value for enemyx & enemyy
function pointEnemy(enemyx, enemyy, gunx, guny, gunangle, gunrange)
{
const isWithinRange = dist(enemyx, enemyy, gunx, guny) < gunrange;
if(isWithinRange)
{
gunangle = atan2(enemyy - guny, enemyx - gunx) + radians(90);
}
push();
translate(gunx, guny);
// rect(-25, -20, 50, 40) // Draw the gun base
// ellipse(0, 0, gun.range*2) // display the gun range
rotate(gunangle);
image(firetowerturretImg, -28, -45); // Set the offset of the gun sprite and draw the gun
pop();
}
Here is a picture to help visualise the problem
As you can see, currently I'm just iterating through all the enemies and giving their location, so it's basically pointing to every enemy nearby.
Updates
1
I tried the approach given by #user3386109 , but wasn't able to implement it, also if possible I want the turret/gun to point towards the enemy till it leaves the range and not always point towards the closest enemy. It should start off with the closest and then keep pointing towards it till it leaves or the enemy dies(position removed from the list), whichever comes first. The function should then restart again and continue the process.
This process is the complete aiming for the tower. Add this to draw and it searches for enemies.
for (var i = 0; i < FireTowerPos.length; i++)
{
// image(firetowerbaseImg, FireTowerPos[i][0], FireTowerPos[i][1]);
// pointEnemy(mouseX, mouseY, FireTowerPos[i][0] +28, FireTowerPos[i][1]+25, FireTowerPos[i][2], FireTowerPos[i][3]);
image(firetowerbaseImg, FireTowerPos[i][0], FireTowerPos[i][1]);
var enemiesInRange = [];
let firetowerx = FireTowerPos[i][0];
let firetowery = FireTowerPos[i][1];
for (var j = 0; j < globalenemy1position.length; j++)
{
var checkDist = dist(globalenemy1position[j][0], globalenemy1position[j][1], firetowerx, firetowery);
let thisenemyx = globalenemy1position[j][0];
let thisenemyy = globalenemy1position[j][1];
if (checkDist < FireTowerRange)
{
enemiesInRange.push([thisenemyx, thisenemyy]);
pointEnemy(enemiesInRange[0][0], enemiesInRange[0][1], FireTowerPos[i][0] +28, FireTowerPos[i][1]+25, FireTowerPos[i][2], FireTowerPos[i][3]);
}
else
{
enemiesInRange.shift();
}
}
}

scriptProcessorNode oscillator frequency

I am working on a web audio stochastic oscillator and am having trouble with the scriptProcessorNode. My algorithm uses a random walk to determine dynamic breakpoints in the waveform and then interpolates between them.
As the breakpoints move on the x axis I thought the frequency of the oscillating waveform would change, but there is just a filtering effect, and the frequency seems to just be determined by the scriptProcessorNode buffer size, which must be a power of 2 between 256 and 16384.
How do you change the frequency of a scriptProcessorNode oscillator?
Here is my synthesis code:
scriptNode.onaudioprocess = function(audioProcessingEvent) {
walk(); //use random walk to generate new x/y position for each breakpoint
var outputBuffer = audioProcessingEvent.outputBuffer;
var lastPoint = 0;
var index = 0;
// linearly interpolate between the new breakpoint positions
for(var i = 0; i < breakpoint.length-1; i++) {
var y = breakpoint[lastPoint].y;
for(var channel = 0; channel <= 0;channel++) {
var outputData = outputBuffer.getChannelData(channel);
if(i != 0){
if(y >= breakpoint[i].y) {
while(y >= breakpoint[i].y) {
y = (breakpoint[i].m*index)+breakpoint[i].b;// y = m(x)+b
outputData[index] = y;
index++;
}
} else if(y <= breakpoint[i].y) {
while(y <= breakpoint[i].y) {
y = (breakpoint[i].m*index)+breakpoint[i].b;
outputData[index] = y;
index++;
}
}
}
}
lastPoint = i;
}
}
And here is a link to a working example: http://andrewbernste.in/bernie/gendy011.html
This is all based on Iannis Xenakis' GENDY stochastic synthesis program.
Thanks!
I solved the problem by using an index variable outside of my scriptNode.onaudioprocess function to write the waveform to the scriptNode buffer. That way the frequency at which the waveform is written to the buffer is not tied to the size of the buffer.
Here is the final code:
var index = 0;
var freq = 0.8;
scriptNode.onaudioprocess = function(audioProcessingEvent){
var outputBuffer = audioProcessingEvent.outputBuffer;
var outputData = outputBuffer.getChannelData(0);
for(var j = 0; j < outputData.length;j++){
// linearly interpolate between the new breakpoint positions
// get the interp point by comparing index to the x distance
var lerp = (index - breakpoint[point].x) / (breakpoint[point+1].x - breakpoint[point].x)
y = nx.interp(lerp,breakpoint[point].y,breakpoint[point+1].y);
if(point < breakpoint.length && index >= breakpoint[point+1].x) {
point++;
}
outputData[j] = y;
index+=freq;
if(index >= breakpoint[breakpoint.length-1].x){
index = 0;
point = 0;
walk();
}
}
}

N-Body Gravity Simulation in JavaScript

So, I am trying to create a N-Body Gravity simulation in JavaScript:
http://jsfiddle.net/4M94x/
var Circle = function(c, r, cor, cof) { // Fix CoR & CoF // Had to add code for JSFiddle link :P
this.c = c
this.r = r
this.m = r * r * Math.PI
this.v = new Vector()
this.cor = cor
this.cof = cof
}
The problem's that when you spawn (click) and put 2 balls (accidentally renamed "particles") next to each other they start to generate velocity and faster and faster push eachother.. How do I fix this, btw is my gravity implementation correct?
This is easy to explain: You are implementing Euler forward as solver for the ODE, and in mechanical systems the systematic error of Euler forward increases the energy. Euler backward decreases the energy, so a combination of alternating the explicit and implicit Euler methods would leave the energy a little more constant.
But then you can implement with the same or even less effort the second order symplectic methods which preserve energy and other physical invariants, either the (implicit) midpoint method or the Verlet-(Stoermer-Cromer-...-Newton-)method.
Or even higher order Runge-Kutta, which will also preserve the energy to a higher order, despite not being symplectic.
See Hairer on the Stoermer-Verlet-...-Newton method, postprint or preprint and the "Moving stars around" tutorial text using C++ or Ruby.
A note to the physics: All in all the implementation is very minimal and well readable. But the gravitational force is
g*m1*m2*(p2-p1)/norm(p2-p1)^3
as the negative gradient of
g*m1*m2/norm(p2-p1)
you are only using the square of the norm, where the force would be the negative gradient of the gravitational potential energy
g*m1*m2*ln(norm(p2-p1))
which is right for flatland physics, but not for a 2D section of 3D space.
Working code
with velocity Verlet and energy preservation:
Add a new field a=Vector() to the circle object and replace the kitchen sink which is the update() function with the following collection of dedicated functions
function compute_forces() {
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
p.a.set(0);
for (var j = 0; j < i; j++) {
var p2 = particles[j];
var d = p.c.sub(p2.c);
var norm = Math.sqrt(100.0 + d.lengthSq());
var mag = gravity / (norm * norm * norm);
p.a.set(p.a.sub(d.mul(mag * p2.m)));
p2.a.set(p2.a.add(d.mul(mag * p.m)));
}
}
}
function do_collisions() {
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
for (var j = 0; j < i; j++) {
var p2 = particles[j];
if (checkCCCol(p, p2)) {
resCCCol(p, p2);
}
}
}
}
function do_physics(dt) {
// do velocity Verlet
// with consistent state at interval half points
// x += 0.5*v*dt
for (var i1 = 0; i1 < particles.length; i1++) {
var p1 = particles[i1];
p1.c.set(p1.c.add(p1.v.mul(0.5 * dt)));
}
// a = A(x)
compute_forces();
// v += a*dt
for (var i2 = 0; i2 < particles.length; i2++) {
var p2 = particles[i2];
p2.v.set(p2.v.add(p2.a.mul(dt)));
}
// x += 0.5*v*dt
for (var i3 = 0; i3 < particles.length; i3++) {
var p3 = particles[i3];
p3.c.set(p3.c.add(p3.v.mul(0.5 * dt)));
}
do_collisions();
}
function update() {
for (var k = 0; k < 4; k++) {
do_physics(1.0 / 4);
}
render();
RAF(update);
}
See http://jsfiddle.net/4XVPH/
Altered example with particles coloured based on their mass(hopefully better displaying their interaction), one bug fixed, and some additional comments: http://jsfiddle.net/24mg6ctg/12/

How to draw map from pixel array

I'm trying to load a map from a image, I get the hex codes for every pixel on my image, which is put into map[]. The world[] will store 1 or 0 or whatever number for number of sprite on the spritesheet. If the color is #8aff00 then it will store 0 for grass. The map is 16 by 16 pixels, which is my world size. When I try to make the world array, the for statement is working right, there is no errors. I know I have all the data, but this part of my function is not working, it just stops after these for statements:
function createWorld() {
for (var y=0; y < worldHeight; y++) {
for (var x=0; x < worldWidth; x++) {
if (map[pl] == '#8aff00') world[x][y] = 0;
if (map[pl] == '#000000') world[x][y] = 1;
pl+=4;
}
}
alert('about to draw');
draw();
}
The alert never gets called. When I displayed the x and y, it went '0,0' to '1,0' then back to '0,0' for the value x and y. The pl is for which number of the array I want. When I put another for statement to handle that it messed up more. Is there something wrong with the code, if you need more of the code just let me know.
I've managed to build code which is working.
Now it's Your turn to implement it as You need.
worldHeight = 16;
worldWidth = 16;
world = {};
map = ['#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000']
pl = 0
function draw(){
console.log(world);
}
function createWorld() {
for (var y=0; y < worldHeight; y++) {
for (var x=0; x < worldWidth; x++) {
if (map[pl] == '#8aff00')
world[x] = 0;
world[x][y] = 0;
if (map[pl] == '#000000')
world[x] = 0;
world[x][y] = 1;
pl+=4;
}
}
alert('about to draw');
draw();
}
createWorld();
Cheers.

Improve function speed

I'm doing a BattleShip game in javascript with iio engine.
I'm trying to play against a computer so I have to put a random position for the ships (I hope you know the game :) ).
I have 5 ships that have to be placed in a grid (10x10). The problem is that the function is pretty slow, and sometimes the page don't get load at all.
I want to know if there are some emprovement for the speed of these function, I'm a little bit newbie :D
function posShips(size){
// var size -> size of the ship
var isOk = false; // flag var to check if the ship is in a right position
var isOk2 = true; // flag var, become false if the cell is already fill with another ship
var i;
var j;
var side; // horizontal or vertical
while(!isOk){
i = iio.getRandomInt(1,11);
j = iio.getRandomInt(1,11);
side = iio.getRandomInt(0,2);
if((side ? j : i)+size-1 < 11){ // Not out of the array
for (var k = 0; k < size; k++) { // Size of the ship
if(side){
if(gridHit[i][j+k].stat == "empty"){ //If is empty put the ship
gridHit[i][j+k].stat = "ship";
gridHit[i][j+k].setFillStyle("red")
}else{ // If not empty
isOk2 = false; //Position is not good, do all the thing again.
for (var a = 0; a < size; a++) { // Reset cell
gridHit[i][j+a].stat = "empty";
}
k = 10;
}
}else{
if(gridHit[i+k][j].stat == "empty"){ //If is empty put the ship
gridHit[i+k][j].stat = "ship";
gridHit[i+k][j].setFillStyle("red")
}else{ // If not empty
isOk2 = false; //Position is not good, do all the thing again.
for (var a = 0; a < size; a++) { // Reset cell
gridHit[i+a][j].stat = "empty";
}
k = 10;
}
}
};
if(isOk2)
isOk = true;
}
}
}
Don't pick ship positions that will fall outside the grid. Pick the direction first, and then limit the x and y initial positions based on size. e.g. if the size is 3, there's no point going above 7 for the initial value of the varying coordinate.
Don't change the array while you're searching. Do the search first, and only afterwards update the array. This avoids any "cleanup" operation.
Wherever possible, eliminate repeated deep object references. If accessing grid[y][x] repeatedly for differing x, take a reference to grid[y] first, and then use that for the subsequent accesses.
Break out of loops early, there's no point continuing to test a position if a previous one already failed.
Place your big ships first - it's easier to fit small ships into the gaps left between the big ones.
See http://jsfiddle.net/alnitak/Rp9Ke/ for my implementation, with the equivalent of your function being this:
this.place = function(size) {
// faster array access
var g = this.grid;
// initial direction, and vector
var dir = rand(2); // 0 - y, 1 - x
var dx = dir ? 1 : 0;
var dy = dir ? 0 : 1; // or 1 - dx
LOOP: while (true) {
// initial position
var x = dir ? rand(10 - size) : rand(10);
var y = dir ? rand(10) : rand(10 - size);
// test points
var n = size, tx = x, ty = y;
while (n--) {
if (g[ty][tx]) continue LOOP;
tx += dx;
ty += dy;
}
// fill points
n = size;
while (n--) {
g[y][x] = size;
x += dx;
y += dy;
}
break;
}
};

Categories