Loading Image in P5.js - javascript

Hey I hope somebody can help me out with this question, well basically I am trying to upload a picture in my canvas through the p5.js library. And as soon as I load my html file I get this:
I am using brackets, I already tried to set up a web server with wamp server but same thing happened. Here is the code:
//HomePage.js
var rect = [];
var rooms = [];
function preload() {
for (var i = 0; i <= 1; i++){
rooms[i] = loadImage("Raeume/" + i + ".jpg");
}
}
function setup() {
cnv = createCanvas(1000, 600);
}
function mousePressed() {
var r = floor(random(0, rooms.length));
var b = new Raeume(mouseX, mouseY, rooms[r]);
rooms.push(b);
}
function draw() {
background(0);
for (var i = rooms.length-1; i >= 0; i--) {
rooms[i].update();
rooms[i].display();
}
}
//Raeume.js
function Room (x, y, img) {
this.x = x;
this.y = y;
this.img = img;
this.display = function () {
imageMode(CENTER);
image(img, this.x, this.y, 100, 100);
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Raum 007</h1>
<script src="p5/p5.min.js"></script>
<script src="HomePage.js"></script>
<script src="Raeume.js"></script>
</body>
</html>
I really hope you guys can help me on this one! Thanks!

Well, for one, your rooms array is holding first two images (assuming those are the right urls), and then you also add a Raeume object onto the end on mousePressed. Thus, when you call update and display on each entity in the array, it might throw some errors. It's very hard to tell what's the real problem since you don't have an example, but I would say the most likely problem is that your images aren't actually named 0.jpg and 1.jpg. If that's not the prob, then you could try running it in firefox, as I think it's more friendly with p5.js.

Related

"Exception has occured: TypeError: Arrary.prototype.forEach called on null or undefined" in p5.js file

After trying to run some p5.js code in Visual Studio Code, I came upon this error. My HTML Code is below, and I copied and pasted it straight from the P5 editor:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
My javascript code is below, and when running in p5, no errors come up:
var numOfFood;
var foodList;
var numOfSlimes;
var slimesList;
function setup() {
createCanvas(400, 400);
numOfFood = prompt("Enter the amount of food that should be spawned: ");
numOfSlimes = prompt("Enter the amount of slimes to be spawned: ");
foodList = [];
slimesList = [];
background(220);
rect(25, 25, width - 50, height - 50);
spawnFood(numOfFood);
initializeSlimes(numOfSlimes);
}
// SLIME
Slime = function (x, y) {
this.x = x;
this.y = y;
}
Slime.prototype.draw = function () {
ellipse(this.x, this.y, 12, 12);
}
Slime.prototype.assignFood = function (index) {
this.food = foodList[index];
this.foodIndex = index;
}
// SLIME
// HAWK
Hawk = function (x, y) {
Slime.call(this, x, y);
this.type = "HAWK";
}
Hawk.prototype = Object.create(Slime.prototype);
//HAWK
// DOVE
Dove = function (x, y) {
Slime.call(this, x, y);
this.type = "DOVE";
}
Dove.prototype = Object.create(Slime.prototype);
// DOVE
// FOOD
Food = function (x, y) {
this.x = x;
this.y = y;
}
Food.prototype.draw = function () {
ellipse(this.x, this.y, 10, 10);
}
Food.prototype.assignSlime = function (firstSlime = null, secondSlime = null) {
this.firstSlime = firstSlime;
this.secondSlime = secondSlime;
}
// FOOD
spawnFood = function(food) {
fill(229, 246, 88);
var factors = []
var differences = []
for (let i = 1; i < food; i++) {
var value = food/i;
if (value != Math.floor(value)) {
continue;
}
factors.push([value, i]);
differences.push(abs(value - i));
}
var currentMinIndex = 0;
for (let i = 0; i < differences.length; i++) {
if (differences[i] < differences[currentMinIndex]) {
currentMinIndex = i;
}
}
for (let x = 50; x < 350; x += 300/factors[currentMinIndex][0]) {
for (let y = 50; y < 350; y += 300/factors[currentMinIndex][1]) {
var myFood = new Food(x, y);
foodList.push(myFood);
myFood.draw();
}
}
}
initializeSlimes = function (slimes) {
var tempx = 0;
var tempy = 0;
fill(67, 163, 235);
for (let i = 25; i < 375; i+= 375/(slimes / 4)) {
let mySlime = new Slime(i, 12.5); mySlime.draw(); slimesList.push(mySlime);
}
for (let i = 25; i < 375; i+= 375/(slimes / 4)) {
let mySlime = new Slime(i, 387.5); mySlime.draw(); slimesList.push(mySlime);
}
for (let i = 25; i < 375; i+= 375/(slimes / 4)) {
let mySlime = new Slime(12.5, i); mySlime.draw(); slimesList.push(mySlime);
}
for (let i = 25; i < 375; i+= 375/(slimes / 4)) {
let mySlime = new Slime(387.5, i); mySlime.draw(); slimesList.push(mySlime);
}
}
However, when I try to run this in VSCode, chrome opens to try and run the file, but then the window switches back to VSCode, and it shows me:
My error code (I don't have enough rep to embed a picture yet)
If anybody knew how to fix this, I would be extremely grateful. Is this a problem in my code, or is this a problem with the p5 library?
Could you show where the error appears in your javascript file rather than in the p5.js library itself?
Otherwise, I don't even see a call to Array.forEach() in your code snippit, did you make sure to paste all of the code you're running? Or since your p5.js file isn't even being loaded in your index.html, are you trying to run the p5.js file itself? That won't work, make sure you're running your index.html file.
I tried running your index.html using a copy of p5.js in the source folder and copied all of your code into a sketch.js file, and I was able to run it through VSCode. Let me know if this helps at all or if you have any other information that could help with fixing your problem!

how to detect an element inside a canvas?

I am trying to detect the drawn elements inside the canvas (for example: every slice in the pie) to put a click event on them later, but it seems not to be an easy task, I think the math would be the best way to carry it out, but where should I start.
Please Help me to find a solution for this.
here is the demo:
outer link
code is:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#myCanvas{
width: 50%;
height: 50%;
}
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
class Piechart{
constructor(){
this.options = arguments[0];
this.canvas = arguments[0].canvas;
this.ctx = this.canvas.getContext('2d');
if(this.options.colors){
this.colors = arguments[0].colors;
}
else if (!this.options.colors){
this.colors = [
"#fde23e",
"#f16e23",
"#57d9ff",
"#937e88",
'#2fe678',
'#228888',
'#b111c1'
];
}
this.donut_hole = 0.5;
}
drawPie(){
var total_value = 0;
var color_index = 0;
for(var categ in this.options.data){
var val = this.options.data[categ];
total_value += val;
}
var start_angle = 0;
for(var categ in this.options.data){
var val = this.options.data[categ];
var slice_angle = 2*Math.PI*val/total_value;
this.drawPieSlice(
this.ctx,
this.canvas.width/2,
this.canvas.height/2,
Math.min(this.canvas.width/2,this.canvas.height/2),
start_angle,
start_angle+slice_angle,
this.colors[color_index%this.colors.length]
);
start_angle += slice_angle;
color_index++;
}
}
drawPieSlice(){
arguments[0].fillStyle = arguments[6];
arguments[0].beginPath();
arguments[0].moveTo(arguments[1],arguments[2]);
arguments[0].arc(
arguments[1],
arguments[2],
arguments[3],
arguments[4],
arguments[5]
);
arguments[0].closePath();
arguments[0].fill();
}
}
var myCanvas = document.getElementById("myCanvas");
var myCanvas_width = myCanvas.scrollWidth;
var myCanvas_height = myCanvas.scrollHeight;
myCanvas.width = myCanvas_width;
myCanvas.height = myCanvas_height;
var myVinyls = {
'Classical music':10,
'Rock':14,
'Pop':15,
'Jazz':4,
'test':6,
'test_1':7,
'test_2':8
};
var myPiechart = new Piechart(
{
canvas:myCanvas,
data:myVinyls,
colors:[
"#fde23e",
"#f16e23",
"#57d9ff",
"#937e88",
'#2fe678',
'#228888',
'#b111c1'
]
}
);
myPiechart.drawPie();
How to be able to detect each slice? Thank you.
EDIT
I have found an amazing solution for the purpose of adding hit region in the canvas and here is the link: Anton Lavrenov
First of all there are no elements on canvas you should understand this. It is a 2d plane where things are just drawn and if you want to move things around you need to redraw them entirely.
This said lets go back to the original problem.
Since you create the "object" in the canvas you know the size and distances of the object which you should keep in some js object for later use.
what i would do in this case to have an object that will hold the data of all other objects so when you click on the canvas you can get the click x and y and determine whether they are greater or equal to any of your objects' xs and ys
an example algorithm would be
if click.X>elem.X && click.X<elem.X+elem.Width
{
x is in check the same for y
}
if x__in&&y__in
{
you clicked the element
}

JS Game - cannot set property of undefined typeerror

I know there are similar questions as mine but they did not work for my case and I can not waste more time.
I am learning JS so I am trying to code an easy pacman game. In this case, every time pacman eats a powerup, all the active ghosts have to turn into weak ghosts.
The problems comes when while I am playing and I grab a powerup, the game crashes saying:
Uncaught TypeError: Cannot set property 'isWeak' of undefined.
I did not post all the code in this question. Only the main part where the error comes from(I think so).
My code in main.js:
var activeGhosts = [];
var powerups = [];
for (var i = 0; i < powerups.length; i++) {
if (pacman.collision(powerups[i])) {
makeWeak();
powerups.splice(i,1);
}
}
function makeWeak() {
for (var i = 0; i < activeGhosts.length; i++) activeGhosts[i].isWeak = true;
}
My code in ghost.js:
function Ghost(x,y,img){
this.x = x;
this.y = y;
this.img = img;
this.direction = 0;
this.radius = 16; // half of 32 px because every image is 32x32 px
this.crash = false;
this.isWeak = false;
this.show = function () {
if (this.isWeak) {
image(weakghostimg, this.x, this.y);
} else {
// img can be the all the different ghosts
image(img, this.x, this.y);
}
};

Javascript arrays giving NaN

I have a bit of HTML that is supposed to bounce ball(s) around the canvas, but the arrays storing the coordinates seem to be 'NaN' when I set them to a random position and test with alert("Co-ordinates " + (cirX[i]) + " x " + (cirY[i]));. This returns 'Co-ordinates NaN x NaN'. I have tried to do it with one ball without the arrays and it worked. I am not sure if I am coding my arrays badly or if it is something else. Here is my HTML:
<!Doctype HTML>
<head>
<script>
var cirX = [];
var cirY = [];
var chX = [];
var chY = [];
var width;
var height;
function initCircle(nBalls) {
alert(nBalls)
for(var i = 0; i<nBalls;i++) {
alert("loop " + i)
chX[i] = (Math.floor(Math.random()*200)/10);
chY[i] = (Math.floor(Math.random()*200)/10);
cirX[i] = Math.floor(Math.random()*width);
cirY[i] = Math.floor(Math.random()*height);
alert("Co-ordinates " + (cirX[i]) + " x " + (cirY[i]));
circle(cirX[i],cirY[i],3);
setInterval('moveBall(i)',10);
}
}
function moveBall(ballNum) {
if(cirX[ballNum] > width||cirX[ballNum] < 0) {
chX[ballNum] = 0-chX[ballNum];
}
if(cirY[ballNum] > height|| cirY[ballNum] < 0) {
chY[ballNum] = 0-chY[ballNum];
}
cirX[ballNum] = cirX[ballNum] + chX[ballNum];
cirY[ballNum] = cirY[ballNum] + chY[ballNum];
circle(cirX[ballNum],cirY[ballNum],3);
}
function circle(x,y,r) {
var c=document.getElementById("canvas");
var ctx=c.getContext("2d");
canvas.width = canvas.width;
ctx.fillStyle="#FF0000";
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI*2, true);
ctx.fill();
width = canvas.width;
height = canvas.height;
}
</script>
</head>
<body>
<canvas id="canvas" width="400" height="300">
</canvas>
<script>
initCircle(3); //this sets the number of circles
</script>
</body>
I have looked up how to initialise arrays e.c.t, but I seem to be doing it right? Thanks in advance for your help!
EDIT:
Despite fixing the above problems, only one ball moves and at varying speeds despite the variable ballNum in moveBall() varying from 0 to 2 as expected (tested by adding alert(ballNum)). Does anyone know why?
You call this line
cirX[i] = Math.floor(Math.random()*width);
when width is still undefined. So you can only get NaN as a result.
To properly call the moveBall function from setInterval, you may use
(function(i) { // embedds i to protect its value (so that it isn't the one of end of loop
setInterval(function(){moveBall(i)}, 10);
})(i);
It is because width is undefined when the statement gets executed for the first time. You can get the canvas and its dimension in the beginning and keep it global.
http://jsbin.com/agavoq/9/edit
To call setInterval you can use a self invoking function preserving the value of i
(function(x){
setInterval(moveBall,10, x);
})(i);
Or simply
setInterval(moveBall,10, i);
Or
setInterval('moveBall(' + i+ ')',10);
I see another issue because look at this line
setInterval('moveBall(i)',10);
The i is not what you think it is. You should not use a string in setTimeout.

Not Looping? HTML5 and JavaScript

I have no idea why this code does not loop as it should. My mind is blown and hopefully someone can give me a hand. This is my first attempt into the HTML5 and JavaScript world and my first StackOverflow post. My background is in java so that should explain the quirks in my code. By the way, if you run the code the canvas and balls will show up, just not move.
First off, here is the HTML5
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ChainReaction5</title>
<script type="text/javascript" src="chain_reaction.js"></script>
</head>
<body>
<body onLoad="init();">
<canvas id="myCanvas" width="500" height="400">
Your browser dosen't support the HTML5 canvas.</canvas><br />
</body>
</html>
Secondly here is the js
//gobal vars
var context;
var box;
var balls;
var defaultBallX=240;
var defaultBallY=190;
var defaultBallRad=6;
var defaultBallV=5;
var defaultNumBalls=10;
//box class
function Box() {
var boxx=20;
var boxy=20;
var boxWidth=460;
var boxHeight=360;
this.getX = function() {return boxx;}
this.getY = function() {return boxy;}
this.getWidth = function() {return boxWidth;}
this.getHeight = function() {return boxHeight;}
this.getBalls = function() {return ball;}
this.paintMe = function() {
context.fillStyle = "black";
context.strokeRect(boxx, boxy, boxWidth, boxHeight);
}
}
/* Box Class
* this class is sloppy but more memory efficent
*/
function Ball(x, y, radius, vx, vy, color) {
this.x=x;
this.y=y;
this.radius=radius;
this.vx=vx;
this.vy=vy;
this.color=color;
this.paintMe = function() {
context.beginPath();
context.arc(this.x, this.y, radius, 0, 2*Math.PI, true);
context.fillStyle = this.color;
context.fill();
}
}
Array.prototype.appendBalls = new function(array) {}
Array.prototype.clearBalls = new function() {}
Array.prototype.appendBalls = function(array) {
for (var i = 0; i < array.length; i++) {
balls.push(array[i]);
}
}
Array.prototype.clearBalls = function() {
balls = new Array();
}
// begin program
function init() {
context = document.getElementById("myCanvas").getContext("2d");
box = new Box();
balls = new Array();
balls.appendBalls(createBalls(box, defaultNumBalls));
setInterval(moveBall(balls, box), 100);
}
function createBalls(box, numBalls) {
var locBalls = new Array(numBalls);
for (var i = 0; i < numBalls; i++) {
var randx = randp(50, 400)
var randy = randp(50, 300);
var randr = Math.random()*defaultBallRad+1;
var randvx = randv();
var randvy = randv();
var randc = randColor();
locBalls[i] = new Ball(randx, randy, randr, randvx, randvy, randc);
}
return locBalls;
function randv() {
var neg = 1;
if (Math.random()>.5) neg = -neg;
return Math.random()*defaultBallV*neg;
}
function randp(low, hight) {
if (low < 0) low = 0;
var p = -1;
while (p > hight || p < low) {
p = Math.random()*hight;
}
return p;
}
function randColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
}
function moveBall(balls, box) {
clear(this.box);
this.box.paintMe();
for (var i = 0; i < this.balls.length; i++) {
moveAndCheck(this.balls[i], this.box);
}
}
function moveAndCheck(b, box) {
if ((b.x+b.vx+b.radius-1)>(this.box.boxWidth+this.box.boxx) || b.x+b.vx-b.radius<this.box.boxx+1) {
b.vx = -b.vx;
}
if ((b.y+b.vy+b.radius-1)>(this.box.boxHeight+this.box.boxy) || b.y+b.vy-b.radius<this.box.boxy+1) {
b.vy = -b.vy;
}
b.x += b.vx;
b.y += b.vy;
b.paintMe();
}
function clear(box) {
context.clearRect(this.box.boxx, this.box.boxy,
this.box.boxWidth, this.box.boxHeight);
}
The first time I tried running it I got the following in the Firebug console:
useless setInterval call (missing quotes around argument?)
[Break On This Error] setInterval(moveBall(balls, box), 100);
Putting quotes around 'moveBalls(balls, box)' animates things.
Incidentally, you can use prototype inhertiance to make your function a bit more efficient, the methods in Box are given to each instance. To have them inherit the methods, put them on the constructor's prototype:
Box.prototype = {
getX: function() {return this.boxx;},
getY: function() {return this.boxy;},
getWidth: function() {return this.boxWidth;},
getHeight: function() {return this.boxHeight;},
getBalls: function() {return this.ball;},
paintMe: function() {
context.fillStyle = "black";
context.strokeRect(this.boxx, this.boxy, this.boxWidth, this.boxHeight);
}
};
Note that in javascript, a function's this keyword is set by the call, it is not set by how you declare the function (though you can use ES5 bind, but that is not widely supported yet).
Some other hints:
In the Box constructor you are making local variables but you really want to assign them to the new Box instance, so use this instead of var:
function Box() {
this.boxx=20;
this.boxy=20;
this.boxWidth=460;
this.boxHeight=360;
}
In the clearBox function, you are using this when it is not set in the call, so it references window. Just get rid of it, you pass box to the function so reference it directly:
function clear(box) {
context.clearRect(box.boxx, box.boxy,
box.boxWidth, box.boxHeight);
}
Same applies to the moveBall and moveAndCheck functions, just get rid of this (I think you should do some research on how this is handled in javascript, there are many articles on it, it's quite different to Java).
Now the balls will bounce around nicely inside the box.
I want to thank the people who contributed to my question and it has been helpful in resolving the issue and the answer I selected was current in a way, but it fixed the problem for a different reason.
Incorrect:
Putting quotes around 'moveBalls(balls, box)' animates things.
What actually fixes the problem is removing the arguments and parentheses from the call to the moveball function. I discovered this when rewriting other parts of my code as the poster suggested.
So for future notice to other people with a similar problem if you need to remove the arguments and use a wrapper function or global variables.

Categories

Resources