New to coding, and I decided to create an interactive, onclick adventure game using 6 images I pulled from online.
I added the the first image to canvas and put a cool little animation in front of the image on canvas, but now I'm left with a big problem.
This whole game is done on ONE canvas, with MULTIPLE, as well as BRANCHING on click events.
Example: On the title screen, the user can either select "Start Game", or "Credits" (done as clickable text).
If the user selects "Start Game", the screen transitions to picture number 2, after clicking again, picture number 2 blurs out and narration text will appear in front of the user. However, if they select "Credits", the screen transitions instead to a different picture, picture number 3. On picture number 3, the credits display in an slow automatic scrolling up fashion.
I've looked this up online, but I usually get answers in a general ballpark of what I'm looking for, some results I've found are switch cases(not much experience with them, let alone make a BRANCHING switch case), the Undum framework for interactive story telling, event handlers, etc.
I haven't worked much with Javascript or with canvas, and before I tackled this project, I thought it best to present my project question outright and get a experienced opinion on it, as well as break the project down piece by piece and form some kind of method of attack.
Knowing how this project is going to work, what resources or coding methods would you guys recommend for me to use? What would this "branching" animation tree even look like?
Here is what my code is so far:
-- HTML --
<html>
<head>
<title>Detective</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
<!-- load in the jquery -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.js">
</script>
</head>
<body>
</body>
</html>
-- CSS --
body{
background:#000;
width: 100%;
height: 100%;
overflow:hidden;
}
canvas{
/*the code below this activates the canvas border, turn it on to visibly see how big the canvas is */
/* border: 1px solid red;*/
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
margin:auto;
display: none;
}
#font-face{
font-family: 'Betty Noir Regular';
src: url('/assets/bettynoir.ttf');
}
-- JS --
var canvas = document.createElement('canvas');
var w = canvas.width = 800,
h = canvas.height = 400;
var c = canvas.getContext('2d');
var img = new Image();
img.src = 'http://oi41.tinypic.com/4i2aso.jpg';
var background = new Image();
background.src = "https://i2.wp.com/i2.listal.com/image/2669447/500full.jpg";
var position = {x : 410, y : 238};
document.body.appendChild(canvas);
var particles = [];
var random = function(min, max){
return Math.random()*(max-min)*min;
};
function Particle(x, y){
this.x = x;
this.y = y;
this.velY = -2;
this.velX = (random(1, 10)-5)/10;
this.size = random(3, 5)/10;
this.alpha = 1;
this.update = function(){
this.y += this.velY;
this.x += this.velX;
this.velY *= 0.99;
if(this.alpha < 0){this.alpha = 0;}
c.globalAlpha = this.alpha;
c.save();
c.translate(this.x, this.y);
c.scale(this.size, this.size);
c.drawImage(img, -img.width/2, -img.height/2);
c.restore();
this.alpha *= 0.96;
this.size += 0.02;//
};
}
var draw = function(){
var p = new Particle(position.x, position.y);
particles.push(p);
// draw the background image before you draw the particles
c.drawImage(background,160,0);
c.font="20px Betty Noir Regular";
c.fillStyle = "white";
c.fillText("Start",500,200);
c.font="20px Betty Noir Regular";
c.fillStyle = "white";
c.fillText("Credits",500,250);
while(particles.length > 500) particles.shift();
for(var i = 0; i < particles.length; i++)
{
particles[i].update();
}
};
setInterval(draw, 3500/60);
$(document).ready(function() {
$("canvas").fadeIn(7000);
});
$(document).ready(function() {
$("#noir-song").get(0).play();
});
Looks good.
I would say get rid of setInterval as it will only cause you problems in the long run. As you have a particle system, some devices may not handle the load that well and as setInterval does not check to see if the last render job is done befor it puts a call on the call stack you could end up overflowing the call stack and crashing the app.
Use window.requestAnimationFrame(functionName)
As follows
// your main render function
function draw(){
// do your stuff
requestAnimationFrame(draw); // needs to be call for every new frame
}
draw(); // start it all happening.
requestAnimationFrame is sensitive to rendering load, will try its best to maintain an even frame rate 1/60th or 60fps. Syncs with monitor refresh rates if possible so you don't get shearing. It is designed for animations (hence the name) so give it a try.
I would ask "why use jquery?" you will be using browsers that support canvas and jquery offers no real benefit but that of legacy browser support, and only adds to the complexity of the pages and increases the load time. You only use it for page ready, so seems a bit of a waste. Remove jQuery and use onload to replace the ready calls
window.addEventListener("load",function(){
// your startup up code
});
A better way of creating particles. Using new is slow especially when you are creating many instances of the same thing.
Try
// define the function to update once. In the new Particle() version
// javascript actually has to create this function every time you create a particle.
// This makes it quicker.
var particleUpdate = function(){
this.y += this.velY;
this.x += this.velX;
this.velY *= 0.99;
// a quicker way to clamp a value
// if(this.alpha < 0){this.alpha = 0;} // done in the following line
c.globalAlpha = Math.max(0,this.alpha); // returns the max value so while
// alpha > 0 it returns alpha
// when alpha < 0 returns max
// which is 0;
//c.save(); // dont need this here do it outside the loop that renders
// the particles. Save and restore are expensive in terms
// of GPU performance and should be avoided if possible.
// the translate and scale can be done in one call halving the time
// to do the same thing
//c.translate(this.x, this.y);
//c.scale(this.size, this.size);
// use setTransform does the same as translate and scale but in one step
c.setTransform(this.size,0,0,this.size,this.x,this.y)
c.drawImage(img, -img.width/2, -img.height/2);
// c.restore(); see above
this.alpha *= 0.96;
this.size += 0.02;//
};
var createParticle = function(x,y){
return {
x:x,
y:y,
velY:-2,
velX:(random(1, 10)-5)/10,
size:random(3, 5)/10,
alpha = 1,
update:particleUpdate,
}
}
Then to create
particles.push(createParticle(position.x, position.y));
Update and cull as you are already doing just add the save and restore outside the loop. Also getting "particles.length" is slower than a direct variable. So rewrite the loop as follows
var len = particles.length
c.save()
for(var i = 0; i < len; i++){
particles[i].update();
}
c.restore();
It will not make much difference in this case as there is not that much going on. But as you push for more and more fx, more bang per frame performance will become a major problem. Learning efficient methods early on will help.
Related
For example I have a limited canvas, smaller width/height than the uploaded image in it.
Guys how to make the effect of moving the image in the canvas window? In other words, the canvas window does not change, and the picture we "run". thanks
Animation basic movement
Like all animation to make something appear as if it moves is to draw a sequence of still images (a frame), each image slightly different. If the rate of frames are high enough (over about 20 per second) the human eye and mind see the sequence of still images as a continuous movement. From the first movies to today's high end games this is how animation is done.
So for the canvas the process of drawing a frame is simple. Create a function that clears the canvas, draws what you need, exit the function so that the browser can move the completed frame to the display. (Note that while in the function anything draw on the canvas is not seen on the display, you must exit the function to see what is drawn)
To animate you must do the above at at least more than 20 times a seconds. For the best results you should do it at the same rate as the display hardware shows frames. For the browser that is always 60 frames per second (fps).
Animation in the browser
To help sync with the display you use the function requestAnimationFrame(myDrawFunction) it tells the browser that you are animating, and that the results of the rendering should be displayed only when the display hardware is ready to show a new complete frame, not when the draw function has exited (which may be halfway through a hardware frame).
Animation Object
So as a simple example let's create a animation object.
const imageSrc = "https://i.stack.imgur.com/C7qq2.png?s=328&g=1";
const myImage = {
posX: 0, // current position of object
posY: 0,
speed: 3, // speed in pixels per frame (1/60th second)
direction: 0, // direction of movement in radians 0 is at 3oclock
image: (() => { // create and load an image (Image will take time to load
// and may not be ready until after the code has run.
const image = new Image;
image.src = imageSrc;
})(),
Draw function
Then a draw function that draws the object on the canvas
draw(ctx) {
ctx.drawImage(this.image, this.posX, this.posY);
},
Update function
As we are animating we need to move the object once per frame, to do this we create a update function.
update() {
this.posX += (mx = Math.cos(this.direction)) * this.speed;
this.posY += (my = Math.sin(this.direction)) * this.speed;
}
} // end of object
Many times a second
To do the animation we create a main loop that is call for every hardware display frame via requestAnimationFrame.
function mainLoop() {
// clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// update the obj
myImage.update();
// draw the object
myImage.draw(ctx);
// request the next frame
requestAnimationFrame(mainLoop);
// note all of the above code is not seen by the use until the
// next hardwares display frame. If you used setTimeout or setInterval
// then it would be displayed when this function exits (which may be
// halfway through a frame resulting in the animation being cut in two)
}
// request the first frame
requestAnimationFrame(mainLoop);
Some extras
And that is the most basic animation. of course you need to get the canvas context and wait for the image to load. Also because the image moves of the canvas you would need to check when it does and either stop the animation.
Eg to stop animation is image is off screen
if(myImage.posX < canvas.width){ // only render while image is on the canvas
requestAnimationFrame(mainLoop);
} else {
console.log("Animation has ended");
}
Now to put it together as a demo.
The demo
The demo has some extra smarts to make the image wrap around, ensure that the image has loaded before starting and make it start off screen, but is basicly the same as outlined above.
// get the 2D context from the canvas id
const ctx = canvas.getContext("2d");
// setup the font and text rendering
ctx.font = "32px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// create the image object and load the image
const imageSrc = "https://i.stack.imgur.com/C7qq2.png?s=328&g=1";
const myImage = {
posX: 0, // current position of object
posY: 0,
speed: 3, // speed in pixels per frame (1/60th second)
direction: 0, // direction of movement in radians 0 is at 3oclock
image: (() => { // create and load an image (Image will take time to load
// and may not be ready until after the code has run.
const image = new Image;
image.src = imageSrc;
// to start move the image of the display
image.onload = function(){
const imageDiagonalSize = Math.sqrt(
image.width * image.width + image.height * image.height
)
myImage.posX = (canvas.width / 2) - imageDiagonalSize - Math.cos(myImage.direction) * imageDiagonalSize;
myImage.posX = (canvas.height / 2) - imageDiagonalSize - Math.sin(myImage.direction) * imageDiagonalSize;
}
return image;
})(),
draw(ctx) {
ctx.drawImage(this.image, this.posX, this.posY);
},
update() {
var mx,my; // get movement x and y
this.posX += (mx = Math.cos(this.direction)) * this.speed;
this.posY += (my = Math.sin(this.direction)) * this.speed;
// if the image moves of the screen move it to the other side
if(mx > 0) { // if moving right
if(this.posX > canvas.width){
this.posX = 0-this.image.width;
}
}else if(mx < 0) { // if moving left
if(this.posX + this.image.width < 0){
this.posX = canvas.width;
}
}
if(my > 0) { // if moving down
if(this.posY > canvas.height){
this.posY = 0-this.image.height;
}
}else if(my < 0) { // if moving up
if(this.posY + this.image.height < 0){
this.posY = canvas.height;
}
}
}
}
function mainLoop() {
// clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(myImage.image.complete) { // wait for image to load
myImage.update();
myImage.draw(ctx);
}else{ // some feedback to say the image is loading
ctx.fillText("Loading image..",canvas.width / 2, canvas.height / 2);
}
// request the next frame
requestAnimationFrame(mainLoop);
}
// request the first frame
requestAnimationFrame(mainLoop);
canvas {
border: 2px solid black;
}
<!-- id's must be unique to the page -->
<canvas id="canvas"></canvas>
Please note that the above code uses ES6 and will need a code pre processor like Babel to run on legacy browsers.
Check out this answer: https://stackoverflow.com/a/30739547/3200577
Basically, the way that html canvas works is very different from how html elements are rendered and painted. Whereas you can select and move an html element on the page, you cannot select and move something that you have added to a canvas because all you can do on a canvas is add and clear pixels. So, when you add an image to a canvas, you are adding the pixels of the image to the canvas. If you were to add the image again but a little to the left, then it would look like you've added two images, where the second one overlaps the first, which is not what you want.
So, to animate the motion of an image on the canvas, you need to:
choose an x and y as the position of the image on the canvas
draw the image on the canvas at x and y
increment the values of x and y to the new position that you want
clear the canvas
redraw the image at the new x and y
A more abstract description of this flow: basically, you need to create, store, and manage your own model of what your canvas looks like; when you want to add, remove of change things that you've painted on the canvas, you actually aren't going to be adding, removing, or changing anything directly on the canvas. You would add, remove and change things in your own model, clear the canvas, and then redraw the canvas on the basis of your model.
For instance, your model might be a JS object such as
myModel = {
images: [
{ url: "my/picture.png", position: [123,556] },
{ url: "another/picture.jpg", position: [95,111] }
]
}
and you would write functions for 1) incrementing the values of the positions of the images in the model, 2) clearing the canvas, and 3) drawing your model onto the canvas. Then, you would create a loop (using requestAnimationFrame or setInterval) that would repeatedly execute those three functions.
For large or complex projects, I strongly recommend using a canvas library such as paperjs, which implements that flow for you (so that you don't have to think about creating a model and clearing and redrawing the canvas). It provides high-level functionality such as animation right out of the box.
I have been practicing using sprites for a game I am going to make and have watched and read a few tutorials, I thought I was close to getting my sprite to appear so I could finally start my game but while practicing I cant get it to work, I have dont 2 seperate tutorials where I can get the sprite and the background to appear by themselfs but cannot get them to work together, I have been using EaselJS too. some of the sprite animation code has been copied from tutorials too.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>sprite prac<title>
<!-- EaselJS library -->
<script src="lib/easel.js"></script>
<script>
// Initialize on start up so game runs smoothly
function init() {
canvas = document.getElementById("canvas");
stage = new Stage(canvas);
bg = new Image();
bg.src = "img/grassbg.jpg";
bg.onload = setBG;
stage.addChild(background);
imgMonsterARun = new Image();
imgMonsterARun.onload = handleImageLoad;
imgMonsterARun.onerror = handleImageError;
imgMonsterARun.src = "img/MonsterARun.png";
stage.update();
}
function handleImageLoad(e) {
startGame();
}
// Simple function for setting up the background
function setBG(event){
var bgrnd = new Bitmap(bg);
stage.addChild(bgrnd);
stage.update();
}
function startGame() {
// create a new stage and point it at our canvas:
stage = new createjs.Stage(canvas);
// grab canvas width and height for later calculations:
screen_width = canvas.width;
screen_height = canvas.height;
// create spritesheet and assign the associated data.
var spriteSheet = new createjs.SpriteSheet({
// image to use
images: [imgMonsterARun],
// width, height & registration point of each sprite
frames: {width: 64, height: 64, regX: 32, regY: 32},
animations: {
walk: [0, 9, "walk"]
}
});
// create a BitmapAnimation instance to display and play back the sprite sheet:
bmpAnimation = new createjs.BitmapAnimation(spriteSheet);
// start playing the first sequence:
bmpAnimation.gotoAndPlay("walk"); //animate
// set up a shadow. Note that shadows are ridiculously expensive. You could display hundreds
// of animated rats if you disabled the shadow.
bmpAnimation.shadow = new createjs.Shadow("#454", 0, 5, 4);
bmpAnimation.name = "monster1";
bmpAnimation.direction = 90;
bmpAnimation.vX = 4;
bmpAnimation.x = 16;
bmpAnimation.y = 32;
// have each monster start at a specific frame
bmpAnimation.currentFrame = 0;
stage.addChild(bmpAnimation);
// we want to do some work before we update the canvas,
// otherwise we could use Ticker.addListener(stage);
createjs.Ticker.addListener(window);
createjs.Ticker.useRAF = true;
createjs.Ticker.setFPS(60);
}
//called if there is an error loading the image (usually due to a 404)
function handleImageError(e) {
console.log("Error Loading Image : " + e.target.src);
}
function tick() {
// Hit testing the screen width, otherwise our sprite would disappear
if (bmpAnimation.x >= screen_width - 16) {
// We've reached the right side of our screen
// We need to walk left now to go back to our initial position
bmpAnimation.direction = -90;
}
if (bmpAnimation.x < 16) {
// We've reached the left side of our screen
// We need to walk right now
bmpAnimation.direction = 90;
}
// Moving the sprite based on the direction & the speed
if (bmpAnimation.direction == 90) {
bmpAnimation.x += bmpAnimation.vX;
}
else {
bmpAnimation.x -= bmpAnimation.vX;
}
// update the stage:
stage.update();
}
</script>
</head>
<body onload="init();">
<canvas id="canvas" width="500" height="500" style="border: thin black solid;" ></canvas>
</body>
</html>
There are a few places where you are using some really old APIs, which may or may not be supported depending on your version of EaselJS. Where did you get the easel.js script you reference?
Assuming you have a version of EaselJS that matches the APIs you are using, there are a few issues:
You add background to the stage. There is no background, so you are probably getting an error when you add it. You already add bgrnd in the setBackground method, which should be fine. If you get an error here, then this could be your main issue.
You don't need to update the stage any time you add something, just when you want the stage to "refresh". In your code, you update after setting the background, and again immediately at the end of your init(). These will fire one after the other.
Are you getting errors in your console? That would be a good place to start debugging. I would also recommend posting code if you can to show an actual demo if you continue to have issues, which will help identify what is happening.
If you have a newer version of EaselJS:
BitmapAnimation is now Sprite, and doesn't support direction. To flip Sprites, use scaleX=-1
Ticker no longer uses addListener. Instead it uses the EventDispatcher. createjs.Ticker.addEventListener("tick", tickFunction);
You can get new versions of the CreateJS libraries at http://code.createjs.com, and you can get updated examples and code on the website and GitHub.
We are working on visualization of sorting algorithms, required to add sleep and wait logic to help visualize the selected element and the element to which it is compared. After searching li'l bit, we found a code "function sleep(milliseconds){...}" which should work as desired but has failed so far.
In function insertionSort(){...}, the current element is depicted with color red and the element to which it is compared with is depicted with color blue, once the current element is swapped with the other the color of the element is again changed to white from blue (working correctly, verified using debugger), However during execution, these color transformations were not visible (only the element in red is displayed after each iteration)
var element = function(value, color)
{
this.value = value;
this.color = color;
};
var x = [];
x[0] = new element(2, "white");
x[1] = new element(1, "white");
x[2] = new element(5, "white");
x[3] = new element(4, "white");
x[4] = new element(3, "white");
x[5] = new element(7, "white");
x[6] = new element(6, "white");
x[7] = new element(8, "white");
x[8] = new element(10, "white");
x[9] = new element(9, "white");
var i = 1;
var context;
var delayTime = 1000;
function myFunction()
{
var bar = document.getElementById("bar");
width = bar.width;
height = bar.height;
context = bar.getContext("2d");
window.setInterval(insertionSort, 3000);
}
function insertionSort()
{
if(i>=0 && i<x.length)
{
var j = i;
x[j].color = "red";
drawGraph(j);
while(j>0 && x[j-1].value > x[j].value)
{
x[j-1].color = "blue";
x[j].color = "red";
drawGraph();
//need to add delay here
sleep(delayTime);
//swap
var temp = x[j];
x[j] = x[j-1];
x[j-1] = temp;
drawGraph();
// and here...
sleep(delayTime);
x[j].color = "white";
drawGraph();
j = j-1;
}
x[j].color = "white";
i++;
}
else if(i>=x.length)
{
for(k=0;k<x.length;k++)
{
x[k].color = "white";
}
drawGraph();
i=-1;
}
}
function sleep(milliseconds)
{
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++)
{
if ((new Date().getTime() - start) > milliseconds)
{
break;
}
}
}
function drawGraph()
{
context.StrokeStyle = "black";
context.clearRect ( 0 , 0 , width, height);
for(k=0;k<x.length;k++)
{
context.fillStyle = x[k].color;
//x and y coordinate of top left corner of rectangle
context.strokeRect(400+k*20, 18, 20, x[k].value*10);
context.fillRect(400+k*20, 18, 20, x[k].value*10);
}
}
<html>
<head>
<script language="javascript" type="text/javascript" src="../p5.js"></script>
<!-- uncomment lines below to include extra p5 libraries -->
<!--<script language="javascript" src="../addons/p5.dom.js"></script>-->
<!--<script language="javascript" src="../addons/p5.sound.js"></script>-->
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<!-- this line removes any default padding and style. you might only need one of these values set. -->
<style> body {padding: 0; margin: 0;} </style>
</head>
<body>
<button onclick="myFunction()">Try it</button>
<canvas id="bar" width="1000" height="400" style="border:2px"></canvas>
</body>
</html>
The approach to used in that implementation of sleep() would be terrible in any programming language, because it consumes a lot of CPU while waiting. In JavaScript, however, it's especially bad, because a JavaScript program is required to relinquish control frequently; it is not permitted to keep computing for an extended period of time. In Chrome browser, for example, Chrome will consider the program to be unresponsive, and will suggest to the user that they kill it.
But even if that weren't the case, it won't produce the desired effect, which I assume is that some animation happens on the screen, with some delay from one step to the next. The way JavaScript works in the browser, is that any changes you make to the page get rendered when your program relinquishes control; nothing updated on-screen while any JavaScript code is running. If you call a sleep function like that one, you are not relinquishing control, you are running JavaScript the whole time, and therefore the browser will not update the screen during that time. It will only update when your entire insertionSort method returns, and the browser has that 3000ms time window (from your setInterval) to take care of its own stuff (rendering).
Unfortunately, you will have to find a way to split up that algorithm, so that each step that you want to be distinctly visible to the user happens in its own timed callback.
It will probably be something along the lines of:
function stepOne() {
do the first bit;
setTimeout(secondStep, delay)
}
secondStep() {
do some more stuff;
setTimeout(thirdStep, delay)
}
and so on. The way you control the speed of the animation is with the delay parameter from one step to the next.
It's going to be tricky, especially because you aren't just trying to animate Insertion Sort, but various algorithms. So then, do you break them all up as in: insertionSortStepOne/Two/Three, shellSortStepOne/Two/Three? that would be quite ugly.
Depending on how ambitious you are, and how much you want to get out of this assignment, you might explore this feature of ES6 (a newer version of JavaScript)
function*
What this lets you do is let your function, with all its nested loops, remain structured pretty much as it is, but you insert points where it relinquishes control. Later, it is called back to continue from the point where it left off. You would use setTimeout or setInterval to do that. I've not experimented with this myself, but it seems super-cool.
I'm trying to build an application which, based on various user interactions, allows for various ellipse based visuals to be added to the stage and then animated very simply. I've currently got a basic demo set up where javascript / jquery communicates with processing.js, but it just seems like really inefficient code, because processing relies on running a continuous loop in order to draw to the screen. I'm wondering, one, if the way I'm doing it will be effective on a larger scale, and two, if there's a better technology or method to use. I come from a flash background where nothing on screen is changed or drawn/animated unless a function is triggered telling it to animate, which seems sensible. Anyway, here's my code:
HTML / JS:
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Processing</title>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="js/processing-1.3.6.min.js"></script>
<script src="processing/Tween.lib"></script>
</head>
<body>
<canvas id="circles" data-processing-sources="js/drawCircles.js"></canvas>
<div id="clicker">Click</div>
<script>
window.Processing.data = {};
var dataRef = window.Processing.data;
var animInterval;
dataRef.circleArray = new Array();
$('#clicker').click(function(){
var circle = {};
circle.radius = 50;
dataRef.circleArray.push(circle)
var from = {property: 50};
var to = {property: 75};
jQuery(from).animate(to, {
duration: 300,
step: function() {
for (var i in dataRef.circleArray){
circle.radius = this.property;
}
}
});
})
</script>
</body>
</html>
PROCESSING.JS
// Global variables
float radius = 1.0;
int X, Y;
int nX, nY;
int delay = 16;
// Setup the Processing Canvas
void setup(){
// Fill canvas grey
background( 100 );
size( 200, 200 );
strokeWeight( 10 );
frameRate( 15 );
X = width / 2;
Y = width / 2;
nX = X;
nY = Y;
}
// Main draw loop
void draw(){
var dataRef = window.Processing.data;
for (var i in window.Processing.data.circleArray){
radius = dataRef.circleArray[i].radius;
// Set fill-color to blue
fill( 0, 121, 184 );
// Set stroke-color white
stroke(255);
// Draw circle
ellipse( X+(i*10), Y, radius, radius );
}
}
If you want to control when Processing.js draws to the canvas, you have two options. In both cases, the first thing you'll want to do is get access to the Processing instance:
var p = Processing.instances[0];
Now you can make all the Processing API calls you want from JavaScript. You could call noLoop() in your sketch's setup() function, and then inside your jQuery animation loop you could call p.redraw(), which will animate one frame.
In Processing.js we attach all of the functions to the Processing instance. So another option is creating your own function in the sketch, and call it with:
var p = Processing.instances[0];
p.drawEllipses(radius);
You could even pass the data to it in the function parameters, removing the need for windows.Processing.data.
For what you want to do, you might prefer using another library such as paperjs http://paperjs.org/
I wrote this javascript to increase canvas size by 1 pixel whenever the ball hit the border. However, the whole canvas will blink when the size is changed. Don't know what causes this problem. Is there any way to fix?
function testWalls() {
var ball;
var testBall;
for (var i =0; i <balls.length; i++) {
ball = balls[i];
if (ball.nextX+ball.radius > theCanvas.width) {
ball.velocityX = ball.velocityX*-1;
ball.nextX = theCanvas.width - ball.radius;
theCanvas.width++;
drawScreen();
} else if (ball.nextX-ball.radius < 0 ) {
ball.velocityX = ball.velocityX*-1;
ball.nextX = ball.radius;
} else if (ball.nextY+ball.radius > theCanvas.height ) {
ball.velocityY = ball.velocityY*-1;
ball.nextY = theCanvas.height - ball.radius;
theCanvas.height++;
drawScreen();
} else if(ball.nextY-ball.radius < 0) {
ball.velocityY = ball.velocityY*-1;
ball.nextY = ball.radius;
}
}
}
a demo can be found here
http://converteveryunit.com/pot/demo3.html
I haven't looked at your code, but there are a few things you can do, but I will mention two.
One is to buffer your code, so you would draw to an off-screen canvas, then put that on, but, the more important thing is not to clear the entire image, then redraw.
Clear just what is changing, and redraw that, which should fix your problem.
For more ideas on what you can do you can look at
http://www.html5rocks.com/en/tutorials/canvas/performance/
You can use buffering.
Here is a good tutorial for it:
http://www.slideshare.net/ernesto.jimenez/5-tips-for-your-html5-games
Nice application! :)
I think you might get a better user experience by making the sliders change canvas onMouseUp instead of onMouseMove.
Also, I noticed that some balls are spawning one inside another, and so they are getting stuck toguether forever. You could check collision before spawning to avoid that.