So I have these functions to fade a canvas in and out that aren't working the way I expect them to. Here's what I'm working with at the moment:
function fade_out ()
{
var canvas = document.getElementById("builder");
var context = canvas.getContext('2d');
console.log(context.globalAlpha);
context.globalAlpha -= 0.01;
if(context.globalAlpha > 0)
{
setTimeout(fade_out, 5);
}
}
function fade_in ()
{
var canvas = document.getElementById("builder");
var context = canvas.getContext('2d');
context.globalAlpha += 0.01;
if(context.globalAlpha < 1)
{
setTimeout(fade_in, 5);
}
}
My intent was to make it a half second fade. What I ended up with was it just blinking in and out in a flash. The console.log in the first function tells me it's not even close to working the way I expect it to. What went wrong here?
EDIT: There seems to be an endless loop going, and the context.globalAlpha is getting into 20 significant digits, even though I didn't use numbers like that.
function fade_in() {
setTimeout( function() {
var cn = document.getElementById("builder");
var ct = cn.getContext('2d').globalAlpha;
ct += 0.02;
if(ct >= 1) {
ct=1;
}
if (ct < 1) {
fade_in();
}
else {
return false;
}
}, 30);
}
function fade_out() {
setTimeout( function() {
var cn = document.getElementById("builder");
var ct = cn.getContext('2d').globalAlpha;
ct -= 0.02;
if(ct <= 0) {
ct=0;
}
if (ct > 0) {
fade_out();
}
else {
return false;
}
}, 30);
}
Related
I have 2 sets of code in here. One is the simple bounce off code. The other is a function. I've tried to make it a function but it doesn't seem to be working properly.
The bg framerate doesn't clear in the sense that a string of balls show rather than a ball bouncing and animating.
if(this.y_pos > 400) this condition doesn't seem to be working even tho it works when it is drawn in the draw function.
var sketch = function (p) {
with(p) {
p.setup = function() {
createCanvas(800, 600);
// x_pos = 799;
// y_pos = 100;
// spdx = -random(5,10);
// spdy = random(12,17);
};
p.draw = function() {
background(0);
// fill(255);
// ellipse(x_pos,y_pos,50);
// x_pos += spdx;
// y_pos += spdy;
// if(y_pos > 400)
// {
// spdy *= -1;
// }
// for( var i = 0; i < 10; i++)
avalance(799, 100, random(5,10), random(12,17));
};
function avalance(x, y, spdx, spdy)
{
this.x_pos = x;
this.y_pos = y;
this.spdx = spdx;
this.spdy = spdy;
this.x_pos = 799;
this.y_pos = 100;
this.spdx = 1;
this.spdy = 1;
this.movement = function()
{
this.x_pos += -spdx;
this.y_pos += spdy;
if(this.y_pos > 400)
{
this.spdy *= -1;
}
}
this.draw = function()
{
this.movement();
this.drawnRox();
}
this.drawnRox = function()
{
fill(255);
ellipse(this.x_pos,this.y_pos,50);
}
}
}
};
let node = document.createElement('div');
window.document.getElementById('p5-container').appendChild(node);
new p5(sketch, node);
body {
background-color:#efefef;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<div id="p5-container"></div>
Let's address both issues:
The draw() function is called for each new frame and in it you call avalance which creates a new ball. To fix that you need to
Create a global variable let ball; out of setup() and draw() so that you can reuse that later;
In setup create a new ball and assign it to your ball variable: ball = new avalance(799, 100, random(5,10), random(12,17));
In draw() you want to update the ball and that's what its own draw() function does (I would advise renaming it update() for example, to avoid confusion with the p5 specific draw() function). So you just need to call ball.draw() in draw().
This creates a ball which moves but still don't respect your 400px limit.
The issue is that in movement() you add spdx and spdy to the position but when the ball crosses the limit you update this.spdy, so you need to update the function with this code:
this.x_pos += -this.spdx;
this.y_pos += this.spdy;
And you should be good! Here is a code pend with your code working as you intend.
Also as a bonus advise: You probably want to use some p5.Vector objects to store positions, speeds and accelerations it really makes your code easier to read and to use. You could also rename your function Avalance (capital A) to show that you actually use a class and that this function shouldn't be called without new.
As #statox suggested, do new avalance(799, 100, random(5,10), random(12,17)) in the setup() section and call draw of the ball in draw() section.
You can test the code below by clicking "Run code snippet".
var sketch = function (p) {
with(p) {
var ball;
p.setup = function() {
createCanvas(800, 600);
ball = new avalance(799, 100, random(5,10), random(12,17));
};
p.draw = function() {
background(0);
ball.draw();
};
function avalance(x, y, spdx, spdy)
{
function movement ()
{
x += -spdx;
y += spdy;
if (y > height || y < 0)
{
spdy *= -1;
}
if (x > width || x < 0)
{
spdx *= -1;
}
}
this.draw = function()
{
movement();
drawnRox();
}
function drawnRox ()
{
fill(255);
ellipse(x,y,50);
}
}
}
};
let node = document.createElement('div');
window.document.getElementById('p5-container').appendChild(node);
new p5(sketch, node);
body {
background-color:#efefef;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<div id="p5-container"></div>
Im trying to make simple game in canvas. I made animation for hero using setTimeout() function. I check pressed keys with function moove(e):
Everything works pretty fine when i press leftarrow or rightarrow for the first time, but then hero doesnt moove. Any recomendations to the code is appreciated.
var cns = document.getElementById("can");
cns.height = 600;
cns.width = 300;
var ctx = cns.getContext("2d");
var hero = new Image();
hero.src = "images/hero.png";
hero.onload = function() {
ctx.drawImage(hero, 120, 570);
hero.xx = 120;
hero.yy = 570;
};
var intervalL, intervalR, intervalLL, intervalRR;
var keys = [];
function moove(e) {
keys[e.keyCode] = (e.type == "keydown");
if (keys[37]) {
clearTimeout(intervalR);
clearTimeout(intervalRR);
goLeft(hero);
} else {
clearTimeout(intervalL);
clearTimeout(intervalLL);
}
if (keys[39]) {
clearTimeout(intervalL);
clearTimeout(intervalLL);
goRight(hero);
} else {
clearTimeout(intervalR);
clearTimeout(intervalRR);
}
}
function goLeft(img) {
var x = img.xx,
y = img.yy;
function f() {
ctx.clearRect(img.xx, img.yy, img.width, img.height);
ctx.drawImage(img, x, y);
img.xx = x;
img.yy = y;
x -= 1.2;
if (x < -35) {
x = cns.width;
}
}
if (!intervalL) {
intervalL = setTimeout(function run() {
f();
intervalLL = setTimeout(run, 5);
}, 5);
}
}
Function goRight is similiar to goLeft.
Function moove is called in tag body onkeydown='moove(event)' onkeyup='moove(event)'.
You can check the project here: https://github.com/Fabulotus/Fabu/tree/master/Canvas%20game%20-%20dodge%20and%20jump
The reason it doesn't work the first time is because the first time through you are setting the position to its previous position (x = image.xx) then updating x after you draw. You should update the x value x -= 1.2 before calling drawImage
Here is a "working" version of your code:
var cns = document.getElementById("can");
cns.height = 170;
cns.width = 600;
var ctx = cns.getContext("2d");
var hero = new Image();
hero.src = "http://swagger-net-test.azurewebsites.net/api/Image";
hero.onload = function() {
ctx.drawImage(hero, cns.width-10, cns.height/2);
hero.xx = cns.width-10;
hero.yy = cns.height/2;
};
var intervalL, intervalR, intervalLL, intervalRR;
var keys = [];
function goLeft(img) {
function f() {
ctx.beginPath()
ctx.clearRect(0, 0, cns.width, cns.height);
ctx.drawImage(img, img.xx, img.yy);
img.xx--;
if (img.xx < -img.width) {
img.xx = cns.width;
}
}
if (!intervalL) {
intervalL = setTimeout(function run() {
f();
intervalLL = setTimeout(run, 5);
}, 5);
}
}
goLeft(hero)
<canvas id="can">
As you can see the function goLeft has been significantly simplified.
One recommendation: avoid the many setTimeout and clearTimeout instead use one setInterval to call a draw function that takes care of drawing everything on your game, all the other function should just update the position of your gameObjects.
The bug happens when you shoot and die at the same time, and in the console it pops up as "Uncaught TypeError: Cannot read property 'draw' of undefined. Line 65"
The thing is, the bug started happening when I included the function that kills the player, which starts on line 143, and the thing that breaks it is the single line
enemy = [];
Here's the enemy function
function Enemy(x, y) {
this.x = x;
this.y = y;
this.draw = function() {
noStroke();
fill(255, 0, 0);
rect(this.x, this.y, 20, 20);
}
this.move = function() {
this.x -= movement; }
this.offscreen = function() {
if(this.x < 0) {
return true;
} else {
return false;
}
}
this.contact = function() {
for(let i = 0; i < enemy.length; i++) {
var d = dist(playerx, playery, enemy[i].x, enemy[i].y);
if(d <= 20) {
this.kill();
}
}
}
this.kill = function() {
var prevScore = score;
playerx = width / 10;
playery = height / 2;
alert("You died! your score was: " + prevScore);
fire = [];
enemy = [];
score = 0
}
}
Here's where it says it's getting the type error (which worked perfectly before)
This is lines 55 - 74
for(let i = fire.length - 1; i > 0; i--) {
fire[i].draw();
fire[i].move();
fire[i].check();
if(fire[i].offscreen()) {
fire.splice(i, 1);
}
}
for(let i = enemy.length - 1; i > 0; i--) {
enemy[i].draw();
enemy[i].move();
if(enemy[i].offscreen()) {
enemy.splice(i, 1);
}
if(enemy[i].contact()) {
enemy[i].kill();
}
}
The entire code is here: https://code.sololearn.com/Wtza5vElEZ9d/?ref=app
(It's less than 200 lines so not really big)
As well as that bug, I am wanting to find out how it would be possible to make the game gradually get faster. I tried having the frameCount be divided/modulos by a variable (that I had called spawnRate) but when I altered the variable in any way, it just stopped spawning the squares all together.
It's also made with p5.js.
Your enemy.contact() function is used in if statement so you should return a boolean with that function.
this.contact = function() {
return dist(playerx, playery, this.x, this.y) <= 20;
}
It would be better if you make function death() in player object.
It will not be so confusing.
I'm a bit new to JavaScript and have been playing around with Phaser lately. So I'm building an infinite side scroller and everything works fine except that my player won't collide with the walls. Both sprites have physics enabled and I have tried multiple solutions, none of which work. Can you please help me out?
function bloxo()
{
var game = new Phaser.Game(1200, 600, Phaser.CANVAS, 'gameStage', { preload: preload, create: create, update: update });
var prevHole = 3;
function preload() {
game.load.image('bloxoDown','../bloxo/assets/images/bloxoDown.png');
game.load.image('bloxoUp','../bloxo/assets/images/bloxoUp.png');
game.load.image('wall','../bloxo/assets/images/platform.png',400,200);
var space;
var esc;
var player;
var walls;
var score;
}
function create() {
//Canvas With a White Bacground and Physics is Created
game.stage.backgroundColor = "#ffffff";
game.physics.startSystem(Phaser.Physics.ARCADE);
//Sets the initial Score.
score = 0;
//Sets how fast the tiles move
tileSpeed = -300;
tileWidth = game.cache.getImage('wall').width;
tileHeight = game.cache.getImage('wall').height;;
//Keys for User Input are created
space = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
esc = game.input.keyboard.addKey(Phaser.Keyboard.ESC);
//Adds Bloxo to the game as a sprite.
player = game.add.sprite(200,200,'bloxoDown');
player.scale.setTo(0.6, 0.6);
game.physics.enable(player, Phaser.Physics.ARCADE);
player.body.collideWorldBounds = true;
player.body.immovable = true;
//Walls Group is created
walls = game.add.physicsGroup();
walls.createMultiple(50, 'wall');
walls.enableBody = true;
game.physics.arcade.overlap(player, walls,null,this)
game.physics.arcade.collide(player,walls,gameOver);
// Stop the following keys from propagating up to the browser
game.input.keyboard.addKeyCapture([ Phaser.Keyboard.SPACEBAR, Phaser.Keyboard.ESC,]);
//Unpausing Function
window.onkeydown = function(event)
{
if (esc.onDown && (esc.timeDown > 2000))
{
if(game.paused)
{
game.paused = !game.paused;
pauseLbl.destroy();
}
}
}
//Add an initial platform
addWall();
//Add a platform every 3 seconds
var timerWorld = game.time.events.loop(500, addWall);
}
function update() {
if (space.isDown)
{
player.body.y -=5;
bloxoUp();
}
else
{
player.body.y +=5;
bloxoDown();
}
if(esc.isDown)
{
pauseGame();
}
}
function bloxoUp()
{
player.loadTexture('bloxoUp');
}
function bloxoDown()
{
player.loadTexture('bloxoDown');
}
function pauseGame()
{
game.paused = true;
pauseLbl = game.add.text(500, 300, 'Game Paused', { font: '30px Roboto', fill: '#aaaaaa' });
}
function addTile(x,y)
{
//Get a tile that is not currently on screen
var tile = walls.getFirstDead();
//Reset it to the specified coordinates
tile.reset(x,y);
tile.body.velocity.x = tileSpeed;
tile.body.immovable = true;
//When the tile leaves the screen, kill it
tile.checkWorldBounds = true;
tile.outOfBoundsKill = true;
}
function addWall()
{
//Speed up the game to make it harder
tileSpeed -= 1;
score += 1;
//Work out how many tiles we need to fit across the whole screen
var tilesNeeded = Math.ceil(game.world.height / tileHeight);
//Add a hole randomly somewhere
do
{
var hole = Math.floor(Math.random() * (tilesNeeded - 2)) + 1;
}while((hole > (prevHole + 2)) && (hole < (prevHole - 2)) );
prevHole = hole;
//Keep creating tiles next to each other until we have an entire row
//Don't add tiles where the random hole is
for (var i = 0; i < tilesNeeded; i++){
if (i != hole && (i != hole+1 && i != hole-1) && (i != hole+2 && i != hole-2)){
addTile(game.world.width, i * tileHeight);
}
}
}
function gameOver()
{
console.log("player hit");
player.kill();
game.state.start(game.state.current);
}
}
You have just to move collide call into your update method:
game.physics.arcade.collide(player, walls, gameOver);
Take a look to the runnable snippet below(I have resized the canvas for the preview, sorry) or Fiddle:
var game = new Phaser.Game(450, 150, Phaser.CANVAS, 'gameStage', {
preload: preload,
create: create,
update: update
});
var prevHole = 3;
function preload() {
game.load.image('bloxoDown', '../bloxo/assets/images/bloxoDown.png');
game.load.image('bloxoUp', '../bloxo/assets/images/bloxoUp.png');
game.load.image('wall', '../bloxo/assets/images/platform.png', 400, 100);
var space;
var esc;
var player;
var walls;
var score;
}
function create() {
//Canvas With a White Bacground and Physics is Created
game.stage.backgroundColor = "#ffffff";
game.physics.startSystem(Phaser.Physics.ARCADE);
//Sets the initial Score.
score = 0;
//Sets how fast the tiles move
tileSpeed = -300;
tileWidth = game.cache.getImage('wall').width;
tileHeight = game.cache.getImage('wall').height;;
//Keys for User Input are created
space = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
esc = game.input.keyboard.addKey(Phaser.Keyboard.ESC);
//Adds Bloxo to the game as a sprite.
player = game.add.sprite(200, 200, 'bloxoDown');
player.scale.setTo(0.6, 0.6);
game.physics.enable(player, Phaser.Physics.ARCADE);
player.body.collideWorldBounds = true;
player.body.immovable = true;
//Walls Group is created
walls = game.add.physicsGroup();
walls.createMultiple(50, 'wall');
walls.enableBody = true;
game.physics.arcade.overlap(player, walls, null, this)
// remove your call to collide
// Stop the following keys from propagating up to the browser
game.input.keyboard.addKeyCapture([Phaser.Keyboard.SPACEBAR, Phaser.Keyboard.ESC, ]);
//Unpausing Function
window.onkeydown = function(event) {
if (esc.onDown && (esc.timeDown > 2000)) {
if (game.paused) {
game.paused = !game.paused;
pauseLbl.destroy();
}
}
}
//Add an initial platform
addWall();
//Add a platform every 3 seconds
var timerWorld = game.time.events.loop(500, addWall);
}
function update() {
if (space.isDown) {
player.body.y -= 5;
bloxoUp();
} else {
player.body.y += 5;
bloxoDown();
}
// move your collide call here
game.physics.arcade.collide(player, walls, gameOver);
if (esc.isDown) {
pauseGame();
}
}
function bloxoUp() {
player.loadTexture('bloxoUp');
}
function bloxoDown() {
player.loadTexture('bloxoDown');
}
function pauseGame() {
game.paused = true;
pauseLbl = game.add.text(500, 300, 'Game Paused', {
font: '30px Roboto',
fill: '#aaaaaa'
});
}
function addTile(x, y) {
//Get a tile that is not currently on screen
var tile = walls.getFirstDead();
//Reset it to the specified coordinates
if (tile) {
tile.reset(x, y);
tile.body.velocity.x = tileSpeed;
tile.body.immovable = true;
//When the tile leaves the screen, kill it
tile.checkWorldBounds = true;
tile.outOfBoundsKill = true;
}
}
function addWall() {
//Speed up the game to make it harder
tileSpeed -= 1;
score += 1;
//Work out how many tiles we need to fit across the whole screen
var tilesNeeded = Math.ceil(game.world.height / tileHeight);
var prevHole;
//Add a hole randomly somewhere
do {
var hole = Math.floor(Math.random() * (tilesNeeded - 2)) + 1;
} while ((hole > (prevHole + 2)) && (hole < (prevHole - 2)));
prevHole = hole;
//Keep creating tiles next to each other until we have an entire row
//Don't add tiles where the random hole is
for (var i = 0; i < tilesNeeded; i++) {
if (i != hole && (i != hole + 1 && i != hole - 1) && (i != hole + 2 && i != hole - 2)) {
addTile(game.world.width, i * tileHeight);
}
}
}
function gameOver() {
console.log("player hit");
player.kill();
game.state.start(game.state.current);
}
canvas{
border: 5px solid #333;
margin-left:25px;
margin-top:25px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/2.6.2/phaser.min.js"></script>
I am making a game with html and javascript. Just for clarification, this is not a duplicate or anything. Nothing has the answer I need. Also before I explain, I want to say I have no trouble with the key listener, my game knows when a key is pressed and when it is released. Okay, I have 5 frames of a character walking. I have a while loop that basically says while the key D is pressed or Right arrow is pressed, then increment the frames to make it look like the character is walking. Then it has a setTimeout function that pauses for 1/10 of a second. This should make it look like the character is walking. I know it has something to do with the setTimeout() function. Here is the while loop:
while (keys[68] || keys[39]) {
charFrame++;
setTimeout(function() {
}, 100);
}
Then here is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sparring Spartans</title>
<style type="text/css">
</style>
</head>
<body>
<canvas id="canvas" width="1000" height="600"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
var groundX = 0, groundY = 400;
var playerx = width/2, playery = groundY-120;
var charFrame = 1;
var speed = 4;
var keys = [];
window.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
}, false);
window.addEventListener("keyup", function(e) {
delete keys[e.keyCode];
}, false);
var spartan1 = new Image();
spartan1.src = "spartan1.png";
var spartan2 = new Image();
spartan2.src = "spartan2.png";
var spartan3 = new Image();
spartan3.src = "spartan3.png";
var spartan4 = new Image();
spartan4.src = "spartan4.png";
var spartan5 = new Image();
spartan5.src = "spartan5.png";
var stone = new Image();
stone.src = "stone.png";
function game() {
update();
render();
}
function player() {
if (charFrame === 1) {
context.drawImage(spartan1, playerx, playery);
} else if (charFrame === 2) {
context.drawImage(spartan2, playerx, playery);
} else if (charFrame === 3) {
context.drawImage(spartan3, playerx, playery);
} else if (charFrame === 4) {
context.drawImage(spartan4, playerx, playery);
} else if (charFrame === 5) {
context.drawImage(spartan5, playerx, playery);
}
}
function ground() {
for (var i = 0; i <= 1000; i += 55) {
context.drawImage(stone, i, groundY);
}
for (var i = 0; i <= 1000; i += 55) {
context.drawImage(stone, i, groundY+55);
}
for (var i = 0; i <= 1000; i += 55) {
context.drawImage(stone, i, groundY+110);
}
for (var i = 0; i <= 1000; i += 55) {
context.drawImage(stone, i, groundY+165);
}
}
function manager() {
ground();
while (keys[68] || keys[39]) {
charFrame++;
setTimeout(function() {
}, 100);
}
player();
}
function update() {
manager();
player();
}
function render() {
context.fillStyle = "#AFE4FF";
context.fillRect(0, 0, width, height);
manager();
}
setInterval(function() {
game();
}, 1000/30);
</script>
</body>
</html>
What am I doing wrong? I know it HAS to be the setTimeout, but I have tried to fix this problem many times. The images don't even change.
Because your manager function gets called 30 times per second, you should check your keypress once per frame using an if statement instead of a loop:
function manager() {
ground();
if (keys[68] || keys[39]) {
charFrame++;
}
}
In addition, your manager function is getting called twice per frame, once in the update function and once in the render function. Also, your player function is called both in update and in manager, again twice per frame. Your code will need some refactoring in order to work properly, to make sure nothing gets called twice per frame.