Ok so I'm attempting to have a webpage with two buttons. Each of these buttons, when clicked, creates a new canvas and calls a different draw function. The first draw function would draw large circles where the users mouse is and small ones when the mouse is pressed. The other draw function does the same thing except small circles when the mouse is unpressed and large ones when it is. I'm not having a problem referencing one of these with the button but the other button doesn't seem to call its draw function. sketch2.js seems to be working fine but it seems that the draw function in sketch.js is not being called. Any advice on how I should go about fixing this is greatly appreciated!
Below is my HTML code:
<html>
<head>
<meta charset="UTF-8">
<button id="myBtn">little then big</button>
<div id="holder"></div>
<button id="myBtn2">big then little</button>
<div id="holder2"></div>
<style> body {padding: 0; margin:0;} </style>
</head>
<body>
<script type="text/javascript" src = "/Users/bburke95/Desktop/JS/p5.dom.js"> </script>
<script language="javascript" type="text/javascript" src="../p5.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<script language="javascript" type="text/javascript" src="sketch2.js"></script>
</body>
</html>
This is my sketch.js class
btn = document.getElementById("myBtn");
var q;
btn.onclick = function setup() {
createCanvas(640, 480);
document.getElementById("holder").innerHTML = '<canvas id="myCanvas" width="490" height="220"></canvas>';
q = 1;
set = 0;
}
function draw() {
if (q == 1) {
var x;
var y;
if (mouseIsPressed) {
fill(255);
x = 160;
y = 160;
} else {
fill(0);
x = 80;
y = 80;
}
ellipse(mouseX, mouseY, x, y);
}
}
and this is my sketch2.js class
btn2 = document.getElementById("myBtn2");
var set;
btn2.onclick = function setup() {
createCanvas(640, 480);
document.getElementById("holder2").innerHTML = '<canvas id="myCanvas2" width="490" height="220"></canvas>';
set = 1;
q = 0;
}
function draw() {
if (set == 1) {
var x;
var y;
if (mouseIsPressed) {
fill(0);
x = 80;
y = 80;
} else {
fill(255);
x = 160;
y = 160;
}
ellipse(mouseX, mouseY, x, y);
}
}
If you want to run more than one P5.js processing sketches on the same page, you have to use "instance mode" to ensure that all the functions aren't cluttering the global namespace (which is a good idea anyway) so they don't overwrite one another.
From their Github project, you can instantiate new sketches like this:
var s = function( p ) {
var x = 100;
var y = 100;
p.setup = function() {
p.createCanvas(700, 410);
};
p.draw = function() {
p.background(0);
p.fill(255);
p.rect(x,y,50,50);
};
};
var myp5 = new p5(s);
Related
Once I upload an image I make 2 clicks over it. That's how (x1,y1) and (x2,y2) are obtained. Given these 4 numbers I waanna draw a rectangle over the image by means for example of P5.js. Then I should say rect(x1,y1,x2,y2) but this never happens. How can I deal with this problem (maybe not by P5)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
</head>
<body>
<div id="app">
<button v-on:click="isHidden = false">Load img</button>
<img onclick="showCoords(event)" v-if="!isHidden" v-bind:src="src[z]"></img>
</div>
<script>
var test = new Vue({
el: '#app',
data: {
src: ["cat.jpg", "dog.jpg"],
z: Math.round(Math.random()),
isHidden: true,
}
})
var k=0;
var koors = [];
var flag = false;
function showCoords(event) {
if (k===0){
koors[0] = event.clientX;
koors[1] = event.clientY;
k+=1;
} else if (k===1){
flag = true;
koors[2] = event.clientX;
koors[3] = event.clientY;
}
if ((koors[3] != 0) && (flag)){
console.log(koors)
}
}
//p5
function setup(){
}
function draw(){
console.log(koors[0],koors[1],koors[2],koors[3]);
rect(koors[0],koors[1],koors[2],koors[3])
}
</script>
<script src="p5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<script src="js.js"></script>
</body>
</html>
P5 needs a canvas for rendering. If you don't initialize one, it creates it himself (and you are in trouble).
Also, P5 is powerful library, it has tools for events, image processing etc. For current example I wouldn't use any other library (vue).
I created canvas on top of the image (css) and rest is playing with P5.
var test = new Vue({
el: '#app',
data: {
src: [ "https://i.stack.imgur.com/XZ4V5.jpg", "https://i.stack.imgur.com/7bI1Y.jpg"],
z: Math.round(Math.random()),
isHidden: false,
}
})
var recStart;
var coords = {};
/*******************************************************************
* P5 setup
* run once, use for initialisation.
*
* Create a canvas, change dimensions to
* something meaningful(like image dim)
********************************************************************/
function setup(){
var canvas = createCanvas(480, 320);
canvas.parent('app');
}
/*******************************************************************
* P5 draw
* endless loop.
*
* Lets redraw rectangle until second click.
********************************************************************/
function draw(){
if(recStart)
drawRect();
}
/*******************************************************************
* drawRect
*
* Draw a rectangle. mouseX and mouseY are P5 variables
* holding mouse current position.
********************************************************************/
function drawRect(){
clear();
noFill();
stroke('red');
rect(coords.x, coords.y, mouseX-coords.x, mouseY-coords.y);
}
/*******************************************************************
* P5 mouseClicked
*
* P5 event. Again, mouseX and mouseY are used.
********************************************************************/
mouseClicked = function() {
if (mouseButton === LEFT) {
if(!recStart){ // start rectangle, give initial coords
coords.x = mouseX;
coords.y = mouseY;
recStart = true; // draw() starts to draw
} else {
recStart = false; // stop draw()
drawRect(); // draw final rectangle
coords = {}; // clear coords
}
}
};
canvas {
width: 500px;
height:500px;
z-index: 2;
border:1px solid;
position:absolute;
left: 0;
top: 0;
}
img {
z-index: 1;
position: absolute;
border: 2px solid black;
left: 0;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<img id="pilt" v-if="!isHidden" v-bind:src="src[z]"></img>
</div>
It seems that you don't call draw anywhere. You may also consider draw the image into a canvas and than draw rect in this canvas. Checking if koors[3] != 0 is really risky as user may click at 0th pixel.
I am making a javascript game, using Canvas. However, I got that error(below image) and background image is not shown. I suspect below 4 files, because other files didn't make any trouble. I guess the problem is related with game_state...how can I solve the problem??
I am agonizing for 2days:( plz, help me..
error image1
error image2
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>Lion Travel</title>
<!--GameFramework-->
<script src="/.c9/gfw/GameFramework.js"></script>
<script src="/.c9/gfw/FrameCounter.js"></script>
<script src="/.c9/gfw/InputSystem.js"></script>
<script src="/.c9/gfw/SoundManager.js"></script>
<script src="/.c9/gfw/GraphicObject.js"></script>
<script src="/.c9/gfw/SpriteAnimation.js"></script>
<script src="/.c9/gfw/ResourcePreLoader.js"></script>
<script src="/.c9/gfw/DebugSystem.js"></script>
<script src="/.c9/gfw/Timer.js"></script>
<script src="/.c9/gfw/FrameSkipper.js"></script>
<script src="/.c9/gfw/TransitionState.js"></script>
<!--GameInit-->
<script src="/.c9/gfw/gfw.js"></script>
<!--Game Logic-->
<script src="/.c9/RS_Title.js"></script>
</head>
<body>
<canvas id="GameCanvas" width="800" height="600">html5 canvas is not supported.</canvas>
</body>
</html>
gfw.js
function onGameInit() {
document.title = "Lion Travel";
GAME_FPS = 30;
debugSystem.debugMode = true;
resourcePreLoader.AddImage("/.c9/title_background.png");
soundSystem.AddSound("/.c9/background.mp3", 1);
after_loading_state = new TitleState();
setInterval(gameLoop, 1000 / GAME_FPS);
}
window.addEventListener("load", onGameInit, false);
RS_Title.js
function TitleState()
{
this.imgBackground = resourcePreLoader.GetImage("/.c9/title_background.png");
soundSystem.PlayBackgroundMusic("/.c9/background.mp3");
return this;
}
TitleState.prototype.Init = function()
{
soundSystem.PlayBackgroundMusic("/.c9/background.mp3");
};
TitleState.prototype.Render = function()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
//drawing backgroundimage
Context.drawImage(this.imgBackground, 0, 0);
};
TitleState.prototype.Update = function()
{
};
GameFramework.js
var GAME_FPS;
var game_state = after_loading_state;
function ChangeGameState(nextGameState)
{
//checking essential function
if(nextGameState.Init == undefined)
return;
if(nextGameState.Update == undefined)
return;
if(nextGameState.Render == undefined)
return;
game_state = nextGameState;
game_state.Init();
}
function Update()
{
timerSystem.Update();
game_state.Update();
debugSystem.UseDebugMode();
}
function Render()
{
//drawing
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
Context.fillStyle = "#000000";
Context.fillRect(0, 0, 800, 600);
//game state
game_state.Render();
if(debugSystem.debugMode)
{
//showing fps
Context.fillStyle = "#ffffff";
Context.font = '15px Arial';
Context.textBaseline = "top";
Context.fillText("fps: "+ frameCounter.Lastfps, 10, 10);
}
}
function gameLoop()
{
Update();
Render();
frameCounter.countFrame();
}
The issue here is that you are initializing game_state with the object after_loading_state even before after_loading_state is initialized(which is initialized only after the document is loaded). Due to this game_state remains undefined.
To fix this, change var game_state = after_loading_state; in GameFramework.js to var game_state;. And add game_state = after_loading_state; as the first line in gameLoop function. This way, the initialization of variables occur in the correct order.
Lately I learned a bit about strange attractors, and I created the following programm in JS:
var ctx, clock, width, height, pixSize;
var x,y,a,b,c,d;
window.onload = function(){
start();
};
function start(random=true){
window.cancelAnimationFrame(clock);
if(random){
a = 6*Math.random()-3;
b = 6*Math.random()-3;
c = 2*Math.random()-0.5;
d = 2*Math.random()-0.5;
}
canvasSetup();
clearCanvas();
x = Math.random()-Math.random();
y = Math.random()-Math.random();
clock = requestAnimationFrame(main);
}
function save(){
var text = JSON.stringify({
a:a,
b:b,
c:c,
d:d
});
window.prompt("Copy to clipboard: Ctrl+C", text);
}
function load(){
var input = JSON.parse(window.prompt("Import Save:"));
a = input.a;
b = input.b;
c = input.c;
d = input.d;
start(false);
}
function canvasSetup(){
canvas = document.getElementById('canvas');
width = window.innerWidth-5;
height = window.innerHeight-5;
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
var min = Math.min(width,height);
var scale = min/4;
ctx.translate(width/2, height/2);
ctx.scale(scale, scale);
pixSize = 1/scale/2;
ctx.globalCompositeOperation = "lighter";
}
function clearCanvas(){
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0,0,width,height);
ctx.restore();
}
function main(){
for(var i=0;i<10000;i++){
var xnew = Math.sin(y*b)+c*Math.sin(x*b);
var ynew = Math.sin(x*a)+d*Math.sin(y*a);
x = xnew;
y = ynew;
plot(x,y,"rgb(50,5,1)");
}
clock = requestAnimationFrame(main);
}
function plot(x,y,color="white"){
ctx.fillStyle = color;
ctx.fillRect(x,-y,pixSize,pixSize);
}
body {
background-color: black;
color: white;
font-family: Consolas;
font-size: 13px;
margin: 0;
padding: 0;
}
#buttons{
position: absolute;
top: 0;
left: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Strange Attractor</title>
<link rel="stylesheet" href="style.css">
<script src="rules.js"></script>
<script src="script.js"></script>
</head>
<body>
<div align="center">
<canvas id="canvas"></canvas>
</div>
<div id="buttons">
<button onclick="start()">New Attractor</button><br>
<button onclick="save()">Save</button><br>
<button onclick="load()">Load</button>
</div>
</body>
</html>
It's taking 4 random Parameters (a,b,c,d) and uses the formular
var xnew = Math.sin(y*b)+c*Math.sin(x*b);
var ynew = Math.sin(x*a)+d*Math.sin(y*a);
x = xnew;
y = ynew;
for the new point. In some cases this indeed creates a fancy strange sttractor:
But in other cases I only get a single line or a few points. Is there a simple way to look at the parameters and find out, if the attrator they create will be strange?
I know, that I could save a bunch of values, compare them with each other and test in that way, if the picture might be intresting, but I'd love a different solution...
I hope you can help :)
EDIT:
To look at speccific values you can simply use the save and load buttons in the js sketch above...
I have a canvas element. I have a few troubles, how to draw to user canvas in "realtime",.. So, that my drawing is not already there when they open the site, but rather to draw to the canvas like somebody is actually drawing... So looping through the coordinates.
That's what I tried so far but it's BAAD! It's drawing slowly and it takes a lot of CPU.
// Pencil Points
var ppts = [];
/* Drawing on Paint App */
tmp_ctx.lineWidth = 4;
tmp_ctx.lineJoin = 'round';
tmp_ctx.lineCap = 'round';
tmp_ctx.strokeStyle = '#4684F6';
tmp_ctx.fillStyle = '#4684F6';
// Tmp canvas is always cleared up before drawing.
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
tmp_ctx.beginPath();
var timer = 0;
$.timer(500, function() {
ppts.push({x: 10*timer, y: 5*timer});
timer++;
})
$.timer(10, function() {
if (timer > 250) {
timer = 0;
clearTempCanvas();
} else {
for (var i = 1; i < ppts.length - 2; i++) {
var c = (ppts[i].x + ppts[i + 1].x) / 2;
var d = (ppts[i].y + ppts[i + 1].y) / 2;
tmp_ctx.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d);
}
console.log(i);
tmp_ctx.stroke();
}
})
function clearTempCanvas() {
// Writing down to real canvas now
ctx.drawImage(tmp_canvas, 0, 0);
// Clearing tmp canvas
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
// Emptying up Pencil Points
ppts = [];
}
Here's an example for you to learn from: http://jsfiddle.net/m1erickson/j4HWS/
It works like this:
define some points to animate along and put those points in an array points.push({x:25,y:50})
use requestAnimationFrame to create an animation loop
break each line segment into 100 sub-segments and animate along those sub-segments
Example code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.lineWidth=2;
ctx.strokeStyle="blue";
var points=[];
points.push({x:125,y:125});
points.push({x:250,y:200});
points.push({x:125,y:200});
points.push({x:125,y:125});
var pointIndex=1;
var linePct=0;
var continueAnimating=true;
var img=new Image();img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/pen.png";
function start(){
animate();
}
function draw(pointIndex,linePct){
// clear the canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
// draw fully completed lines
ctx.beginPath();
ctx.moveTo(points[0].x,points[0].y);
for(var i=1;i<pointIndex;i++){
ctx.lineTo(points[i].x,points[i].y);
}
// draw current line-in-process
var pos=getLineXYatPercent(points[pointIndex-1],points[pointIndex],linePct/100);
ctx.lineTo(pos.x,pos.y);
ctx.stroke();
// draw the pen
ctx.drawImage(img,pos.x-93,pos.y-92);
}
function animate() {
if(!continueAnimating){return;}
requestAnimationFrame(animate);
// Drawing code goes here
draw(pointIndex,linePct);
if(++linePct>100){
linePct=1;
if(++pointIndex>points.length-1){
continueAnimating=false;
}
}
}
function getLineXYatPercent(startPt,endPt,percent) {
var dx = endPt.x-startPt.x;
var dy = endPt.y-startPt.y;
var X = startPt.x + dx*percent;
var Y = startPt.y + dy*percent;
return( {x:X,y:Y} );
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=350 height=350></canvas>
</body>
</html>
I've been trying to create a game with falling blocks that will stack on top of each other. The blocks will fall into one of 6 columns and need to stop falling down the screen when they collide with the top block on that column. I've been trying to get the y-coordinate of the top block, but that causes a problem because its still getting the newest created block and not the last finished block. Any help would be greatly appreciated!
var FPS = 60;
setInterval(function() {
//update();
draw();
}, 1000/FPS);
var y = 30;
//draw the screen
function draw() {
if(+new Date() > lastTime + minWait){
var column = Math.floor(Math.random()*6)
lastTime = +new Date();
blocks.push(new Block(5 + column*40, 30,40,40, 5, "red","black"));
}
context.clearRect(0,0,canvas.width, canvas.height);
blocks.forEach(function(e){
e.update();
e.render();
});
};
var blocks = [];
var lastTime = +new Date();
var minWait = 1000;
var topBlock = 310;
function columnTop(column){
for(var i=0; i < blocks.length; i++){
if(blocks[i].x === (5 + 40*columnTop)){
if(blocks[i].y < topBlock){
topBlock = blocks[i].y
}
}
}
}
//block functions
Block.prototype.update = function(){
var topCol1 = columnTop(1);
var topCol2 = columnTop(2);
var topCol3 = columnTop(3);
var topCol4 = columnTop(4);
var topCol5 = columnTop(5);
var topCol6 = columnTop(6);
if(this.y < 310){
this.y+= this.dy
}else{
this.dy = 0;
}
};
Block.prototype.render = function(){
Block(this.x, this.y, this.w, this.h, this.r, this.fillstyle, this.strokestyle);
};
Maintain a maximum-Y value for each column.
maximum-Y is the y-position of the last stacked block.
Whenever a block exceeds the maximum-Y, force that block to sit atop the maximum-Y.
Then reduce maximum-Y by that blocks height.
if( block.y + block.height > maxY ){
block.y = maxY - block.height;
maxY = block.y;
}
Here's code and a Demo: http://jsfiddle.net/m1erickson/FMv2q/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
function Blocks(floor,colCount){
this.blocks=[];
this.floor=floor;
this.cols=[];
this.continueRAF=true;
for(var i=0;i<colCount;i++){
this.cols.push({maxY:floor,needsNewBlock:true});
}
}
function animate(){
if(blocks.continueRAF){ requestAnimationFrame(animate); }
for(var i=0;i<blocks.cols.length;i++){
if(blocks.cols[i].needsNewBlock){
blocks.cols[i].needsNewBlock=false;
blocks.blocks.push(new Block(i));
}
}
ctx.clearRect(0,0,canvas.width,canvas.height);
var fallingCount=0;
for(var i=0;i<blocks.blocks.length;i++){
var block=blocks.blocks[i];
fallingCount+=block.fall();
ctx.fillStyle=block.fill;
ctx.fillRect(block.x,block.y,block.w,block.h);
}
if(fallingCount==0 && blocks.continueRAF){
blocks.continueRAF=false;
alert("All done after "+blocks.blocks.length+" blocks fell.");
}
}
function Block(column){
this.column=column;
this.x=this.column*50;
this.w=parseInt(Math.random()*20+15);
this.h=parseInt(Math.random()*15+5);
this.y=-this.h;
this.vy=parseInt(Math.random()*3+4);
this.fill=randomColor();;
this.isFalling=true;
}
Block.prototype.fall=function(){
if(!this.isFalling){return(0);}
var col=blocks.cols[this.column];
if(this.y+this.h+this.vy>col.maxY){
this.isFalling=false;
this.y=col.maxY-this.h;
col.maxY=this.y;
if(col.maxY>35){
col.needsNewBlock=true;
}
}else{
this.y+=this.vy;
}
return(1);
}
var blocks=new Blocks(350,6);
animate();
function randomColor(){
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=350 height=350></canvas>
</body>
</html>