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/
Related
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.
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.
This is my code and when run instead of a black box containing my game in the centre of the screen there is just a gap and no website can seem to tell me where I went wrong:
console.log("start")
//Global functions
var canvas = document.getElementById("canva");
var canvasCon;
var snakeX = 400;
var snakeY = 300;
var direction;
var snakeSpeed = 1;
var apple = false;
var appleX;
var appleY
var snakeSize = 30;
var scoreboard = document.getElementById("score");
var Score = 0;
var trailX = new Array();
var trailY = new Array();
console.log("set global variables!")
window.onload = function(){
console.log("ran on window load function")
canvasCon = canvas.getContext('2d');
//Calls "drawing" and "move" fps times per second
var fps = 30
setInterval(function(){
move()
drawing()
},1000/fps);
}
document.addEventListener('keydown', getKey);
function getKey(event){
//gets the keycode
direction = event.keyCode;
return direction;
}
//moves the objsects
function move(){
//creates a easier to read way to check the value of getKey
var left = 37;
var up = 38;
var right = 39;
var down = 40;
//changing the position of the snake
switch(direction){
case right:
snakeX = snakeX + snakeSpeed;
break;
case left:
snakeX = snakeX - snakeSpeed;
break;
case up:
snakeY = snakeY - snakeSpeed;
break;
case down:
snakeY = snakeY + snakeSpeed;
break;
}
trail()
//checks if snake has gone off the board and then moves the snake to the other end of the board if that returns True
if(snakeX > canvas.width){
snakeX = 0
}else if(snakeX < 0){
snakeX = canvas.width
}
if(snakeY > canvas.height){
snakeY = 0
}else if(snakeY < 0){
snakeY = canvas.height
}
}
//draws everything /w updated coordinates
function drawing(){
//Backround of the Game
canvasCon.fillStyle = 'black';
canvasCon.fillRect(0,0,canvas.width,canvas.height);
//The snake
canvasCon.fillStyle = 'green';
canvasCon.fillRect(snakeX,snakeY,snakeSize,snakeSize);
//apple creation
apples()
canvasCon.fillStyle = 'red';
canvasCon.fillRect(appleX,appleY,25,25);
}
//makes the apples work
function apples(){
if(collision()){
Score += 1
console.log(Score)
scoreboard.innerHTML = "<b>Score: "+Score+"<b>"
apple = false
}
if(apple == false){
apple = true
appleX = Math.floor(Math.random() * (canvas.width - 50));
appleY = Math.floor(Math.random() * (canvas.height - 50));
}
}
function collision(){
var distX = Math.abs(appleX - snakeX-snakeSize/2);
var distY = Math.abs(appleY - snakeY-snakeSize/2);
if (distX <= (snakeSize/2) && distY <= (snakeSize/2)) { return true; }
}
function trail(){
//adds X and Y coordinates to their respective lists
trailX.push(snakeX)
trailY.push(snakeY)
//makes sure the lists are the right length
while(trailX.length > Score){
var index = trailX.indexOf(0);
trailX.splice(index, 1);
}
while(trailY.length > Score){
var index = trailY.indexOf(0);
trailY.splice(index, 1);
}
if(trailY.length != trailX.length){
console.log("trailY != trailX")
}
for(i= trailX.length-1; i<=0; i--){
canvasCon.fillStyle = 'yellow';
canvasCon.fillRect(trailX[i],trailY[i],25,25);
}
}
<title>SNAKE!!</title>
<body>
<p style="text-align:center; text-color:red"><b>Hope you Enjoy Ma GREAT GAME!!</b></p>
<br/><br/><br/>
<div style="width:800px; margin:0 auto;">
<canvas id=canva width="800" height="600"></canvas>
<br/>
<p id="score">Score: </p>
</div>
</body>
whenever the page gets reloaded even on jsfiddle.net it crashes.
plz help I have no idea what i did wrong!
First rule of JS - if it is stuck, you probably have an endless loop.
And indeed You have an endless loop with your final for:
for(i= trailX.length-1; i<=0; i--){
canvasCon.fillStyle = 'yellow';
canvasCon.fillRect(trailX[i],trailY[i],25,25);
}
i<=0
If i start with 0 and goes down by 1 each iteration, it will always be less or equal to 0 so the end condition will never be met.
I'm making a game, and I'd like to know how to make a character move more smoothly. The character can already move, but it moves really choppy; when you click the arrow key, it instantly appears 10 pixels ahead. I'd like it to move smoothly so it doesn't just "appear" 10 pixels ahead of itself.
Here is the Code:
document.onkeydown = checkKey;
var canvas;
var ctx;
var up;
var down;
var left;
var right;
var bobX = 200;
var bobY = 200;
var bobWidth = 30;
var bobHeight = 30;
window.onload = function() {
canvas = document.getElementById("gameCanvas");
ctx = canvas.getContext("2d");
var fps = 200; // frames per second
setInterval(function() {
updateAll();
drawAll();
}, 1000/fps)
};
var drawAll = function() {
// draw background
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// draw bob
ctx.fillStyle = "red";
ctx.fillRect(bobX, bobY, bobWidth, bobHeight);
};
var updateAll = function() {
if (up == true) {
up = false;
}
if (down == true) {
bobY += 1;
down = false;
}
if (left == true) {
bobX -= 1;
left = false;
}
if (right == true) {
bobX += 1;
right = false;
}
};
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '38') {
up = true;
}
else if (e.keyCode == '40') {
down = true;
}
else if (e.keyCode == '37') {
left = true;
}
else if (e.keyCode == '39') {
right = true;
}
}
I tried doing moving it by one pixel every keypress, but it moves very slowly when I do that.
Your screen has maximum refreshrate, usually 60 fps. Some screens can get up to 120fps, but that's a rather rare case.
So what is happening here:
var fps = 200; // frames per second
setInterval(function() {
updateAll();
drawAll();
}, 1000/fps)
};
The canvas gets redrawn and the position gets updated at a rate which your screen can't catch up with. You simply can't see that your character only moves 1 pixel instead of 10 pixel.
Solution would be to use requestAnimationFrame instead. Which invokes when the screen refreshes:
function animate() {
requestAnimationFrame(animate);
updateAll();
drawAll();
};
animate();
I am currently developing a Javascript game (almost everything is based on a tutorial yet, so I am not worried of sharing the code).
The problem is, I can't get the character to jump after pressing the Space button. Please, can someone look at the code and help me?
// EDIT: Sorry for lack of information I provided. The thing is - code is written, the game is in the state, that the character is animated (=is running) and the backgrounds are moving. Yesterday, I tried to implement some basic controls, such as jump by pressing spacebar. The thing is, the player won't jump at all, and browser console is not giving me any error statements.
Character is defined as Player on line 5. and 321. in the code provided below.
The jumping is defined in the following examples:
Pressing the Space button
var KEY_CODES = {
32: 'space'
};
var KEY_STATUS = {};
for (var code in KEY_CODES) {
if (KEY_CODES.hasOwnProperty(code)) {
KEY_STATUS[KEY_CODES[code]] = false;
}
}
document.onkeydown = function(e) {
var keyCode = (e.keyCode) ? e.keyCode : e.charCode;
if (KEY_CODES[keyCode]) {
e.preventDefault();
KEY_STATUS[KEY_CODES[keyCode]] = true;
}
};
document.onkeyup = function(e) {
var keyCode = (e.keyCode) ? e.keyCode : e.charCode;
if (KEY_CODES[keyCode]) {
e.preventDefault();
KEY_STATUS[KEY_CODES[keyCode]] = false;
}
};
Other jump information (please, read the comments in the code)
this.update = function() {
// jump, if the characted is NOT currently jumping or falling
if (KEY_STATUS.space && this.dy === 0 && !this.isJumping) {
this.isJumping = true;
this.dy = this.jumpDy;
jumpCounter = 12;
assetLoader.sounds.jump.play();
}
// longer jump if the space bar is pressed down longer
if (KEY_STATUS.space && jumpCounter) {
this.dy = this.jumpDy;
}
jumpCounter = Math.max(jumpCounter-1, 0);
this.advance();
// gravity
if (this.isFalling || this.isJumping) {
this.dy += this.gravity;
}
// change animation is-falling
if (this.dy > 0) {
this.anim = this.fallAnim;
}
// change animation is-jumping
else if (this.dy < 0) {
this.anim = this.jumpAnim;
}
else {
this.anim = this.walkAnim;
}
this.anim.update();
};
/**
* Update the Sprite's position by the player's speed
*/
this.update = function() {
this.dx = -player.speed;
this.advance();
};
/**
* Draw the current player's frame
*/
this.draw = function() {
this.anim.draw(this.x, this.y);
};
}
Player.prototype = Object.create(Vector.prototype);
Everything seems just fine to me, but the player just won't move. :(
Any help?
If you are curious about the full code, go here: http://pastebin.com/DHZKhBMT
EDIT2:
Thank you very much for your replies so far.
I have moved the RequestAnimFrame to the end of the function - will keep that in mind, thanks.
I have also implemented the simple jumping script Ashish provided above, but the character is still not jumping.
This is what it looks like now:
/** JUMP KEYS DEFINITION **/
$(document).keypress(function(e){
if(e.which==32){
$('Player.prototype').css({'top':"0px"});
}
setTimeout(function(){
$('Player.prototype').css({'top':"200px"});
},350);
});
/** DEFINING CHARACTER **/
function Player(x, y) {
this.dy = 0;
this.gravity = 1;
this.speed = 6;
this.jumpDy = -10;
this.isJumping = false;
this.width = 60;
this.height = 96;
this.sheet = new SpriteSheet('imgs/normal_walk.png', this.width, this.height);
this.walkAnim = new Animation(this.sheet, 4, 0, 11);
this.jumpAnim = new Animation(this.sheet, 4, 3, 3);
this.fallAnim = new Animation(this.sheet, 4, 3, 3);
this.anim = this.walkAnim;
Vector.call(this, x, y, 0, this.dy);
var jumpCounter = 0; // Maximalna dlzka drzania tlacidla skakania
}
Player.prototype = Object.create(Vector.prototype);
Where am I wrong?
I've tried in http://jsfiddle.net/Ykge9/1/
and you have an infinite loop in animate, the requestAnimFrame should be at the end of the function:
/**
* Loop cykly hry
*/
function animate() {
background.draw();
for (i = 0; i < ground.length; i++) {
ground[i].x -= player.speed;
ctx.drawImage(assetLoader.imgs.grass, ground[i].x, ground[i].y+250);
}
if (ground[0].x <= -platformWidth) {
ground.shift();
ground.push({'x': ground[ground.length-1].x + platformWidth, 'y': platformHeight});
}
player.anim.update();
player.anim.draw(64, 260);
requestAnimFrame( animate );
}