I'm trying to replicate the crude line connection function that I have working here, https://editor.p5js.org/knectar/sketches/0Thp1IJn but using objects in an array. It seems like this code should work, but the values aren't populating as needed to draw the connecting line. Any assistance would be appreciated!
Here's the code (or here https://editor.p5js.org/knectar/sketches/HYPwtjge):
var dotCount = 2;
var dot;
var xTempPos, yTempPos;
var xEndPos, xEndPos;
function setup() {
createCanvas(windowWidth, windowHeight);
noStroke();
fill(200);
for (let i = 0; i < dotCount; i++) {
dotArray.push(new Dot());
}
}
function draw() {
// background(0);
for (let i = 0; i < dotArray.length; i++) {
dotArray[i].sketch();
}
for (let i = dotArray.length - 1; i > 0; i--) {
dotArray[i].connect();
xEndPos = dotArray[i].xPos;
xEndPos = dotArray[i].yPos;
xTempPos = dotArray[i - 1].xPos;
yTempPos = dotArray[i - 1].yPos;
console.log(xTempPos);
}
}
class Dot {
constructor() {
this.xStartPos = random(width);
this.yStartPos = random(height);
this.rad = 5;
}
sketch() {
ellipse(this.xStartPos, this.yStartPos, this.rad);
}
connect() {
stroke(200);
strokeWeight(1);
line(this.xStartPos, this.yStartPos, xTempPos, yTempPos);
if (xTempPos <= xEndPos) {
xTempPos = xTempPos + 1;
}
if (yTempPos <= xEndPos) {
yTempPos = yTempPos + 1;
}
}
}```
The declaration of dotArray is missing.
var dotArray = [];
Furthermore it has to be xStartPos, yStartPos rather than xPos, yPos.
See the example:
var dotCount = 2;
var dot;
var xTempPos, yTempPos;
var xEndPos, xEndPos;
var dotArray = [];
function setup() {
//createCanvas(windowWidth, windowHeight);
createCanvas(400, 200);
for (let i = 0; i < dotCount; i++) {
dotArray.push(new Dot());
}
}
function draw() {
background(255, 255, 255);
fill(255, 0, 0);
stroke(255, 0, 0);
strokeWeight(1);
for (let i = 0; i < dotArray.length; i++) {
dotArray[i].sketch();
}
for (let i = dotArray.length - 1; i > 0; i--) {
dotArray[i].connect();
xEndPos = dotArray[i].xStartPos;
xEndPos = dotArray[i].yStartPos;
xTempPos = dotArray[i - 1].xStartPos;
yTempPos = dotArray[i - 1].yStartPos;
console.log(xTempPos);
}
}
class Dot {
constructor() {
this.xStartPos = random(width);
this.yStartPos = random(height);
this.rad = 5;
}
sketch() {
ellipse(this.xStartPos, this.yStartPos, this.rad);
}
connect() {
line(this.xStartPos, this.yStartPos, xTempPos, yTempPos);
if (xTempPos <= xEndPos) {
xTempPos = xTempPos + 1;
}
if (yTempPos <= xEndPos) {
yTempPos = yTempPos + 1;
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>
Related
I've got a small web app in development to simulate the Ising model of magnetism. I've found that the animation slows down considerably after a few seconds of running, and it also doesn't loop after 5 seconds like I want it to with the command:
setInteval(main, 500)
I've added start and stop buttons. When I stop the animation, and then restart it, it begins fresh at the usual speed, but again slows down.
My question is: what steps can I take to troubleshoot and optimize the performance of my canvas animation? I hope to reduce or mitigate this slowing effect.
JS code:
window.onload = function() {
var canvas = document.getElementById("theCanvas");
var context = canvas.getContext("2d");
var clength = 100;
var temperature = 2.1;
var playAnim = true;
canvas.width = clength;
canvas.height = clength;
var imageData = context.createImageData(clength, clength);
document.getElementById("stop").addEventListener("click",function(){playAnim=false;});
document.getElementById("start").addEventListener("click",function(){playAnim=true;});
function init2DArray(xlen, ylen, factoryFn) {
//generates a 2D array of xlen X ylen, filling each element with values defined by factoryFn, if called.
var ret = []
for (var x = 0; x < xlen; x++) {
ret[x] = []
for (var y = 0; y < ylen; y++) {
ret[x][y] = factoryFn(x, y)
}
}
return ret;
}
function createImage(array, ilen, jlen) {
for (var i = 0; i < ilen; i++) {
for (var j = 0; j < jlen; j++) {
var pixelIndex = (j * ilen + i) * 4;
if (array[i][j] == 1) {
imageData.data[pixelIndex] = 0; //r
imageData.data[pixelIndex+1] = 0; //g
imageData.data[pixelIndex+2] = 0; //b
imageData.data[pixelIndex+3] = 255; //alpha (255 is fully visible)
//black
} else if (array[i][j] == -1) {
imageData.data[pixelIndex] = 255; //r
imageData.data[pixelIndex+1] = 255; //g
imageData.data[pixelIndex+2] = 255; //b
imageData.data[pixelIndex+3] = 255; //alpha (255 is fully visible)
//white
}
}
}
}
function dU(i, j, array, length) {
var m = length-1;
//periodic boundary conditions
if (i == 0) { //top row
var top = array[m][j];
} else {
var top = array[i-1][j];
}
if (i == m) { //bottom row
var bottom = array[0][j];
} else {
var bottom = array[i+1][j];
}
if (j == 0) { //first in row (left)
var left = array[i][m];
} else {
var left = array[i][j-1];
}
if (j == m) { //last in row (right)
var right = array[i][0];
} else {
var right = array[i][j+1]
}
return 2.0*array[i][j]*(top+bottom+left+right); //local magnetization
}
function randInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
var myArray = init2DArray(clength, clength, function() {var c=[-1,1]; return c[Math.floor(Math.random()*2)]}); //creates a 2D square array populated with -1 and 1
function main(frame) {
if (!playAnim){return;} // stops
window.requestAnimationFrame(main);
createImage(myArray, clength, clength);
context.clearRect(0,0,clength,clength);
context.beginPath();
context.putImageData(imageData,0,0);
for (var z = 0; z < 10*Math.pow(clength,2); z++) {
i = randInt(clength-1);
j = randInt(clength-1);
var deltaU = dU(i, j, myArray, clength);
if (deltaU <= 0) {
myArray[i][j] = -myArray[i][j];
} else {
if (Math.random() < Math.exp(-deltaU/temperature)) {
myArray[i][j] = -myArray[i][j];
}
}
}
}
var timer = setInterval(main, 500);
}
So I got this jackpot coding. First it finds 7 unique random numbers between 1-36:
function RandomTal(Limit)
{
var RandomLottoTal
var Cont = true
while(Cont)
{
RandomLottoTal=Math.round(Math.random()*100+1)
if (RandomLottoTal <= Limit)
{
Cont = false
}
}
return RandomLottoTal;
}
function FindLottoTal()
{
var min = 1
var RandomTalNy
var LottoTal = []
for (var i=min; i<=7; i++)
{
RandomTalNy = RandomTal(36)
if(LottoTal.indexOf(RandomTalNy)<0)
{
LottoTal[i] = RandomTalNy
}
else
{
i--
}
}
DineLottoTal.value = LottoTal
return i;
}
Then when I have to draw the circle something doesn't work. What I want it to do is it checks all numbers from 1-36 and if it is the same as one of my 7 random jackpot numbers, it has to draw a red circle, else it has to draw a white circle.
Circle coding:
function TegnCirkel()
{
var canvas = document.getElementById("LottoPlade")
var ctx = canvas.getContext("2d")
var LottoTalNy = FindLottoTal()
for (var j=1; j<=4; j++)
{
var Tæller = 0
for (var i=1; i<=9; i++)
{
Tæller = Tæller + 1
XPos = i*100-50
YPos = j*100-50
if (LottoTalNy.indexOf(Tæller)<0)
{
// Color for white not yet added
ctx.beginPath()
ctx.arc(XPos,YPos,20,0,2*Math.PI)
ctx.stroke()
}
else
{
// Color for red not yet added
ctx.beginPath()
ctx.arc(XPos,YPos,20,0,2*Math.PI)
ctx.stroke()
}
}
}
}
Anyone know what's wrong or a fix.
Help is appreciated a lot :)
maybe it helps, but I did not have much time to understand what you wanted to do
jsfiddle
function TegnCirkel()
{
var canvas = document.getElementById("LottoPlade")
var ctx = canvas.getContext("2d")
var LottoTalNy = FindLottoTal()
for (var j=1; j<=4; j++)
{
var Tæller = 0
for (var i=1; i<=9; i++)
{
Tæller = Tæller + 1
XPos = i*100-50
YPos = j*100-50
if (LottoTalNy.toString().indexOf(Tæller)<0)
{
ctx.beginPath()
ctx.arc(XPos,YPos,20,0,2*Math.PI)
ctx.stroke()
}
else
{
ctx.beginPath()
ctx.arc(XPos,YPos,20,0,2*Math.PI)
ctx.stroke()
}
}
}
}
function RandomTal(Limit)
{
var RandomLottoTal
var Cont = true
while(Cont)
{
RandomLottoTal=Math.round(Math.random()*100+1)
if (RandomLottoTal <= Limit)
{
Cont = false
}
}
return RandomLottoTal;
}
function FindLottoTal()
{
var min = 1
var RandomTalNy
var LottoTal = []
for (var i=min; i<=7; i++)
{
RandomTalNy = RandomTal(36)
if(LottoTal.indexOf(RandomTalNy)<0)
{
LottoTal[i] = RandomTalNy
}
else
{
i--
}
}
FindLottoTal.value = LottoTal
return i;
}
For a fun little project I decided to program conway's game of life in javascript. My logic seems to make sense and each individual function does its job however I still dont get my intended result. I have an array called grid, which stores the value of all the cells, and if they are alive or dead. I check each individual cell, then check all 8 surrounding cells to count neighbors, repeat for every other cell. At some point my grid no longer stores the correct value and resets. At this point I'm starting to think it's a javascript problem.
<body>
<style>
* {
padding: 0;
margin: 0;
}
body {
overflow: hidden;
}
canvas {
background: #FFFFFF;
display: block;
margin: 0 auto;
}
</style>
<canvas id="canvas" style="border:1px solid #000000;"></canvas>
</body>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var Game = {};
var nextGrid, emptyGrid, grid;
Game.horCells = 30;
Game.cellSize = canvas.width / Game.horCells;
Game.verCells = Math.floor(canvas.height / Game.cellSize);
Game.startLives = 80;
config();
//setInterval(run, 1000);
function config() {
console.log("in config");
emptyGrid = newGrid(Game.horCells, Game.verCells);
grid = emptyGrid;
nextGrid = emptyGrid;
//Manual Setup
for (var i = 0; i < Game.startLives; i++) {
//grid[getRandomInt(0, Game.horCells - 1)][getRandomInt(0, Game.verCells - 1)] = true;
}
grid[0][3] = true;
grid[1][3] = true;
grid[2][3] = true;
}
function run() {
console.log("gread" + grid[3][3]);
draw();
update();
}
function draw() {
console.log("Draw");
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < Game.horCells; i++) {
for (var j = 0; j < Game.verCells; j++) {
if (grid[i][j] === false) {
ctx.fillStyle = "#FFFFFF";
} else if (grid[i][j] === true) {
console.log("drawing live");
ctx.fillStyle = "#000000";
}
ctx.fillRect(i * Game.cellSize, j * Game.cellSize, Game.cellSize, Game.cellSize);
}
}
}
function update() {
for (var p = 0; p < Game.horCells; p++) {
for (var k = 0; k < Game.verCells; k++) {
nextGrid[p][k] = survival(p, k);
}
}
}
function survival(x, y) {
var neighbours = 0;
for (var l = 0; l < 3; l++) {
for (var m = 0; m < 3; m++) {
var sx = (x - 1) + l;
var sy = (y - 1) + m;
//Check bounds
if (inBounds(sx, sy) === true && grid[sx][sy]) {
neighbours++;
}
}
}
if (grid[x][y]) {
neighbours--;
if (neighbours === 2 || neighbours === 3) {
return true;
} else if (neighbours < 2 || neighbours > 3) {
console.log("DIED");
return false;
}
} else if (grid[x][y] === false && neighbours === 3) {
return true;
} else {
console.log("DIED");
return false;
}
}
function inBounds(x, y) {
return (x >= 0 && x < Game.horCells && y >= 0 && y < Game.horCells);
}
function newGrid(xCells, yCells) {
var gridd = new Array(xCells);
for (var i = 0; i < xCells; i++) {
gridd[i] = new Array(yCells);
}
for (var j = 0; j < xCells; j++) {
for (var k = 0; k < yCells; k++) {
gridd[j][k] = false;
}
}
return gridd;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>
emptyGrid = newGrid(Game.horCells, Game.verCells);
grid = emptyGrid;
nextGrid = emptyGrid
Creates 1 grid, then assigns grid and nextGrid to the same object. Again, grid and nextGrid are the same object. Any changes you make to 1 will happen to the other.
Create 2 separate grids so they can be changed independently:
grid = newGrid(Game.horCells, Game.verCells);
nextGrid = newGrid(Game.horCells, Game.verCells);
Or, to neaten it up slightly:
var g = () => newGrid(Game.horCells, Game.verCells);
grid = g();
nextGrid = g();
Just to clear up the question in the comments:
var g = () => newGrid(Game.horCells, Game.verCells);
Is (basically) the same thing as:
var g = function() {
return newGrid(Game.horCells, Game.verCells);
}
It's known as a "fat-arrow" function.
Both bits do the same thing though: they create a function that returns a new grid. This has the benefit of not needing to write newGrid(Game.horCells, Game.verCells); twice.
I used an arrow function instead of the function keyword because the latter is giant and ugly, which takes away from the goal of cleaning up the code.
I'm doing something a bit different, instead of putting the scoreboard outside of the Canvas, its inside it and associated with the canvas properties.
It's fully functional but I don't understand why it does not add to the score whenever a row is cleared.
Here's that part:
var totalPoints = 0;
function erase() {
for ( var y = rows - 1; y >= 0; y--) {
var full = true;
for (var x = 0; x < columns; x++) {
if (board[y][x] == 0) {
full = false;
totalPoints--;
break;
}
}
if (full) {
totalPoints++;
for ( var j = y; j > 0; j--) {
for ( var x = 0; x < columns; x++) {
board[j][x] = board[j-1][x]
}
}
++y;
}
}
}
function showOnload(){
c.fillStyle = "black";
c.fillText("scores", 200, 100);
c.fillText(totalPoints, 200, 140);
}
Note:
I've the showOnload function as a body onload for my HTML page, does this have anything to do with why it doesn't change?
Update score each time it is changed.
var totalPoints = 0;
function erase() {
for ( var y = rows - 1; y >= 0; y--) {
var full = true;
for (var x = 0; x < columns; x++) {
if (board[y][x] == 0) {
full = false;
totalPoints--;
showOnload(); //HERE
break;
}
}
if (full) {
totalPoints++;
showOnload(); //HERE
for ( var j = y; j > 0; j--) {
for ( var x = 0; x < columns; x++) {
board[j][x] = board[j-1][x]
}
}
++y;
}
}
}
function showOnload(){
c.fillStyle = "black";
c.fillText("scores", 200, 100);
c.fillText(totalPoints, 200, 140);
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Html
<html>
<head>
<script type="text/javascript" src="/test.js"></script>
<script type="text/javascript">
start();
</script>
</head>
<body>
</body>
</html>
Java script
var points = 1;
var points1;
var DELAY = 30;
var SPEED = 5;
var MAX_DY = 12;
var OBSTACLE_WIDTH = 30;
var OBSTACLE_HEIGHT = 100;
var TERRAIN_WIDTH = 10;
var MIN_TERRAIN_HEIGHT = 20;
var MAX_TERRAIN_HEIGHT = 50;
var POINTS_PER_ROUND = 5;
var DUST_RADIUS = 3;
var DUST_BUFFER = 10;
var NUM_OBSTACLES = 3;
var copter;
var dy = 0;
var clicking = false;
var score; // text you see on the screen
var obstacles = [];
var top_terrain = [];
var bottom_terrain = [];
var dust = [];
function start(){
starta();
}
function starta() {
setup();
setTimer(game, DELAY);
mouseDownMethod(onMouseDown);
mouseUpMethod(onMouseUp);
setTimer(points2, 10)
}
function points2(){
points1 = points/100
return points1;
}
function setup() {
setBackgroundColor(Color.black);
copter = new WebImage("image.png");
copter.setSize(25, 50);
copter.setPosition(getWidth()/3, getHeight()/2);
copter.setColor(Color.blue);
add(copter);
addObstacles();
addTerrain();
score = new Text("0");
score.setColor(Color.white);
score.setPosition(10, 30);
add(score);
}
function updateScore() {
points += POINTS_PER_ROUND;
score.setText(points);
}
function game() {
updateScore();
if (hitWall()) {
lose();
return;
}
var collider = getCollider();
if (collider != null) {
if (collider != copter) {
lose();
return;
}
}
if (clicking) {
dy -= 1;
if (dy < -MAX_DY) {
dy = -MAX_DY;
}
} else {
dy += 1;
if (dy > MAX_DY) {
dy = MAX_DY;
}
}
copter.move(0, dy);
moveObstacles();
moveTerrain();
moveDust();
addDust();
}
function onMouseDown(e) {
clicking = true;
}
function onMouseUp(e) {
clicking = false;
}
function addObstacles() {
for (var i = 0; i < NUM_OBSTACLES; i++) {
var obstacle = new WebImage("image.jpg");
obstacle.setSize(50, 100);
obstacle.setColor(Color.green);
obstacle.setPosition(getWidth() + i * (getWidth()/NUM_OBSTACLES),
Randomizer.nextInt(0, getHeight() - OBSTACLE_HEIGHT));
obstacles.push(obstacle);
add(obstacle);
}
}
function moveObstacles() {
for (var i=0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
obstacle.move(-points1, 0);
if(obstacle.getX() < 0) {
obstacle.setPosition(getWidth(),
Randomizer.nextInt(0, getHeight() - OBSTACLE_HEIGHT));
}
}
}
function hitWall() {
var hit_top = copter.getY() < 0;
var hit_bottom = copter.getY() + copter.getHeight() > getHeight();
return hit_top || hit_bottom;
}
function lose() {
stopTimer(game);
var text = new Text("You Lose!");
text.setColor(Color.red);
text.setPosition(getWidth()/2 - text.getWidth()/2,
getHeight()/2);
add(text);
}
function getCollider() {
var topLeft = getElementAt(copter.getX()-1, copter.getY()-1);
if (topLeft != null) {
return topLeft;
}
var topRight = getElementAt(copter.getX() + copter.getWidth() + 1,
copter.getY() - 1);
if (topRight != null) {
return topRight;
}
var bottomLeft = getElementAt(copter.getX()-1,
copter.getY() + copter.getHeight() + 1);
if (bottomLeft != null) {
return bottomLeft;
}
var bottomRight = getElementAt(copter.getX() + copter.getWidth() + 1,
copter.getY() + copter.getHeight() + 1);
if (bottomRight != null) {
return bottomRight;
}
return null;
}
function addTerrain() {
for (var i=0; i <= getWidth() / TERRAIN_WIDTH; i++) {
var height = Randomizer.nextInt(MIN_TERRAIN_HEIGHT, MAX_TERRAIN_HEIGHT);
var terrain = new Rectangle(TERRAIN_WIDTH, height);
terrain.setPosition(TERRAIN_WIDTH * i, 0);
terrain.setColor(Color.green);
top_terrain.push(terrain);
add(terrain);
height = Randomizer.nextInt(MIN_TERRAIN_HEIGHT, MAX_TERRAIN_HEIGHT);
var bottomTerrain = new Rectangle(TERRAIN_WIDTH, height);
bottomTerrain.setPosition(TERRAIN_WIDTH * i,
getHeight() - bottomTerrain.getHeight());
bottomTerrain.setColor(Color.green);
bottom_terrain.push(bottomTerrain);
add(bottomTerrain);
}
}
function moveTerrain() {
for (var i=0; i < top_terrain.length; i++) {
var obj = top_terrain[i];
obj.move(-points1, 0);
if (obj.getX() < -obj.getWidth()) {
obj.setPosition(getWidth(), 0);
}
}
for (var i=0; i < bottom_terrain.length; i++) {
var obj = bottom_terrain[i];
obj.move(-points1, 0);
if (obj.getX() < -obj.getWidth()) {
obj.setPosition(getWidth(), getHeight() - obj.getHeight());
}
}
}
function addDust() {
var d = new Circle(DUST_RADIUS);
d.setColor("#ffd700");
d.setPosition(copter.getX() - d.getWidth(),
copter.getY() + DUST_BUFFER);
dust.push(d);
add(d);
}
function moveDust() {
for (var i=0; i < dust.length; i++) {
var d = dust[i];
d.move(-points1, 0);
d.setRadius(d.getRadius() - 0.1);
if(d.getX() < 0) {
remove(d);
dust.remove(i);
i--;
}
}
}
Okay so here is my script. The script works perfectly fine on a codehs sandbox, but now that I want to set it on my own website it is not working. Could some one please help me out. Thank you.
Could some one please tell me how I would execute this code from test.js. Thank you.
You need to include the .js to your HTML page, like this:
<script type="text/javascript" src="/test.js"></script>
<script type="text/javascript">
start(); //starts your program
</script>