Part of text dose not show up on screen. JavaScript beginner - javascript

Ending screen should show winning player and sign "click to continue" which is doing but only with the click to continue. I just start with javascript and i try to write code as logic as i can.
function drawEverything() {
canvasContext.fillStyle = 'black';
canvasContext.fillRect(0, 0, canvas.width, canvas.height);
if (showWinScreen) {
canvasContext.fillStyle = 'white';
if (player1Score >= WINNING_SCORE) {
canvasContext.fillText("PLAYER 1 WON!", 400, 100);
} else if (player2Score >= WINNING_SCORE) {
canvasContext.fillText("PLAYER 2 WON!", 400, 100);
}
canvasContext.fillText("PLEASE CLICK TO CONTINUE", 350, 500);
return;
}
Variables from this code below are now changed to the part which is last in sequence of work.
function ballReset() {
if (player1Score >= WINNING_SCORE ||
player2Score >= WINNING_SCORE) {
player1Score = 0;
player2Score = 0;
showWinScreen = true;
}
Now they are here on part that is closing screen with information which shows who won but problem is still same :/
function mouseClick(evt) {
player1Score = 0;
player2Score = 0;
showWinScreen = false;
}

You only draw the victory message if (player1Score >= WINNING_SCORE). However, player1Score gets set to zero in ballReset(), so it can't possibly be greater than the WINNING_SCORE. You need to store the winning player some other way or don't reset the scores to zero until the game restarts.

Related

Keyboard input pause [duplicate]

This question already has answers here:
move element with keypress (multiple)
(3 answers)
Closed 3 years ago.
I made a pretty basic demo, you press an arrow key and the square moves in that direction. One problem: when I first press the key, the square moves a little, pauses, then continues moving. How do I get rid of or work around the pause?
Code:
var canvas = document.getElementById("canvas")
var ctx = canvas.getContext('2d');
var p1 = document.getElementById("p1");
var keys = [];
var x = 25
var y = 25
document.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
update();
});
document.addEventListener("keyup", function(e) {
keys[e.keyCode] = false;
update();
});
function update() {
ctx.clearRect(0, 0, 400, 400)
if(keys[40] == true) {
y += 5
}
if(keys[38] == true) {
y -= 5
}
if(keys[39] == true) {
x += 5
}
if(keys[37] == true) {
x -= 5
}
ctx.fillRect(x, y, 100, 100)
console.log(keys);
p1.innerText = "";
for (i = 0; i < keys.length; i++) {
if (keys[i]) {
p1.innerText += i + " | ";
}
}
}
<canvas id='canvas' width='400' height='400'></canvas>
<p id='p1'>testing</p>
This happens because the keydown event is continuously fired at different intervals in different browsers.
Instead of relying on the browser to send keydown from time to time, it's better to have your own update loop running at 60fps, using requestAnimationFrame and each frame moving the box based on the keys pressed.
var canvas = document.getElementById("canvas")
var ctx = canvas.getContext('2d');
var p1 = document.getElementById("p1");
var keys = [];
var x = 25
var y = 25
document.addEventListener("keydown", function(e) {
e.preventDefault(); // make sure this doesn't scroll the window
keys[e.keyCode] = true;
});
document.addEventListener("keyup", function(e) {
keys[e.keyCode] = false;
});
function update() {
// Tell the browser to run again update when it is "free",
// preferably at 60fps (actually your monitor's refresh rate)
requestAnimationFrame(update);
ctx.clearRect(0, 0, 400, 400)
if(keys[40] == true) {
y += 5
}
if(keys[38] == true) {
y -= 5
}
if(keys[39] == true) {
x += 5
}
if(keys[37] == true) {
x -= 5
}
ctx.fillRect(x, y, 100, 100)
p1.innerText = "";
for (i = 0; i < keys.length; i++) {
if (keys[i]) {
p1.innerText += i + " | ";
}
}
}
update(); // Start running the loop at 60fps
<canvas id='canvas' width='400' height='400'></canvas>
<p id='p1'>testing</p>
Note that the distance the box moves in a given amount of time depends on your framerate, so if the browser can't keep up at 60fps and only runs at 30fps, update will be only called half of the times, so the box will only move half of the distance it would otherwise move at 60fps. To learn more about animations and game update loops I recommend to read this fix your timestep article.

I am having a bug with the enemies and when they reach your character in a small game I made

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.

Sprite vs Group Collider not working in phaser with enableBody set as true

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>

Draw circle line and then erase it

I have a simple script where by I am trying to draw a circle when a mouse goes over the canvas and it takes about 2000 milliseconds, when the mouse leaves the canvas it then erases the circle.
I got most of it working - it draws the circle correctly, but the mouse out does not fully work as it keeps restarting.
This is my code:
canvas.addEventListener('mouseover',fill,false);
canvas.addEventListener('mouseout',erase, false);
function fill(){
circle.animate = true;
circle.direction = 1;
}
function erase(){
circle.animate = true;
circle.direction = 0;
}
function maths(){
if(circle.animate == true){
var amount = circle.vector * deltaTime;
if(circle.direction == 1){
circle.curAngle += amount;
}else if(circle.direction == 0){
circle.curAngle -= amount;
}
if(circle.curAngle % 2 == 0){
circle.curAngle = 0;
}
if(circle.curAngle == circle.endAngle){
circle.animate = false;
}
}
}
function draw(){
deltaTime = Date.now() - frame;
frame = Date.now();
maths();
context.clearRect(0,0,canvas.width,canvas.height);
context.beginPath();
context.arc(canvas.width/2, canvas.height/2, 100, circle.startAngle * Math.PI, circle.curAngle * Math.PI,false);
context.lineWidth = 2;
context.strokeStyle = 'blue';
context.stroke();
setTimeout(draw,1);
}
frames = Date.now();
draw();
I have made a fiddle of it too: http://jsfiddle.net/hru7xyfu/, to reproduce the error mouse over the canvas and wait for it to fully fill up then mouse out and you see the circle keeps restarting after it has fully erased it.
Where am i going wrong?
Try replacing
if(circle.curAngle == circle.endAngle){
circle.animate = false;
}
with:
if(circle.curAngle < circle.endAngle){
circle.curAngle = circle.endAngle
circle.animate = false;
}
if(circle.curAngle > circle.endAngle + 2){
circle.curAngle = circle.endAngle + 2
circle.animate = false;
}
The second if statement solves an issue where the circle grows too large (though you can't see it, because it starts overlapping itself)
Updated JSFiddle here:
http://jsfiddle.net/hru7xyfu/2/

How can I create a running animation on an HTML5 canvas?

I am building a simple 2D game as an attempt to learn canvas. The character can run around a virtual environment, and a variable called yOffset controls his offset from the top of the screen. I also have a global variable called running which sets itself to true or false based on whether or not the character is running (not shown here). My goal is to make the character bob up and down whilst he is running, and all the below code does is spawn lots of setInterval()s. Is this the right way to make my character run, or should I do it another way? If so, how?
$(document).keydown(function(e) {
if(e.which == 97) {
running = true;
run();
} else if(e.which == 100) {
running = true;
run();
} else if(e.which == 119) {
running = true;
run();
} else if(e.which == 115) {
running = true;
run();
}
});
(yes, if the character stops running, the running variable does go to false [not shown here] - I've already made sure the running variable works well)
runTimer = 0;
function run() {
if(runTimer == 0 && running) {
runTimer = 1;
yOffset = 80;
setTimeout(function() {
yOffset = 120;
}, 150);
setTimeout(function() { if (running) { runTimer = 0;run(); } }, 300);
}
}
If you need more information, the version that I am currently working on is available here.
I think you can simplify your code, and in fact you must in the quite probable case where you'd like to add some other characters.
To allow re-use of the animation, it's better to separate what is an animation (== the different steps that your character will go through), and an animation state (== in which step your character is now).
I wrote here some elements of an animation system.
So i define what is an animation step, a whole Animation (which is so far only an array of animation step), and an Animator (which holds the state, one might see it as a 'reader' of an animation).
Once you defined the animation and animators, and started the animators, you just have to call tick(time) to have the animation move on, and offset() to read the offset, which is way simpler than fighting with a bunch of setIntervals.
http://jsfiddle.net/xWwFf/
// --------------------
function AnimationStep(duration, offset) {
this.duration = duration;
this.offset = offset;
// you might add : image index, rotation, ....
}
// --------------------
function Animation(animationSteps) {
this.steps = animationSteps; // Array of AnimationStep
}
// define a read-only length property
Object.defineProperty(Animation.prototype, 'length', {
get: function () {
return this.steps.length
}
});
// --------------------
function Animator() {
this.currentAnimation = null;
this.step = -1;
this.running = false;
this.remainingTime = 0; // remaining time in current step;
}
Animator.prototype.startAnim = function (newAnim, firstStep) {
this.currentAnimation = newAnim;
this.step = firstStep || 0;
this.remainingTime = newAnim.steps[this.step].duration;
this.running = true;
}
Animator.prototype.tick = function (dt) {
// do nothing if no animation ongoing.
if (!this.running) return;
this.remainingTime -= dt;
// 'eat' as many frames as required to have a >0 remaining time
while (this.remainingTime <= 0) {
this.step++;
if (this.step == this.currentAnimation.length) this.step = 0;
this.remainingTime += this.currentAnimation.steps[this.step].duration;
}
};
Animator.prototype.offset = function () {
return this.currentAnimation.steps[this.step].offset;
}
// ______________________________
// example
var bounceAnim = [];
bounceAnim.push(new AnimationStep(200, 10));
bounceAnim.push(new AnimationStep(180, 20));
bounceAnim.push(new AnimationStep(150, 30));
bounceAnim.push(new AnimationStep(300, 40));
bounceAnim.push(new AnimationStep(320, 45));
bounceAnim.push(new AnimationStep(200, 40));
bounceAnim.push(new AnimationStep(120, 30));
bounceAnim.push(new AnimationStep(100, 20));
var anim1 = new Animation(bounceAnim);
var animator1 = new Animator();
var animator2 = new Animator();
animator1.startAnim(anim1);
animator2.startAnim(anim1, 3);
// in action :
var ctx = document.getElementById('cv').getContext('2d');
function drawScene() {
ctx.fillStyle = 'hsl(200,60%, 65%)';
ctx.fillRect(0, 0, 600, 200);
ctx.fillStyle = 'hsl(90,60%,75%)';
ctx.fillRect(0, 200, 600, 200);
ctx.fillStyle = 'hsl(10,60%,75%)';
ctx.fillRect(200, 200 + animator1.offset(), 22, 22);
ctx.fillStyle = 'hsl(40,60%,75%)';
ctx.fillRect(400, 200 + animator2.offset(), 22, 22);
animator1.tick(20);
animator2.tick(20);
}
setInterval(drawScene, 20);

Categories