How can I reverse the direction of an element on a canvas? - javascript

I tried to make it so that when my 'Player' reaches a jumpDistance of 50, it falls down, so he makes a small ' jump ' .
The code might not be exactly "clean" at this point, but I'm getting started with Javascript.
I made the player jump by using a for loop with a delay. I tried to make him go down the same way, but this didn't work out the way I planned.
Fiddle demo
** NOTE : Press space to start!
<!DOCTYPE html>
<html>
<style>
#canvas {
background-color: rgba(177, 177, 177, 1);
}
</style>
<body>
<div>
<p id="jumpDistance"></p>
<p id="jumpDirection"></p>
</div>
<canvas id="canvas" width="800" height="400"></canvas>
<script>
var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');
var xPos = 150;
var yPos = 375;
var jumpDistance = 0;
function spelerObj() {
canvas.width=canvas.width;
context.rect(xPos, yPos, 25, 25);
context.stroke();
context.fillStyle = "#FF0000";
context.fillRect(xPos, yPos, 25, 25);
}
function jump(e) { //Here the player jumps, with a loop that calculates it's jump-distance.
//alert(e.keyCode);
if (e.keyCode == 32) {//
function upLoop() {
setTimeout(function () {
if(jumpDistance < 50) {
yPos -= 1;
jumpDistance++;
upLoop();
spelerObj();
document.getElementById("jumpDistance").innerHTML = jumpDistance.toString();
}
}, 1)
}
upLoop();
spelerObj();
}
}
document.onkeydown = jump;
</script>
</body>
</html>

You'd need a downloop that you can switch to at the top of the jump:
function upLoop() {
setTimeout(function() {
if (jumpDistance < 50) {
yPos -= 1;
jumpDistance++;
upLoop();
} else {
downLoop();
}
spelerObj();
document.getElementById("jumpDistance").innerHTML = jumpDistance.toString();
}, 1)
}
function downLoop() {
setTimeout(function() {
if (jumpDistance > 0) {
yPos += 1;
jumpDistance--;
downLoop();
}
spelerObj();
document.getElementById("jumpDistance").innerHTML = jumpDistance.toString();
}, 1)
}
Demo 1
You could also vary the timeout duration to add a pseudo-gravity effect.
Demo 2

Related

Drawing Rectangles With For Loops

I don't understand why this isn't drawing, it might be a stupid mistake, although I have gone through all the code multiple times, but if it is, I apologize, I am trying to make the snake game and the snake won't draw. I wan't the array cells to keep track of where all of the cells are, and to do this you have to unshift and pop them accordingly.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var unit = 16;
var snakeone = {
maxcells: 3,
cellsx: [],
cellsy: [],
x: 20 * unit,
y: 20 * unit,
};
var apple = {
x: 20 * unit,
y: 20 * unit,
};
var color = 'white';
function setup() {
}
function style() {}
function clear() {
ctx.clearRect(0, 0, 656, 656);
}
document.onkeydown = keydown;
document.onkeyup = keyup;
function keydown(e) {
ctrl(e.code, true);
}
function keyup(e) {
ctrl(e.code, false);
}
function ctrl(code, bool) {
if(code == 37) {
snakeone.a = bool;
}
if(code == 38) {
snakeone.w = bool;
}
if(code == 39) {
snakeone.d = bool;
}
if(code == 40) {
snakeone.s = bool;
}
}
function move() {
if(snakeone.a === true) {
snakeone.x -= 1;
}
if(snakeone.w === true) {
snakeone.y -= 1;
}
if(snakeone.d === true) {
snakeone.x += 1;
}
if(snakeone.s === true) {
snakeone.y += 1;
}
}
function shift() {
if(snakeone.cellsx.length < snakeone.maxcells) {
snakeone.cellsx.unshift(snakeone.x);
snakeone.cellsy.unshift(snakeone.y);
}
}
function draw() {
for(i = 0; i < snakeone.maxcells; i++) {
ctx.fillStyle = color;
ctx.fillRect(snakeone.cellsx[i] + 1, snakeone.cellsy[i] + 1, unit - 2, unit - 2);
}
}
function pop() {
if(snakeone.cellsx.length > snakeone.maxcells) {
snakeone.cellsx.pop();
snakeone.cellsy.pop();
}
}
function timer() {
clear();
move();
shift();
draw();
pop();
}
setup();
setInterval(timer, 150);
body {
background-color: black;
text-align: center;
}
#canvas {
border: 2px solid white;
}
<html>
<head>
<title>
New Tab
</title>
<link href="snake.css" rel="stylesheet" type="text/css">
</head>
<body>
<canvas id="canvas"height="656" width="656"></canvas>
<script src="snake.js"></script>
</body>
</html>
`
Here's a working version of the code. I've made a few changes and simplified things a bit, but it might be helpful to you.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var unit = 16;
var color = "limegreen";
var snake = [];
var snakeone = {
x: 20 * unit,
y: 20 * unit
};
function clear() {
ctx.clearRect(0, 0, 400, 400);
}
function keyup(e) {
const code = e.keyCode;
const lastSegment = snake[snake.length - 1];
if (code == 37) {
// left arrow
snake.push({
...lastSegment,
x: lastSegment.x - 10
});
}
if (code == 38) {
// up arrow
snake.push({
...lastSegment,
y: lastSegment.y - 10
});
}
if (code == 39) {
// right arrow
snake.push({
...lastSegment,
x: lastSegment.x + 10
});
}
if (code == 40) {
// down arrow
snake.push({
...lastSegment,
y: lastSegment.y + 10
});
}
}
function draw() {
ctx.fillStyle = color;
snake.forEach(segment => {
ctx.fillRect(segment.x, segment.y, unit - 2, unit - 2);
});
}
function timer() {
clear();
draw();
}
document.onkeyup = keyup;
snake.push(snakeone);
setInterval(timer, 150);
body {
background-color: black;
text-align: center;
}
#canvas {
border: 2px solid white;
}
<html>
<head>
<title>
New Tab
</title>
</head>
<body>
<canvas id="canvas" height="400" width="400"></canvas>
</body>
</html>

location.reload(); is delayed on remote server (locally works instantly)

Everything works like a charm locally when red block hits black block, it refreshes instantly (coming to start position). I can't figure out why the website doesn't refresh after collision (game over) on the remote server. Sometimes it needs few seconds to react or it requires moving the player position.
Found a tip to replace
location.reload(true);
with
location.href = location.href;
but it doesn't work at all in my case.
Fiddle to inspect my code: https://jsfiddle.net/32o8q5gz/1/
Remote host: https://stacho163.000webhostapp.com/
HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Obulis 2</title>
<link rel="stylesheet" type="text/css" href="gameStyle.css">
</head>
<body>
<div class="game-content">
<h1>Obulis 2</h1>
<canvas id="game-window">
</canvas>
</div>
<script src="gameScript.js"></script>
</body>
</html>
CSS code:
* {
margin: 0;
padding: 0;
}
body {
background-color: #000;
}
.game-content {
position: relative;
width: 100vw;
height: 100vh;
}
h1 {
position: absolute;
color: red;
font-size: 50px;
left: 50%;
top: 1.5%;
transform: translate(-50%);
}
#game-window {
position: absolute;
width: 90vw;
height: 90vw * 16/9;
top: 50%;
left: 50%;
transform: translate(-50%, -46%);
background-color: gray;
}
JS code:
// js game script //
let canvas = document.getElementById('game-window');
let ctx = canvas.getContext('2d');
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
let left = false;
let up = false;
let right = false;
let down = false;
let player = {
size: 50,
posX: (canvas.width / 2) - 25,
posY: (canvas.height / 2) - 25,
speed: 5
}
let obstacle = {
size: Math.round((Math.random() * 100) + 50),
posX: Math.round((Math.random() * 1200) + 50),
posY: -50,
speed: Math.round((Math.random() * 10) + 1)
}
function drawPlayer() {
ctx.fillStyle = "red";
ctx.fillRect(player.posX, player.posY, player.size, player.size);
}
function drawObstacle() {
ctx.fillStyle = "#000";
ctx.fillRect(obstacle.posX, obstacle.posY, obstacle.size, obstacle.size);
obstacle.posY += obstacle.speed;
}
function darknessCollision() {
if (player.posX < 0 ||
player.posY < 0 ||
player.posX > canvas.width - player.size ||
player.posY > canvas.height - player.size) {
location.reload(true);
}
}
function obstacleCollision() {
if (player.posX <= obstacle.posX + obstacle.size &&
player.posY <= obstacle.posY + obstacle.size &&
player.posX + player.size >= obstacle.posX &&
player.posY + player.size >= obstacle.posY) {
location.href = location.href;
}
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function move() {
if (left) {
player.posX -= player.speed;
}
if (up) {
player.posY -= player.speed;
}
if (right) {
player.posX += player.speed;
}
if (down) {
player.posY += player.speed;
}
}
document.onkeydown = function (e) {
if (e.keyCode == 37) left = true;
if (e.keyCode == 38) up = true;
if (e.keyCode == 39) right = true;
if (e.keyCode == 40) down = true;
e.preventDefault();
}
document.onkeyup = function (e) {
if (e.keyCode == 37) left = false;
if (e.keyCode == 38) up = false;
if (e.keyCode == 39) right = false;
if (e.keyCode == 40) down = false;
e.preventDefault();
}
setInterval (function game() {
clearCanvas();
drawObstacle();
drawPlayer();
darknessCollision();
obstacleCollision();
move();
}, 10);
Thanks in advance for your tips! :)
This is a completely normal behavior.
When you refresh a local website, the only delay is the time spent reading the website again from your computer’s memory, and even that can get much faster for many reasons.
However, refreshing an online website, usually (if not cached), requires a “round trip time” from your computer to the server, which is sometimes costing few seconds.
If refreshing the page is for the sake of getting new updates, unfortunately there is no way to reduce the refreshing time. But, if you just need to start the website one more time, you can either use JavaScript history methods as mentioned, or have a JavaScript function that returns you to the first state without the need to refresh at all.
Hope this helps.
Two other options:
history.go(0);
And:
window.location.href = window.location.href;

Javascript how to make object appear over a background image

Hello I am trying to create a guitar hero sort of program with red circles appearing over a violin image when the corresponding key presses are pressed but I can't seem to be able to make them appear over the image even if I write the code after the canvas code. Can someone help me with this? I would also like to make the circles disappear after a while but timeout won't do the trick here because the image is not one color only for example changing the red circles to the background color after a while. How would i do this?
<html>
<head>
<title>Violin Hero</title>
<canvas id="myCanvas" width="1024" height="768"></canvas>
<style>
body {
background-image: url("violin.jpg");
background-size: 2500px 1300px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="1024" height="768"></canvas>
<img id="bow" src="bow.jpg" style="display:none;" />
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
window.addEventListener("keydown", soundPlay);
function fillRed() {
ctx.fillStyle = "red";
ctx.fill();
}
function keyQ(){
ctx.beginPath();
ctx.arc(1200, 300, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
function keyW(){
ctx.beginPath();
ctx.arc(300, 300, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
function keyE(){
ctx.beginPath();
ctx.arc(900, 500, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
function keyR(){
ctx.beginPath();
ctx.arc(950, 100, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
//var x = event.keyCode;
//<input type="text" onkeydown="pressedKey(event)">
function soundPlay(event) {
var x = event.keyCode;
if (x == 27) { // 27 is the ESC key
alert ("You pressed the Escape key!");
}
else if (x == 81) {
keyQ();
var sound = new Audio('1.mp3');
sound.play();
setTimeout(fillRed, 200);
}
else if (event.keyCode == 87) {
keyW();
var sound = new Audio("2.mp3");
sound.play();
setTimeout(fillRed, 200);
}
else if (event.keyCode == 69) {
keyE();
var sound = new Audio("3.mp3");
sound.play();
setTimeout(fillRed, 200);
}
else if (event.keyCode == 82) {
keyR();
var sound = new Audio("4.mp3");
sound.play();
setTimeout(fillRed, 200);
}
}
</script>
</body>
</html>
To bring something in front of images/To bring something always behind elements, one should use z-index.
Make a css for background image like this:
#backgroundImg{
position: absolute;
left: 0px;
top: 0px;
z-index: -1;
}
In this way, the background image will always be behind. Please check this or this for more details.
For your second question, I suggest you should make another post and keep this question focused on one issue only.
I've created a simple Plunkr example for you on how to achieve this kind of functionality in JS.
Click s, a or any other to show a red dot.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body id='mybody'>
<img id='violin' src='http://cdn.shopify.com/s/files/1/0704/3831/products/Antoni_Debut_Violin_Outfit_3677b25a-7618-46f7-9313-6080c2a51e27_grande.jpg?v=1444483336'>
<script>
document.addEventListener('keydown', (event) => {
console.log(event);
if (event.key.toLowerCase() === 's') {
showRedDot(110, 420);
} else if (event.key.toLowerCase() === 'a') {
showRedDot(150, 350);
} else {
showRedDot(200, 300);
}
});
var showRedDot = (top, left) => {
var oldDot = document.getElementById('redDot');
if (oldDot) {
oldDot.remove();
}
var dot = document.createElement('DIV');
dot.id = 'redDot';
dot.style.width = '10px';
dot.style.height = '10px';
dot.style.position = 'absolute';
dot.style.borderRadius = '100%';
dot.style.background = 'red';
dot.style.top = top + 'px';
dot.style.left = left + 'px';
document.getElementById('mybody').appendChild(dot);
};
</script>
</body>
</html>
Here's a working Plunkr

Javascript Key Pressed + setTimeout()

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.

How to move an image depending on mouse location using JS?

I would like an image to move to the left if the mouse is to the left of the screen and to the right if the mouse to the right of the screen, using javascript, here is the code I have so far:
var dirx = 0;
var spdx = 35;
var imgLeftInt;
var imgTopInt;
var imgHeight;
var imgWidth;
var divWidth;
var divHeight;
var t;
var tempX;
var tempY;
So I'm pretty sure I'm not missing any variables...
function animBall(on) {
imgLeftInt = parseInt(document.images['logo'].style.left);
imgTopInt = parseInt(document.images['logo'].style.top);
imgHeight = parseInt(document.images['logo'].height);
imgWidth = parseInt(document.images['logo'].width);
divWidth = parseInt(document.images['container'].width);
if (tempX > 779){
dirx = 1;
}
else if(tempX < 767){
dirx = 2;
}
else {
spdx = 0;
}
So if tempX, which should be the x coordinate of the mouse location, is bigger than 779, which is the halfway point of the div tag, the image should go right. If it's less than that, it should go left, and otherwise, the speed should be zero, as in it should stay still.
if(dirx == 1){
goRight();
} else if(dirx == 2) {
goLeft();
}
}
function getMouseXY(e) {
tempX = e.clientX;
tempY = e.clientY;
}
I found hundreds of different ways to get the mouse location, but this was off W3C so I assume it works.
function goRight() {
document.images['logo'].style.left = imgLeftInt+spdx +"px";
if (imgLeftInt > (divWidth-imgWidth)){
dirx = 2;
spdx= 20;
}
}
function goLeft() {
document.images['logo'].style.left = (imgLeftInt-spdx) +"px";
if (imgLeftInt < 5){
dirx = 1;
spdx= 20;
}
}
</script>
So that's my whole script.
<div id="container" onmousemove="getMouseXY(event);" width="1546" height="423">
Start Animation Stop Animation <br />
<img src="http://qabila.tv/images/logo_old.png" style="position:absolute;left:10px;top:20px;" id="logo" />
</div>
I left the dependency on the mouse location to the very end so the animation script works fine (or at least worked, unless I broke something trying to get it to read the mouse location).
Any ideas what I'm doing wrong??
If it's any help, I've hosted the code here.
I went to your link and tried debugging your code. I get an error on line 21 because your document has no "container" image ("container" is a div).
At the start of your question, you said you wanted to know mouse position relative to center of "screen". For that, you'd probably want to use window.innerWidth instead of the width attribute that you set on your div.
Well that needed a whole load of work, anyway, I have done some of it for you and you can now see things partially working, but you will need to play with it on jsfiddle. Perhaps you can now open some specific questions regarding getting this to work.
<div id="container" width="1546" height="423"> <a id="start" href="#">Start Animation</a> <a id="stop" href="#">Stop Animation</a>
<br />
<img src="http://qabila.tv/images/logo_old.png" style="position:absolute;left:10px;top:20px;" id="logo" />
</div>
/*jslint sub: true, maxerr: 50, indent: 4, browser: true */
/*global */
(function () {
"use strict";
var start = document.getElementById("start"),
stop = document.getElementById("stop"),
container = document.getElementById("container"),
logo = document.getElementById("logo"),
dirx = 0,
spdx = 35,
imgLeftInt,
imgTopInt,
imgHeight,
imgWidth,
divWidth,
divHeight,
t,
tempX,
tempY;
function getMouseXY(e) {
tempX = e.clientX;
tempY = e.clientY;
}
function goRight() {
logo.style.left = imgLeftInt + spdx + "px";
if (imgLeftInt > (divWidth - imgWidth)) {
dirx = 2;
spdx = 20;
}
}
function goLeft() {
logo.style.left = (imgLeftInt - spdx) + "px";
if (imgLeftInt < 5) {
dirx = 1;
spdx = 20;
}
}
// attribute on unused
function animBall(on) {
imgLeftInt = parseInt(logo.style.left, 10);
imgTopInt = parseInt(logo.style.top, 10);
imgHeight = parseInt(logo.height, 10);
imgWidth = parseInt(logo.width, 10);
divWidth = parseInt(container.width, 10);
if (tempX > 779) {
dirx = 1;
} else if (tempX < 767) {
dirx = 2;
} else {
spdx = 0;
}
if (dirx === 1) {
goRight();
} else if (dirx === 2) {
goLeft();
}
}
function startAnim() {
t = setInterval(animBall, 80);
}
start.addEventListener("click", startAnim, false);
function stopAnim() {
clearInterval(t);
}
stop.addEventListener("click", stopAnim, false);
container.addEventListener("mousemove", getMouseXY, false);
}());
Why don't you usee the html5 canvas and gee.js
Here's the js fiddle result (it may take a while to load, but that's fault of jsfiddle, the script will load much faster once on your website): http://jsfiddle.net/wLCeE/7/embedded/result/
and here's the much simpler code to make it work:
var g = new GEE({
width: 500,
height: 423,
container: document.getElementById('canvas')
});
var img = new Image(); // Create new img element
img.onload = function () {
demo(g)
};
img.src = 'http://qabila.tv/images/logo_old.png'; // Set source path
function demo(g) {
var style = "left"
g.draw = function () {
if (g.mouseX > g.width / 2 && style == "left") styleRight()
else if (g.mouseX < g.width / 2 && style == "right") styleLeft()
}
function styleLeft() {
style = "left"
g.ctx.clearRect(0, 0, g.width, g.height)
g.ctx.drawImage(img, 0, 0)
}
function styleRight() {
style = "right"
g.ctx.clearRect(0, 0, g.width, g.height)
g.ctx.drawImage(img, g.width - img.width, 0)
}
}

Categories