How to avoid blink when resizing canvas - javascript

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.

Related

Detection with collision in canvas phaser without physics

I have to do a mini video game for a practice. I have coded in Phaser, JavaScript and Java. The canvas is drawn in Phaser.
I need to put collisions in the borders of the world or something when my spaceship touch the canvas limit for my spaceship doesn't go out to the screen.
My teacher forbidden do something with physics like arcade, ninja, or P2.
Its doesn't matter if the solution is in JavaScript or Phaser. Only I need to put limits in the canvas' border.
I have this for drawing the world in Phaser:
game = new Phaser.Game(1024, 600, Phaser.AUTO, 'gameDiv'
I have my sprite in the world in the preload:
game.global.myPlayer.image = game.add.sprite(0, 0, 'spacewar', game.global.myPlayer.shipType);
In the create function I have the keyboard control:
this.wKey = game.input.keyboard.addKey(Phaser.Keyboard.UP);
this.sKey = game.input.keyboard.addKey(Phaser.Keyboard.DOWN);
this.aKey = game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
this.dKey = game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
this.spaceKey = game.input.keyboard.addKey(Phaser.Keyboard.CONTROL);
this.shiftKey = game.input.keyboard.addKey(Phaser.Keyboard.SHIFT);
In the update function the movement:
if (this.wKey.isDown)
msg.movement.thrust = true;
if (this.sKey.isDown)
msg.movement.brake = true;
if (this.aKey.isDown)
msg.movement.rotLeft = true;
if (this.dKey.isDown)
msg.movement.rotRight = true;
if (this.spaceKey.isDown) {
msg.bullet = this.fireBullet()
}
if (this.shiftKey.isDown) {
msg.push = true;
}
Not sure how asking for the solution to a school project will help you learn anything..
But anyway, the update() function is called for every frame (60 times per second), so inside that function you can do something like this to prevent the player from moving outside the game area:
// cannot move outside game area, left and right
if (game.global.myPlayer.image.x < 0) {
game.global.myPlayer.image.x = 0;
}
if (game.global.myPlayer.image.x > game.world.width) {
game.global.myPlayer.image.x = game.world.width;
}
// cannot move outside game area, top and bottom
if (game.global.myPlayer.image.y < 0) {
game.global.myPlayer.image.y = 0;
}
if (game.global.myPlayer.image.y > game.world.height) {
game.global.myPlayer.image.y = game.world.height;
}

How would I create a "Choose your Own Adventure game" on Canvas?

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.

How can I load new material.map.image.src in background and then render

I am trying to change material.map.image.src on the fly when interacting with mouse, but each time i set the new image, the scene jitters while the image loads. to show the problem at its worst, i have linked the change to the onMouseMove event.
A working jittery example is here: Example
I am doing this in the onMouseMove event which is probably the wrong approach and my code is crude as I have tried to learn javascript in order to use three.js: monkey see, monkey do style.
Can anyone help me make the intersects[i].object.material.map.image.src = "/images/maisy.jpg"; work in the background...?
function onMouseMove(e) {
e.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children);
for (var i = 0; i < intersects.length; i++) {
intersects[i].object.material.map.image.src = "/images/maisy.jpg";
exit; // ensures foreground object is adjusted and not all behind it.
}
}
It is probably obvious to you all, but it has taken me some time to get this far and now I'm stumped.
Many thanks in advance to all who read,
James
Somewhere in your init code you would do:
maisyTex = THREE.ImageUtils.loadTexture( "images/maisy.jpg" );
with maisyTex being a global variable. Then in your code you would just do:
intersects[i].object.material.map = maisyTex;

CreateJS FPS drop when calling stage.update

I'm making a game using CreateJS. On desktop my FPS is good but when I try to play this game on mobile (for example : iPhone 4) the FPS drops seriously.
I'm trying to figure out why but
Some code
My Canvas
<canvas id="gameCanvas"></canvas>
Setup
this.canvas = "gameCanvas";
this.stage = new createjs.Stage(this.canvas);
var context = this.stage.canvas.getContext("2d");
context.imageSmoothingEnabled = false;
createjs.Ticker.setFPS(30);
this.gameLoopBind = this.gameLoop.bind(this);
createjs.Ticker.addEventListener('tick', this.gameLoopBind);
GameLoop
// some extra code
this.stage.update();
When I comment the code 'this.stage.update()' my FPS on mobile/tablet is good...
I've no idea what I'm doing wrong...
EXTRA CODE
Play the game here => f.cowb.eu/mora/chick-ins
Gameloop Function
Game.prototype.gameLoop = function (e) {
if (this.running) {
this.timer++;
this.timer2++;
if (this.timer2 > 30) {
if (this.lastSnack + this.timeBewteen < this.stopwatch.seconds) {
var height = (this.topSnack) ? 150 : 300;
this.lastSnack = this.stopwatch.seconds;
new Snack(this, this.timer, height);
this.topSnack = this.topSnack ? false : true;
}
if (this.timer > (this.lastPostive + 300)) {
this.lastPostive = this.timer;
publisher.publish('showMessage',
this.positiveImages[Math.floor(Math.random() * this.positiveImages.length)],
common.lang,
'right');
}
this.timer2 = 0;
}
}
this.stage.update();
};
New Snack
You can find the code for creating a new snack here => http://jsfiddle.net/9ofpqq3z/
Here we create a new snack and animate it.
From looking at the architecture of the game, I would suggest that you draw the game elements on separate canvases as opposed to the way you have it right now where everything is on one canvas.
Place the TV parts that don't get redrawn often (or at all) on one canvas, and then the moving elements on a separate canvas.
That should help bring the frame rate up.
Also, you can take a look at the following set of slides on how to improve performance on mobile devices when using the canvas:
http://www.slideshare.net/DavidGoemans/html5-performance-optimization

Flip a sprite in canvas

I'm using canvas to display some sprites, and I need to flip one horizontally (so it faces left or right). I can't see any method to do that with drawImage, however.
Here's my relevant code:
this.idleSprite = new Image();
this.idleSprite.src = "/game/images/idleSprite.png";
this.idleSprite.frameWidth = 28;
this.idleSprite.frameHeight = 40;
this.idleSprite.frames = 12;
this.idleSprite.frameCount = 0;
this.draw = function() {
if(this.state == "idle") {
c.drawImage(this.idleSprite, this.idleSprite.frameWidth * this.idleSprite.frameCount, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, this.xpos, this.ypos, this.idleSprite.frameWidth, this.idleSprite.frameHeight);
if(this.idleSprite.frameCount < this.idleSprite.frames - 1) { this.idleSprite.frameCount++; } else { this.idleSprite.frameCount = 0; }
} else if(this.state == "running") {
c.drawImage(this.runningSprite, this.runningSprite.frameWidth * this.runningSprite.frameCount, 0, this.runningSprite.frameWidth, this.runningSprite.frameHeight, this.xpos, this.ypos, this.runningSprite.frameWidth, this.runningSprite.frameHeight);
if(this.runningSprite.frameCount < this.runningSprite.frames - 1) { this.runningSprite.frameCount++; } else { this.runningSprite.frameCount = 0; }
}
}
As you can see, I'm using the drawImage method to draw my sprites to the canvas. The only way to flip a sprite that I can see is to flip/rotate the entire canvas, which isn't what I want to do.
Is there a way to do that? Or will I need to make a new sprite facing the other way and use that?
While Gaurav has shown the technical way to flip a sprite in canvas...
Do not do this for your game.
Instead make a second image (or make your current image larger) that is a flipped version of the spite-sheet. The performance difference between "flipping the context and drawing an image" vs "just drawing an image" can be massive. In Opera and Safari flipping the canvas results in drawing that is ten times slower, and in Chrome it is twice as slow. See this jsPerf for an example.
Pre-computing your flipped sprites will always be faster, and in games canvas performance really matters.
You can transform the canvas drawing context without flipping the entire canvas.
c.save();
c.scale(-1, 1);
will mirror the context. Draw your image, then
c.restore();
and you can draw normally again. For more information, see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Transformations
Use this to flip your sprite sheet
http://flipapicture.com/

Categories