Following is the algorithm for arranging circles in a spiral fashion.
Following clockwise direction.
following is the pseudocode (overall).
let dir = [1, 0]
function checkIntersect(c0, c1) {
const {x0, y0, r0} = c0
const {x1, y1, r1} = c1
return Math.hypot(x0-x1, y0-y1) <= (r0 + r1);
}
for (let i = 0; i < circleCount; i++) {
for (let j = 0; j < circleCount; j++) {
if (checkIntersect(circles[i], circles[j])) {
incrementLocation(circles[j])
flip(dir)
}
}
}
this is what I came up with for spiralling, but it's not working!!
const spiralRadii = 3;
for (let i = 1; i <= radius; i++) {
let x = 0;
let y = 0;
for (let j = 0; j <= 2 * i; j++) {
if (i % 2 === 0) {
if (j <= i) {
x--;
console.log(x, y);
} else {
y++;
console.log(x, y);
}
} else {
if (j <= i) {
x++;
console.log(x, y);
} else {
y--;
console.log(x, y);
}
}
}
}
In this manner how can I fill up the whole space with circles with address in a clock wise spiral fashion?
Always follow Clockwise direction && during each iteration check if clockwise direction is occupied, if not move everything else to that position (while keeping the current one at the previous position),
if occupied move forward
Related
As you can see, each ellipse is part of a wave object and the fill is getting applied on each frame over and over and giving this blinking effect on all ellipses. I want to take a random colour and assign to each ellipse when it is drawn so that it remains with that fill colour instead of defining a new colour at each frame. I tried a lot but couldn't achieve that. Any help would be appreciated.
class Wave {
constructor(amp, period, phase) {
this.amplitude = amp;
this.period = period;
this.phase = phase;
}
evaluate(x) {
return sin(this.phase + (TWO_PI * x) / this.period) * this.amplitude;
}
update() {
this.phase += 0.05;
}
}
let waves = [];
let y;
function setup() {
createCanvas(600, 400);
for (let i = 0; i < 5; i++) {
waves[i] = new Wave(random(20, 80), random(100, 600), random(TWO_PI));
}
}
function draw() {
background(0);
for (let x = 0; x < width; x += 10) {
for (let wave of waves) {
y = wave.evaluate(x);
noStroke();
fill(random(255), random(255), random(255));
ellipse(x, y + height / 2, 6);
}
}
for (let wave of waves) {
wave.update();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Create a list of about 20 colors for each wave. Use color() to create a color:
for (let i = 0; i < 5; i++) {
waves[i] = new Wave(random(20, 80), random(100, 600), random(TWO_PI));
colors = [];
for (let j = 0; j < 20; j++) {
colors.push(color(random(255), random(255), random(255)))
}
waves_colors.push(colors);
}
Use this color to draw the waves. Use the % (modulo) operator to compute the rest of an integra division. The colors are repeated after every 20 points:
for (let i = 0; i < 5; i++) {
wave = waves[i];
colors = waves_colors[i];
for (let j = 0; j < width/10; j ++) {
x = j*10;
y = wave.evaluate(x);
fill(colors[j % colors.length]);
ellipse(x, y + height / 2, 6);
}
}
class Wave {
constructor(amp, period, phase) {
this.amplitude = amp;
this.period = period;
this.phase = phase;
}
evaluate(x) {
return sin(this.phase + (TWO_PI * x) / this.period) * this.amplitude;
}
update() {
this.phase += 0.05;
}
}
let waves = [];
let waves_colors = [];
let y;
function setup() {
createCanvas(600, 400);
for (let i = 0; i < 5; i++) {
waves[i] = new Wave(random(20, 80), random(100, 600), random(TWO_PI));
colors = [];
for (let j = 0; j < 20; j++) {
if (i % 2 == 1)
colors.push(color(0, 0, 255, random(128,255)));
else
colors.push(color(random(255), random(255), random(255)))
}
waves_colors.push(colors);
}
}
function draw() {
background(0);
noStroke();
for (let i = 0; i < 5; i++) {
wave = waves[i];
colors = waves_colors[i];
for (let j = 0; j < width/10; j ++) {
x = j*10;
y = wave.evaluate(x);
fill(colors[j % colors.length]);
ellipse(x, y + height / 2, 6);
}
}
for (let wave of waves) {
wave.update();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
This is in continuation to my previous post here Changing color of intersecting area of squares
I was able to make the intersecting area of the squares change color. The issue was that I wanted multiple intersecting squares and not a single one so I modified the code. Now the problem is that the square is leaving a trail since it is drawing square wherever it moves. And it starts to slow down after a while. How can I overcome this
function draw() {
background(135,206,250);
myColour = (255);
// if a square is being dragged, update its position
if (this.dragObject != null) {
this.dragObject.position.x = mouseX;
this.dragObject.position.y = mouseY;
}
//draw all squares
for (let i = 0; i < squares.length; i++) {
let s = squares[i];
s.show();
}
for (let i = 0; i < squares.length; i++) {
for (let j = i + 1; j < squares.length; j++) {
//block checking collision
if (i != j && squares[i].collides(squares[j])) {
squares[i].changecolor();
//set intersection color
fill(myColour);
//calculate parameters
newX = Math.max(squares[i].position.x, squares[j].position.x);
newY = Math.max(squares[i].position.y, squares[j].position.y);
newW = Math.min(squares[i].position.x + squares[i].w, squares[j].position.x + squares[j].w) - newX;
newH = Math.min(squares[i].position.y + squares[i].h, squares[j].position.y + squares[j].h) - newY;
//draw rectangle
let Osquare = new OverlappingSquares(newX, newY, newW, newH);
overlappingsquares.push(Osquare);
}
}
}
}
changecolor() {
// fill(random(255), random(255), random(255));
// background(200, 255, 100);
for (let i = 0; i < squares.length; i++) {
let s = squares[i];
s.show();
}
for (let i = 0; i < overlappingsquares.length; i++) {
let s = overlappingsquares[i];
s.show();
}
}
//Overlapping sqaures class
class OverlappingSquares {
constructor(X, Y, W, H) {
this.w = W;
this.h = H;
this.position = {
x: X,
y: Y
};
}
show() {
fill(myColour)
rect(this.position.x, this.position.y, this.w, this.h);
}
}
I need some help in printing fractal tree using JavaScript.
I have written code which prints tree sequence according to the rules defined for the tree, but having some trouble to print the tree. Thanks for all the help.
Here is the code:
var sentence = "F";
var rules = [];
rules[0] = {
a: "F",
b: "F[+F]F[-F]F"
}
setup();
function setup() {
turtle();
for (i = 0; i < 2; i++){
generate();
}
}
function turtle(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext('2d');
for (var i = 0; i < sentence.length; i++){
context.beginPath();
var current = sentence.charAt(i);
if (current == "F"){
context.stroke();
context.lineTo(50,50);
}else if (current == "+"){
context.rotate(20*Math.PI/180);
}else if (current == "-"){
context.rotate(-20*Math.PI/180);
}else if (current == "["){
context.save();
}else if (current == "]"){
context.restore();
}
}
}
function generate(){
var nextSentence = "";
for (var i = 0; i < sentence.length; i++){
var current = sentence.charAt(i);
var found = false;
for (var j = 0; j < rules.length; j++ ){
if (current == rules[j].a){
found = true;
nextSentence += rules[j].b;
console.log(nextSentence);
break;
}
}
if (!found){
nextSentence += current;
}
}
sentence = nextSentence;
turtle();
}
I am able to print a tree sequence, but need some help in converting that tree sequence to be able to print a tree on the canvas.
The output should look something like this:
There are some issue with your drawing logic. You code seems to be assuming that save() and restore() also save the coordinates and restore them -- they don't. You aren't using rotate() correctly (it rotates relative to the origin so you need to also translate()). You're doing absolute lineto() when you should be doing it relative to the current position. And moving in the wrong direction. And other issues.
Here's my rework of your code to make it run just enough to produce the example tree:
var sentence = "F";
var rules = [];
rules[0] = {
a: "F",
b: "F[+F]F[-F]F"
}
var x = 150; // starting x
var y = 400; // starting y
var y_stack = []; // save & restore don't handle coordinates
function turtle(sentence, context) {
for (var i = 0; i < sentence.length; i++) {
var current = sentence.charAt(i);
if (current == "F") {
y -= 35;
context.lineTo(x, y);
context.stroke();
} else if (current == "+") {
context.translate(x, y);
context.rotate(20 * Math.PI / 180);
context.translate(-x, -y);
} else if (current == "-") {
context.translate(x, y);
context.rotate(-20 * Math.PI / 180);
context.translate(-x, -y);
} else if (current == "[") {
context.save();
y_stack.push(y);
} else if (current == "]") {
context.restore();
y = y_stack.pop();
context.moveTo(x, y)
}
}
}
function generate(sentence) {
var nextSentence = "";
for (var i = 0; i < sentence.length; i++) {
var current = sentence.charAt(i);
var found = false;
for (var j = 0; j < rules.length; j++ ) {
if (current == rules[j].a) {
found = true;
nextSentence += rules[j].b;
break;
}
}
if (!found) {
nextSentence += current;
}
}
return nextSentence;
}
function draw() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext('2d');
context.moveTo(x, y);
for (i = 0; i < 2; i++) {
sentence = generate(sentence);
}
console.log(sentence);
turtle(sentence, context);
}
I'm programming Conway's Game of Life and have produced a working, smooth JS program. What I do in the working version is to check each neighboring coordinate of every coordinate in the grid, and either kill or spawn it based on its number of neighbors. Now I want to make the algorithm more efficient by keeping track of which coordinates are alive, and only process those and their neighbors, instead of the whole grid. I made this alternative program:
var g = 0;
var cellMatrix = new Array();
var height = 68;
var width = 100;
var livingCellIndex = 0;
var livingCells = new Array();
writeBoard();
declareFirstGeneration();
live();
function live() {
processGeneration();
g++;
setTimeout(live, speed);
}
function declareNextGeneration() {
livingCells[g + 1] = new Array();
cellMatrix[g + 1] = new Array();
for (var x = 0; x < width; x++) {
cellMatrix[g + 1][x] = new Array();
for (var y = 0; y < height; y++) {
cellMatrix[g + 1][x][y] = false;
}
}
}
function declareFirstGeneration() {
livingCells[g] = new Array();
cellMatrix[g] = new Array();
for (var x = 0; x < width; x++) {
cellMatrix[g][x] = new Array();
for (var y = 0; y < height; y++) {
cellMatrix[g][x][y] = false;
}
}
}
function processGeneration() {
declareNextGeneration();
livingCellIndex = 0;
var x, y;
for (var i = 0; i < livingCells[g].length; i++) {
x = livingCells[g][i][0];
y = livingCells[g][i][1];
numberOfNeighbors = getLivingNeighbors(x, y);
//console.log("numberOfNeighbors", numberOfNeighbors);
if (numberOfNeighbors == 2 || numberOfNeighbors == 3) {
spawnCell(g + 1, x, y);
} else {
killCell(g + 1, x, y);
}
for (var neighborX = x - 1; neighborX <= x + 1; neighborX++) {
for (var neighborY = y - 1; neighborY <= y + 1; neighborY++) {
if (neighborX < width && neighborX >= 0 && neighborY < height && neighborY >= 0) {
numberOfNeighbors = getLivingNeighbors(neighborX, neighborY);
//console.log(g, neighborX, neighborY, "has ", numberOfNeighbors, " neighbors");
if (numberOfNeighbors == 3) {
spawnCell(g + 1, neighborX, neighborY);
}
}
}
}
}
refreshGenerationDisplay(x,y);
}
function spawnCell(g, x, y) {
cellMatrix[g][x][y] = true;
livingCells[g][livingCellIndex] = new Array(2);
livingCells[g][livingCellIndex][0] = x;
livingCells[g][livingCellIndex][2] = y;
document.getElementById(x + '-' + y).style.background = "green"; // visual grid
livingCellIndex++;
}
function killCell(g, x, y) {
cellMatrix[g][x][y] = false;
document.getElementById(x + '-' + y).style.background = "none"; // visual grid
}
But I find that it is a lot slower than my first program. It seems like the computational cost of calculating each generation seems to increase with each generation. This surprises me because I though less data is handled in this alternative algorithm. I'm not sure if it is of interest, but here is the first version:
var g = 0;
var cellMatrix = new Array();
var height = 68;
var width = 100;
declareThisGeneration();
function live() {
g++;
processGeneration();
setTimeout(live, speed);
}
function processGeneration() {
if (oscillation) adjustGForOscillation();
if (g > 0) {
processNormalGeneration();
} else {
processFirstGeneration();
}
}
function processFirstGeneration() {
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
processFirstGenCell(g, x, y);
}
}
}
function processFirstGenCell(g, x, y) {
if (cellMatrix[g][x][y]) { //if alive
spawnCell(g, x, y);
} else { //if dead
killCell(g, x, y);
}
}
function processNormalGeneration() {
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
processCell(g, x, y);
}
}
}
function processCell(g, x, y) {
var livingNeighbors = getLivingNeighbors(g - 1, x, y);
if (cellMatrix[g - 1][x][y]) { //if alive
if (livingNeighbors != 2 && livingNeighbors != 3) {
killCell(g, x, y);
} else {
spawnCell(g, x, y);
}
} else { //if dead
if (livingNeighbors == 3) {
spawnCell(g, x, y);
} else {
killCell(g, x, y);
}
}
}
function spawnCell(g, x, y) {
cellMatrix[g][x][y] = true;
document.getElementById(x + '-' + y).className = 'alive';
}
function killCell(g, x, y) {
cellMatrix[g][x][y] = false;
document.getElementById(x + '-' + y).className = ''
}
My question is, what makes the "improved" algorithm so slow, and how can I reduce its cost?
Version 1 // first, fastest
Version 2 // new, slower
You keep allocating new Arrays for each generation in the new version; in the old version, you keep re-using the same grid. In addition to being slower, if not a REASON for it being slower, is that your memory footprint keeps growing.
One possible explanation is that if you keep track on too many things, the computer will need to allocate more memory to store them, and that takes time.
I am working on a top down video game with the crafty.js game library and I keep having to repeat a piece of code to make borders and the background sprite, So i want to put it into its own seperate function and call it, the problem is whenever I do this with traditional javascript syntax it causes an error, and i cant work out how else to do it: heres my scenes code:
Crafty.scene('World', function() {
//Draw Floor
for (var i = 0; i < 32; i++)
{
for (var y = 0; y < 24; y++)
{
Crafty.e('GrateFloor').at(i, y);
}
}
//Draw borders, gotta find a more code efficient way
for (var i = 0; i < 32; i++)
{
Crafty.e('Border').at(i, 0);
}
for (var y = 0; y < 24; y++)
{
Crafty.e('Border').at(0, y);
}
for (var y = 0; y < 24; y++)
{
Crafty.e('Border').at(31, y);
}
for (var y = 0; y < 32; y++)
{
Crafty.e('Border').at(y, 23);
}
//draw in game entities such as the player and obstacles
//drawing walls here
//horizontal walls
for (var y = 10; y <29; y++)
{
Crafty.e('WallHor').at(y, 20);
}
for (var y = 10; y <29; y++)
{
Crafty.e('WallHor').at(y, 5);
}
//vertical walls
for (var i = 6; i <20; i++)
{
Crafty.e('WallVert').at(29, i);
}
for (var i = 6; i <12; i++)
{
Crafty.e('WallVert').at(9, i);
}
for (var i = 14; i <20; i++)
{
Crafty.e('WallVert').at(9, i);
}
//single wall points
Crafty.e('WallTpRht').at(29,5);
Crafty.e('WallBtmRht').at(29,20);
Crafty.e('WallTpLft').at(9,5);
Crafty.e('WallBtmLft').at(9,20);
//everything else
Crafty.e('Enemy').at(20, 10);
Crafty.e('Teleporter1').at(1, 11);
Crafty.e('Player').at(15,15);
});
Crafty.scene('Loading', function() {
//Load in Visual Assets
Crafty.e('2D, DOM, Text')
.attr({ x: 15, y: 15 })
.text('Loading...');
Crafty.load(['assets/White_Male_Student_Animation_Bitmap.gif', 'assets/Walls_Bitmap.gif'], function(){
//Define terrain
Crafty.sprite(24, 24, 'assets/Walls_Bitmap.gif' , {
spr_WallWireHor: [0,0],
spr_Border: [0,1],
spr_WallWireVert: [1,1],
spr_WallWireTopRight: [1,0],
spr_WallWireBottomRight: [1,2],
spr_RobotSkull: [0,2],
spr_WallWireTopLeft: [2,0],
spr_WallWireBottomLeft: [2,1],
spr_Teleporter: [3,0],
spr_GrateFloor: [3,1],
})
//Define player
Crafty.sprite(25, 36.75, 'assets/White_Male_Student_Animation_Bitmap.gif' , {
spr_player: [0,0],
spr_BattlePlayer: [0,1],
},0, 0)
Crafty.scene('World')
})
});
//Screen for all combat to happen upon
Crafty.scene('BattleScreen', function() {
Crafty.e('2D, DOM, Text')
.attr({ x: 24, y: 22 })
.text('Monster destroyed!');
//Draw borders, gotta find a more code efficient way
for (var i = 0; i < 32; i++)
{
Crafty.e('Border').at(i, 0);
}
for (var y = 0; y < 24; y++)
{
Crafty.e('Border').at(0, y);
}
for (var y = 0; y < 24; y++)
{
Crafty.e('Border').at(31, y);
}
for (var y = 0; y < 32; y++)
{
Crafty.e('Border').at(y, 23);
}
//draws Player sprite for the combat screen
Crafty.e('BattlePlayer').at(16,20);
});
Crafty.scene('HubWorld', function() {
//Draw Floor
for (var i = 0; i < 32; i++)
{
for (var y = 0; y < 24; y++)
{
Crafty.e('GrateFloor').at(i, y);
}
}
//Draw borders, gotta find a more code efficient way
for (var i = 0; i < 32; i++)
{
Crafty.e('Border').at(i, 0);
}
for (var y = 0; y < 24; y++)
{
Crafty.e('Border').at(0, y);
}
for (var y = 0; y < 24; y++)
{
Crafty.e('Border').at(31, y);
}
for (var y = 0; y < 32; y++)
{
Crafty.e('Border').at(y, 23);
}
//draw other stuff
Crafty.e('Player').at(28,11);
Crafty.e('Teleporter2').at(30,11);
});
I want to move the Draw floor and Draw boders bits into there own subroutine, and I also need to know how to pass variables to and from functions with crafty.js
Crafty is a framework that uses the component design pattern. (http://gameprogrammingpatterns.com/component.html)
A component is exactly what you are asking for, a reusable piece of code.
So you should create a component which draws the floor and another for the border.
But first you should think again about the way you are drawing. Entities should not be used like that, except if you explicitely need that many entities. An entity is basically an ID with a list of components. The components should do the hard work, not the entities.
Take a look at the TextShadow component below, maybe it helps you to understand the idea:
var TextShadow = {
init: function init () {
this.requires('DOM');
this._textShadowColor = '#FFFFFF';
this._apply();
},
_apply: function _apply () {
this.css('text-shadow', '1px 1px 2px ' + this._textShadowColor);
},
textShadowColor: function textShadowColor (color) {
this._textShadowColor = color;
this._apply();
return this;
}
};
Crafty.c('TextShadow', TextShadow);