JavaScript Loop to create grid on canvas - javascript

What I'm trying to do is fill myCanvas with 32x32 blocks of random colors. I'm using a loop to create the blocks and assign them colors. I've figured out how to get the line to descend on the Y axis as the loop goes on but I can't wrap my head around getting the X axis right.
If you make the canvas larger you will see that lines of blocks 20 blocks long go on to the right.
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
for (i = 0; i < 400; i++) {
var X = i * 32;
var Y = Math.floor(i / 20) * 32;
ctx.fillStyle='#'+Math.floor(Math.random()*16777215).toString(16);
ctx.fillRect(X, Y, 32, 32);
console.log('X:' + X);
console.log('Y:' + Y);
}
I've tried using modulus like this:
if(i % 20 == 0){
X = 0;
}
But it only fixes it when I get multiples of 20 so only the left side of the canvas will be filled with blocks. My problem is wrapping my head around the math involved in getting this done. Sorry I'm pretty tired and new at this :(
Fiddle: http://jsfiddle.net/orwfo7re/

you were already pretty close with your modulus suggestion! However, your if statement only gets executed when i % 20 == 0, something that for instance is not true for i=21
The solution is to just use var x = (i % 20) * 32 for var x in your algoritm. So:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
for (i = 0; i < 400; i++) {
var X = (i % 20) * 32;
var Y = Math.floor(i / 20) * 32;
ctx.fillStyle='#'+Math.floor(Math.random()*16777215).toString(16);
ctx.fillRect(X, Y, 32, 32);
}
fiddle: https://jsfiddle.net/MartyB/ur9vug0x/2/

Do you mean to do something like this:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var width = 640;
var height = 640;
for (y=0; y< height; y=y+32) {
for (x=0; x < width; x=x+32) {
ctx.fillStyle='#'+Math.floor(Math.random()*16777215).toString(16);
ctx.fillRect(x, y, 32, 32);
}
}

Related

How to add a zoom feature with mouse to my canvas

I'm working on a webapp and it includes one part where I draw the graph of a function, the coordinate system is made by Canvas. The problem is, I can not zoom into my coordinate system. I want to make it able to zoom in and out + moving the coordinate system using the mouse. The x and y values should also increase/decrease while zooming in/out.
Could somebody help me with this ?
I searched for some solutions, but I couldn't find anything useful. That's why I decided to ask it here.
Here are my codes:
<canvas id="myCanvas" width="300" height="300" style="border:1px solid #d3d3d3;"></canvas>
<!--Canva startup-->
<script>
// Setup values
var height = 300;
var width = 300;
var zoomFactor = 15;
// --------
var c = document.getElementById("myCanvas");
var xZero = width / 2;
var yZero = height / 2;
var ctx = c.getContext("2d");
// Draw Cord-System-Grid
ctx.beginPath();
ctx.moveTo(xZero, 0);
ctx.lineTo(xZero, height);
ctx.strokeStyle = "#000000";
ctx.stroke();
ctx.moveTo(0, yZero);
ctx.lineTo(width, yZero);
ctx.strokeStyle = "#000000";
ctx.stroke();
ctx.beginPath();
// Draw Numbers
ctx.font = "10px Georgia";
var heightTextX = yZero + 10;
for(var i = 0; i < width; i = i + width / 10) {
var numberX = (-1 * xZero / zoomFactor) + i / zoomFactor;
ctx.fillText(numberX, i, heightTextX);
}
var heightTextY = yZero + 10;
for(var n = 0; n < height; n = n + height / 10) {
var numberY = (-1 * yZero / zoomFactor) + n / zoomFactor;
if(numberY !== 0)
ctx.fillText(numberY * -1, heightTextY, n);
}
</script>
I asked this question before a week, but couldn't get an answer.
I hope somebody can help me
Attach the onwheel event to a function and use the ctx.scale() function to zoom in and out.
You will probably want to do something like
let canvas = document.getElementById('myCanvas');
ctx.translate(canvas.width/2, canvas.height/2);
ctx.scale(zoomFactor, zoomFactor);
ctx.translate(-canvas.width/2, -canvas.height/2);
To make sure it zooms from the center.
Sorry for any minor errors I'm writing this from my phone.

HTML5 Canvas: Bouncing Balls with Image Overlay

I'm really struggling with a couple problems in the HTML5 canvas.
I've posted the project to GitHub pages (https://swedy13.github.io/) and added an image (the circles are in motion) so you can see the issue. Basically, if you scroll down you'll find several green circles bouncing around on the page. I'd like to replace those with my client logos.
I'm calling requestAnimation from three files based on different actions, all of which can be found in https://github.com/swedy13/swedy13.github.io/tree/master/assets/js
Filenames:
- filters.js (calls requestAnimation when you use the filters)
- main.js (on load and resize)
- portfolio.js (this is where the canvas code is)
Update: I've added the "portfolio.js" code below so the answer can be self-contained.
function runAnimation(width, height, type){
var canvas = document.getElementsByTagName('canvas')[0];
var c = canvas.getContext('2d');
// ---- DIMENSIONS ---- //
// Container
var x = width;
var y = height - 65;
canvas.width = x;
canvas.height = y;
var container = {x: 0 ,y: 0 ,width: x, height: y};
// Portrait Variables
var cPos = 200;
var cMargin = 70;
var cSpeed = 3;
var r = x*.075;
if (y > x && x >= 500) {
cPos = x * (x / y) - 150;
cMargin = 150;
}
// Landscape Variables
if (x > y) {
cPos = y * (y / x) - 50;
cMargin = 150;
cSpeed = 3;
r = x*.05;
}
// ---- CIRCLES ---- //
// Circles
var circles = [];
var img = new Image();
// Gets active post ids and count
var activeName = [];
var activeLogo = [];
var activePosts = $('.active').map(function() {
activeName.push($(this).text().replace(/\s+/g, '-').toLowerCase());
// Returns the image source
/*activeLogo.push($(this).find('img').prop('src'));*/
// Returns an image node
var elem = document.getElementsByClassName($(this).text().replace(/\s+/g, '-').toLowerCase())
activeLogo.push(elem[0].childNodes[0]);
});
// Populates circle data
for (var i = 0; i < $('.active').length; i++) {
circles.push({
id:activeName[i],
r:r,
color: 100,
/*image: activeLogo[i],*/
x:Math.random() * cPos + cMargin,
y:Math.random() * cPos + cMargin,
vx:Math.random() * cSpeed + .25,
vy:Math.random() * cSpeed + .25
});
}
// ---- DRAW ---- //
requestAnimationFrame(draw);
function draw(){
c.fillStyle = 'white';
c.fillRect(container.x, container.y, container.width, container.height);
for (var i = 0; i < circles.length; i++){
/*var img = new Image();
var path = circles[i].image;*/
/*var size = circles[i].r * 2;*/
/*img.src = circles[4].image;*/
var img = activeLogo[i];
img.onload = function (circles) {
/*c.drawImage(img, 0, 0, size, size);*/
var pattern = c.createPattern(this, "repeat");
c.fillStyle = pattern;
c.fill();
};
c.fillStyle = 'hsl(' + circles[i].color + ', 100%, 50%)';
c.beginPath();
c.arc(circles[i].x, circles[i].y, circles[i].r, 0, 2*Math.PI, false);
c.fill();
// If the circle size/position is greater than the canvas width, bounce x
if ((circles[i].x + circles[i].vx + circles[i].r > container.width) || (circles[i].x - circles[i].r + circles[i].vx < container.x)) {
circles[i].vx = -circles[i].vx;
}
// If the circle size/position is greater than the canvas width, bounce y
if ((circles[i].y + circles[i].vy + circles[i].r > container.height) || (circles[i].y - circles[i].r + circles[i].vy < container.y)){
circles[i].vy = -circles[i].vy;
}
// Generates circle motion by adding position and velocity each frame
circles[i].x += circles[i].vx;
circles[i].y += circles[i].vy;
}
requestAnimationFrame(draw);
}
}
The way it works right now is:
1. I have my portfolio content set to "display: none" (eventually it will be a pop-up when they click on one of the circles).
2. The canvas is getting the portfolio objects from the DOM, including the image that I can't get to work.
3. If I use the "onload()" function, I can get the images to show up and repeat in the background. But it's just a static background - the circles are moving above it and revealing the background. That isn't what I want.
So basically, I'm trying to figure out how to attach the background image to the circle (based on the circle ID).
----------------- UPDATE -----------------
I can now clip the image to a circle and get the circle to move in the background. But it isn't visible on the page (I can tell it's moving by console logging it's position). The only time I see anything is when the circle lines up with the images position, then it shows.
function runAnimation(width, height, type){
var canvas = document.getElementsByTagName('canvas')[0];
var c = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
// Collects portfolio information from the DOM
var activeName = [];
var activeLogo = [];
$('.active').map(function() {
var text = $(this).text().replace(/\s+/g, '-').toLowerCase();
var elem = document.getElementsByClassName(text);
activeName.push(text);
activeLogo.push(elem[0].childNodes[0]);
});
var img = new Image();
img.onload = start;
var circles = [];
var cPos = 200;
var cMargin = 70;
var cSpeed = 3;
for (var i = 0; i < 1; i++) {
circles.push({
id: activeName[i],
img: activeLogo[i],
size: 50,
xPos: Math.random() * cPos + cMargin,
yPos: Math.random() * cPos + cMargin,
xVel: Math.random() * cSpeed + .25,
yVel: Math.random() * cSpeed + .25,
});
img.src = circles[i].img;
}
requestAnimationFrame(start);
function start(){
for (var i = 0; i < circles.length; i++) {
var circle = createImageInCircle(circles[i].img, circles[i].size, circles[i].xPos, circles[i].yPos);
c.drawImage(circle, circles[i].size, circles[i].size);
animateCircle(circles[i]);
}
requestAnimationFrame(start);
}
function createImageInCircle(img, radius, x, y){
var canvas2 = document.createElement('canvas');
var c2 = canvas2.getContext('2d');
canvas2.width = canvas2.height = radius*2;
c2.fillStyle = 'white';
c2.beginPath();
c2.arc(x, y, radius, 0, Math.PI*2);
c2.fill();
c2.globalCompositeOperation = 'source-atop';
c2.drawImage(img, 0, 0, 100, 100);
return(canvas2);
}
function animateCircle(circle) {
// If the circle size/position is greater than the canvas width, bounce x
if ((circle.xPos + circle.xVel + circle.size > canvas.width) || (circle.xPos - circle.size + circle.xVel < 0)) {
console.log('Bounce X');
circle.xVel = -circle.xVel;
}
// If the circle size/position is greater than the canvas width, bounce y
if ((circle.yPos + circle.yVel + circle.size > canvas.height) || (circle.yPos + circle.yVel - circle.size < 0)) {
console.log('Bounce Y');
circle.yVel = -circle.yVel;
}
// Generates circle motion by adding position and velocity each frame
circle.xPos += circle.xVel;
circle.yPos += circle.yVel;
}
}
I'm not sure if I'm animating the correct thing. I've tried animating canvas2, but that didn't make sense to me.
PS - Sorry for the GitHub formatting, not sure why it looks like that.
PPS - Apologies for any junk code I didn't clean up. I've tried a lot of stuff and probably lost track of some of the changes.
PPPS - And forgive me for not making the answer self-contained. I thought linking to GitHub would be more useful, but I've updated the question to contain all the necessary info. Thanks for the feedback.
To get you started...
Here's how to clip an image into a circle using compositing.
The example code creates a single canvas logo-ball that you can reuse for each of your bouncing balls.
var logoball1=dreateImageInCircle(logoImg1,50);
var logoball2=dreateImageInCircle(logoImg2,50);
Then you can draw each logo-ball onto your main canvas like this:
ctx.drawImage(logoball1,35,40);
ctx.drawImage(logoball2,100,75);
There are many examples here on Stackoverflow of how to animate the balls around the canvas so I leave that part to you.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/m%26m600x455.jpg";
function start(){
var copy=createImageInCircle(img,50);
ctx.drawImage(copy,20,75);
ctx.drawImage(copy,150,120);
ctx.drawImage(copy,280,75);
}
function createImageInCircle(img,radius){
var c=document.createElement('canvas');
var cctx=c.getContext('2d');
c.width=c.height=radius*2;
cctx.beginPath();
cctx.arc(radius,radius,radius,0,Math.PI*2);
cctx.fill();
cctx.globalCompositeOperation='source-atop';
cctx.drawImage(img,radius-img.width/2,radius-img.height/2);
return(c);
}
body{ background-color:white; }
#canvas{border:1px solid red; }
<canvas id="canvas" width=512 height=512></canvas>

How to optimize canvas rendering for dynamic loading HTML5 game world?

I've been working on an isometric game engine for my own game. Currently, it's a big, open world with the map data being retrieved dynamically from the Node.js server. 
To understand what I'm doing... for the most part it's a tile based world. So each map has a max number of cols,rows (19) and each world has a max number of maps by col,row (6). So it's a 6x6 world map consisting of 19x19 tiles per map. Whenever the players move onto a new map/region, the client requests a 3x3 matrix of the surrounding maps with the center map being the map the player is currently on. This part is pretty well optimized.
My problem, however, is finding a great way to optimize the drawing onto the canvas. Currently, I don't have a lot of lag doing so, but I also have a fast computer, but I worry that at times it could cause others to lag / mess with the rendering of other graphics.
Basically, how I have it working right now is when the data is sent back from the server, it adds each map and all the tile images for each col/row it has to render into a buffer. Each loop of the game loop, it will basically render a small section of the 25 tiles onto the specific map's hidden canvas. When all of the requested maps are done rendering (after a few game loops), the camera will go ahead and merge these hidden maps into 1 big map canvas of the 3x3 matrix (by slicing parts from the hidden canvases and merging them onto the new canvas).
Ideally I would love this whole process to be async. but I've been looking into web workers and apparently they do not support canvas well. Has anyone come up with a process to do something similar and keep it well optimized?
Thanks!
Here's an example of rendering a 19x19 grid in each frame. A new random tile is added from right to left top to bottom in each frame. The grid is rendered in the same order and you can see that this works for overlapping tiles.
I think it's best to save each tile and make a function that renders the entire grid. So if the player gets updates in the 3x3 surrounding area then download and keep those tiles and re-render the entire grid.
update
I provided a function to eliminate overdraw and a toggle. This may increase performance for some people. It draws from bottom to top left to right. This draws the overlaying items first and with globalCompositeOperation "distination-over" tells the canvas to leave existing pixels alone when adding new content. This should mean less work to do in putting pixels on the canvas as it's not drawing over unused pixels.
var cols = 19;
var tile_width = 32;
var rows = 19;
var tile_height = 16;
var y_offset = 64;
var h_tw = tile_width / 2;
var h_th = tile_height / 2;
var frames = 0;
var fps = "- fps";
setInterval(function(){
fps = frames + " fps";
frames = 0;
}, 1000);
var can = document.getElementById('tile');
var ctx = can.getContext('2d');
var wcan = document.getElementById('world');
var wctx = wcan.getContext('2d');
wcan.width = cols * tile_width;
wcan.height = rows * tile_height + y_offset;
var tiles = initTiles();
document.getElementById('toggle').addEventListener('click', function() {
if (this.innerHTML == 'renderWorld') {
renderFn = renderWorldNoOverdraw;
this.innerHTML = "renderWorldNoOverdraw";
} else {
renderFn = renderWorld;
this.innerHTML = "renderWorld";
}
});
//renderWorld();
var ani_x = cols;
var ani_y = 0;
var renderFn = renderWorld;
ani();
function initTiles () {
var tiles = [];
for (var y = 0; y < rows; y++) {
var row = [];
for (var x = 0; x < cols; x++) {
var can = document.createElement('canvas');
can.width=tile_width;
can.height=tile_height+y_offset;
row[x]=can;
}
tiles[y] = row;
}
return tiles;
}
function ani() {
var can = tiles[ani_y][--ani_x]
if (ani_x == 0) ani_x = cols, ani_y++;
ani_y %= rows;
var ctx = can.getContext('2d');
randTile(can, ctx);
renderFn();
requestAnimationFrame(ani);
}
// renders from bottom left to right and skips
// drawing over pixels already present.
function renderWorldNoOverdraw() {
frames++;
wctx.clearRect(0,0,wcan.width,wcan.height);
wctx.save();
wctx.globalCompositeOperation = "destination-over";
wctx.translate(0, y_offset);
var x_off = 0;
var y_off = 0;
var y_off2 = 0;
for (var y = rows; y--;) {
x_off = (cols * h_tw)- ((rows-y) * h_tw);
y_off = y * h_th + tile_height;
y_off2 = y_off;
for (var x = 0; x < cols; x++) {
var can = tiles[y][x];
wctx.drawImage(can, x_off, y_off2 + y_offset);
y_off2 -= h_th;
x_off += h_tw;
}
}
wctx.translate(0,-y_offset);
wctx.fillStyle = "#ddaadd";
wctx.fillRect(0,0,wcan.width, wcan.height);
wctx.restore();
wctx.fillStyle= "black";
wctx.fillText(fps, 10, 10);
}
function renderWorld() {
frames++;
wctx.fillStyle = "#CCEEFF";
wctx.fillRect(0, 0, wcan.width, wcan.height);
wctx.save();
wctx.translate(0, y_offset);
var x_off = 0;
var y_off = 0;
var y_off2 = 0;
for (var y = 0; y < rows; y++) {
x_off = (cols * h_tw) + (y * h_tw) - h_tw;
y_off = y * h_th;
y_off2 = y_off;
for (var x = cols; x--;) {
var can = tiles[y][x];
wctx.drawImage(can, x_off, y_off2 - 64);
y_off2 += h_th;
x_off -= h_tw;
}
y_off += h_th;
x_off -= h_tw;
}
wctx.restore();
wctx.fillStyle= "black";
wctx.fillText(fps, 10, 10);
}
function randTile(can, ctx) {
var maxH = can.height - 24;
var ranH = Math.floor(Math.random() * maxH);
var h = Math.max(ranH, 1);
ctx.clearRect(0, 0, can.width, can.height);
ctx.beginPath();
ctx.save();
ctx.translate(0, can.height - 16);
ctx.moveTo(0, 8);
ctx.lineTo(16, 0);
ctx.lineTo(32, 8);
ctx.lineTo(16, 16);
ctx.lineTo(0, 8);
ctx.strokeStyle = "#333333";
ctx.stroke();
// random floor color
var colors = ["#dd9933", "#22aa00", "#66cccc", "#996600"];
ctx.fillStyle = colors[Math.floor(Math.random() * 4)];
ctx.fill();
// random building
if (Math.floor(Math.random() * 8) == 0) {
ctx.beginPath();
ctx.moveTo(8, 8);
ctx.lineTo(8, -h - 4);
ctx.lineTo(16, -h);
ctx.lineTo(16, 12);
ctx.lineTo(8, 8);
ctx.stroke();
ctx.fillStyle = "#333333";
ctx.fill();
ctx.beginPath();
ctx.moveTo(16, 12);
ctx.lineTo(16, -h);
ctx.lineTo(24, -h - 4);
ctx.lineTo(24, 8);
ctx.lineTo(16, 12);
ctx.stroke();
ctx.fillStyle = "#999999";
ctx.fill()
ctx.beginPath();
ctx.moveTo(16, -h);
ctx.lineTo(24, -h - 4);
ctx.lineTo(16, -h - 8);
ctx.lineTo(8, -h - 4);
ctx.moveTo(16, -h);
ctx.stroke();
ctx.fillStyle = "#CCCCCC";
ctx.fill()
}
ctx.restore();
}
body {
background-color: #444444;
}
<button id="toggle">renderWorld</button><br/>
<canvas id='tile' width="32" height="32" style="display:none"></canvas>
<canvas id="world" width="608" height="368">
</canvas>

Algorithm to build a pyramid with squares

I'm trying to build a pyramid using squares in HTML5 Canvas, I have an algoritm that is half working, the only problem is that after three days and some lack of math abilities I haven't been able to find the proper formula.
Here is what I have, check the code comments so you can see what part of the algorithm we have to change.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var W = 1000; var H = 600;
var side = 16;
canvas.width = W;
canvas.height = H;
function square(x, y) {
ctx.fillStyle = '#66FF00';
ctx.fillRect(x, y, side, side);
ctx.strokeStyle = '#000';
ctx.strokeRect(x, y, side, side);
}
function draw() {
ctx.fillRect(0, 0, W, H);
ctx.save();
for(var i = 0; i < 30; i++) {
for(var j = 0; j < i + 1; j++) {
square(
//Pos X
//This is what we have to change to
//make it look like a pyramid instead of stairs
W / 2 - ((side / 2) + (j * side)),
//Pos Y
side * (i + 1)
);
}
}
ctx.restore();
}
//STARTS DRAWING
draw();
This is the code working in jsfiddle so we can try it:
https://jsfiddle.net/g5spscpu/
The desired result is:
Well, I would love if someone could give me a hand, my brain is burning.
You need to use the i index in the formula for X position with:
W/2 - ((side / 2) + ((j - i/2) * side))
see https://jsfiddle.net/9esscdkc/

Overlap/hit test in javascript

Im trying to get a hit test/overlap test to work in the below code which creates 200 circles in a random position on a canvas. I am trying to store the positions of the circles in an array and then checking that array each time another circle is created in the for loop, if the randomly created x and y is too close to a already created circle it should keep getting a new random x and y until it isnt too close to an already created circle.
I just cant get it too work in the while loop.
Any help please...
Thanks
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", canvasDraw);
function canvasDraw () {
var c = document.getElementById("canvas");
var w = window.innerWidth;
var h = window.innerHeight;
c.width = w;
c.height = h;
var ctx = c.getContext("2d");
ctx.clearRect(0,0,c.width, c.height);
var abc = 0;
var colours = new Array ("rgb(0,100,0)", "rgb(51,102,255)");
var positions = new Array();
function hitTest(x, y) {
for(var p in positions) {
pp = p.split(",");
pp[0] = parseInt(pp[0]);
pp[1] = parseInt(pp[1]);
if(((x > (pp[0] - 24)) && (x < (pp[0] + 24))) && ((y > (pp[1] - 24)) && (y < (pp[1] + 24)))) {
return true;
}
}
return false;
}
//Loop 200 times for 200 circles
for (i=0; i<200; i++) {
var x = Math.floor(Math.random()*c.width);
var y = Math.floor(Math.random()*c.height);
while(hitTest(x, y) == true){
var x = Math.floor(Math.random()*c.width);
var y = Math.floor(Math.random()*c.height);
}
var pos = x.toString() + "," + y.toString();
positions.push(pos);
var radius = 10;
var r = radius.toString();
var b = colours[Math.floor(Math.random()*colours.length)];
circle(ctx,x,y, radius, b);
}
}
function circle (ctx, x, y, radius, b) {
ctx.fillStyle = b;
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
</script>
Some things before beginning:
Don't create arrays with new Array(), unless you specify the initial length. Use [];
Don't iterate through arrays using for...in: use a standard for with a counter. This is more a good practice;
Converting numbers into strings and converting back to numbers is useless and expensive. Use a small array to store both values;
Don't use "magic numbers", i.e. number with a precise value but hard to recognize immediately. Use named "constants" or put a comment near each of them telling what they mean, for future maintenance.
Ok, let's see the code.
if(((x > (pp[0] - 24)) && (x < (pp[0] + 24))) && ((y > (pp[1] - 24)) && (y < (pp[1] + 24))))
Honestly, what is this? I'd call it a cranky and obscure snippet. Recall what you've learnt at school:
var dx = pp[0] - x, dy = pp[1] - y;
if (dx * dx + dy * dy < 400) return true;
Isn't it much clearer?
Let's see the whole function:
function canvasDraw () {
var c = document.getElementById("canvas");
var w = window.innerWidth;
var h = window.innerHeight;
c.width = w;
c.height = h;
var ctx = c.getContext("2d");
ctx.clearRect(0,0,c.width, c.height);
// Lolwut?
// var abc = 0;
var colours = ["rgb(0,100,0)", "rgb(51,102,255)"];
var positions = [];
function hitTest(x, y) {
for (var j = 0; j < positions.length; j++) {
var pp = positions[j];
var dx = pp[0] - x, dy = pp[1] - y;
if (dx * dx + dy * dy < 400) return true;
}
return false;
}
// You declare the radius once and for all
var radius = 10;
// Declare the local scoped variables. You forgot i
var x, y, i;
for (i=0; i<200; i++) {
// How about a do...while instead of a while?
do {
var x = Math.floor(Math.random()*c.width);
var y = Math.floor(Math.random()*c.height);
// Testing with === is faster, always do it if you know the type
// I'll let it here, but if the type is boolean, you can avoid testing
// at all, as in while (hitTest(x, y));
} while (hitTest(x, y) === true);
positions.push([x, y]);
// This instruction is useless
// var r = radius.toString();
var b = colours[Math.floor(Math.random()*colours.length)];
circle(ctx,x,y, radius, b);
}
}
BEWARE, though, that depending on your canvas size, there could be no more room for another circle, so it could end in an infinite loop. Try to put 200 circles with a radius of 10 inside a 40x40 box...
There should be another test to do, and that could be complicated.

Categories

Resources