Code:
window.onload = function() {
var a = document.getElementById("q");
var b = 1;
function tri() {
a.style.width = "100px";
b++
if (b == 3) {
b--
}
return b;
}
function un() {
a.style.width = "40px"
if (b == 2) {
b--
}
};
if (b == 1) {
a.addEventListener("click", tri);
};
if (b == 2) {
a.addEventListener("click", un)
};
};
#q {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="q"></div>
I don't know why but my code is not working. Is it possible to add two event listeners in one element? If yes, then please explain how. I tried a lot, but it's not working.
Your code is only adding one listener to the DIV. It's testing the value of b when the page is loaded, and adds the tri function as a listener. It never performs the addEventListener code again when the value of b changes.
You can add multiple event listeners to an element, but there's no need to do that in this case. Just write one event listener that checks a variable. To alternate the action, the function simply inverts the value of the variable.
window.onload = function() {
var a = document.getElementById("q");
var small = true; // Is the DIV small or big?
function change() {
if (small) { // If it's small, make it big
a.style.width = "100px";
} else { // Otherwise, make it small
a.style.width = "40px";
}
small = !small; // invert the value of the variable
}
a.addEventListener("click", change)
};
#q {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="q"></div>
your program is stuck on the first function. you enter as 1, and you get stuck on three. I debugged your program into a tragic story. I call it lost to 3. click on the square for the tragedy to unfold.
var square = document.getElementById("q");
var b = 0;
function triun() {
if (b === 0) {
square.style.width = "100px";
b=1;
}
else if (b === 1) {
square.style.width = "40px"
b=0;
};
}
square.addEventListener("click", triun)
#q {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="q"></div>
window.onload = function() {
var a = document.getElementById("q");
var b = 1;
function tri() {
console.log('I want to be 1 but I am fleeting, forever to be two, click once more for my story'+ b +'unfold')
a.style.width = "100px";
b++;
console.log(b,' wowe is me, am I 2 or am I 3. All I know, is I will be a tragedy of the click handler that will always fire before the comming of the un')
if (b == 3) {
b--
console.log('I am lost to enter as 3, never will I ever be that 1, lost in time to that fading binary dream I once was but am now', b);
}
return b;
}
function un() {
console.log(b)
a.style.width = "40px"
if (b == 2) {
b--
}
};
if (b == 1) {
console.log('I am that first "if", that very first time you dared to dream, what might have been had "un" been here',b )
a.addEventListener("click", tri);
};
if (b == 2) {
console.log('I am that poor un, I will never be, because 2 will never visit me ');
a.addEventListener("click", un)
};
};
#q {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="q"></div>
Related
My goal I want to run loop that decrements a global variable stepwise in n ms (for Example: 200ms) time intervals.
Thanks in advance!
What i already tried
I tried to use ascy await. But in combination with css transition i run in an infinite loop (In codepen.io). But here in SO you will see that it starts not running smoothly if you keep pressing arrow up.
const procentage = document.querySelector(".procentage");
const green = engine.querySelector(".green");
let number = 0;
let decrementing = false;
window.addEventListener('keydown', (e) => {
e = e || window.event;
e.preventDefault();
if (e.keyCode == '38') {
console.log("accelerate");
actionHandler( number++ );
decrementing = false;
downLoop();
}
});
function actionHandler(num) {
procentage.innerHTML = num;
const str = num + "%"
green.style.width = str;
procentage.innerHTML = str;
}
window.addEventListener('keyup', (e) => {
e = e || window.event;
e.preventDefault();
if (e.keyCode == '38') {
console.log("decelerate");
decrementing = true;
downLoop();
}
});
async function downLoop() {
if (! decrementing) {
return false
};
const timer = ms => new Promise(res => setTimeout(res, ms));
while (number > 1) {
// how to decrement ever 200ms???
actionHandler( number-- );
await timer(200)
}
}
#engine {
background-color:black;
height: 50px;
position: relative;
}
p {
text-align: center;
}
.green {
background:green;
height: 50px;
width:0%;
transition: width 0.2s;
text-align:center;
}
.procentage {
position:absolute;
top: 50%;
left: 50%;
transform: translate(0%,-50%);
color: white;
fon-weight: bold;
font-size:28px;
}
<div id="engine">
<div><span class="procentage">0</span></div>
<div class="green"></div>
</div>
<p>press arrow Up</p>
Whenever you animate, you shouldn't rely on setInterval or setTimeout, because that means that you will update "somewhere after X milliseconds" which will often end up in the middle of a screen repaint, and will therefor cause janky animation.
Instead, you should use RequestAnimationFrame which does a calculation before every repaint. So if you got a monitor with a framerate of 60 Hz, that means that you will do 60 repaints every second. For each repaint, check if enough time have passed since the last update (shouldTriggerUpdate() below) and then check if you should update the number.
I also added the class KeyHandler to keep track of which keys that have been pressed.
I got sloppy at the end and just added a decrement as an "else" of the if statement. You will figure something out when you get there when you want to set up more keys to be pressed.
You shouldn't use KeyboardEvent.keyCode, but instead KeyboardEvent.code.
const procentage = document.querySelector(".procentage");
const green = engine.querySelector(".green");
let number = 0;
let speed = 200 // ms
let lastUpdated = 0; // ms
let animationId = 0; // use later on to pause the animation
class KeyHandler {
ArrowLeft = false
ArrowUp = false
ArrowRight = false
ArrowDown = false
#setKey(code, value) { // private method
if (typeof this[code] != undefined) {
this[code] = value;
}
}
set pressedKey(code) {
this.#setKey(code, true);
}
set releasedKey(code) {
this.#setKey(code, false);
}
}
let keyHandler = new KeyHandler();
window.addEventListener('keydown', (e) => {
e = e || window.event;
e.preventDefault();
keyHandler.pressedKey = e.code;
});
window.addEventListener('keyup', (e) => {
e.preventDefault();
keyHandler.releasedKey = e.code
});
function actionHandler(num) {
const str = num + "%"
green.style.width = str;
procentage.innerHTML = str;
}
function shouldTriggerUpdate(timeInMillis) {
let difference = timeInMillis - lastUpdated;
return difference >= speed;
}
function planeAnimation() {
let timeInMillis = new Date().getTime();
if (shouldTriggerUpdate(timeInMillis)) {
lastUpdated = timeInMillis;
if (keyHandler.ArrowUp) {
actionHandler(++number)
} else if (number > 0) {
actionHandler(--number)
}
}
animationId = requestAnimationFrame(planeAnimation)
}
animationId = requestAnimationFrame(planeAnimation);
#engine {
background-color: black;
height: 50px;
position: relative;
}
p {
text-align: center;
}
.green {
background: green;
height: 50px;
width: 0%;
transition: width 0.2s;
text-align: center;
}
.procentage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(0%, -50%);
color: white;
fon-weight: bold;
font-size: 28px;
}
<div id="engine">
<div><span class="procentage">0</span></div>
<div class="green"></div>
</div>
<p>press arrow up</p>
From the above comments ...
"Instead of incrementing each time the number value push a new async timer function, set to 200 msec delay but not immediately triggered, into an array. Create an async generator from it and iterate over the latter via the for-await...of statement where one could decrement number again." – Peter Seliger
"#PeterSeliger Hi Peter! Thank you for your comment. Can you make a small example please?" – Maik Lowrey
And here the requested demonstration.
function createWait(delay) {
return async function wait () {
let settle;
const promise = new Promise((resolve) => { settle = resolve;});
setTimeout(settle, delay, { delay, state: 'ok' });
return promise;
};
}
async function* getWaitIterables(list) {
let wait;
while (wait = list.shift()) {
yield wait();
}
}
// demo for ...
// - creating an async `wait` function
// or a list of such kind.
// - creating an async generator from
// a list of async `wait` functions.
// - iterating an async generator of
// async `wait` functions.
const waitingList = [ // const waitingList = [];
2000, // waitingList.push(createWait(2000));
1000, // waitingList.push(createWait(1000));
3000, // waitingList.push(createWait(3000));
].map(createWait); // - The OP of cause needs to push into.
let number = 3; // - The incremented `number` value e.g. ... 3.
(async () => {
for await (const { delay, state } of getWaitIterables(waitingList)) {
--number;
console.log({ number, delay, state });
}
})();
console.log('... running ...', { number });
.as-console-wrapper { min-height: 100%!important; top: 0; }
I have 9 boxes in my html.
There is a value, id called 'lifepoint'.
There is a mouse-click function: click once & decrease one life point. This code is completed.
function decrementlife() {
var element = document.getElementById('lifepoint');
var value = element.innerHTML;
--value;
console.log(value);
document.getElementById('lifepoint').innerHTML = value;
if(value <= 0) { alert("Game Over!")};
}
Also, there is a css style, called 'crackbox'.
.crackbox {
position: relative;
background: linear-gradient(0deg, black, rgb(120, 120, 120));
width: 12vh;
height: 12vh;
border-radius: 30%;
margin: 5px;
}
I want to change all box class from 'box' to 'crackbox' if life point is zero. Therefore, all box style can be 'crackbox'.
The below code is fail...
$(document).ready(function () {
$(".box").each(function() {
document.getElementById('lifepoint').innerHTML = value;
if(value <= 0) {
".box".toggleClass('crackbox')
};
})
});
Instead of using document ready, call another function from decrement life if the value turns 0. I am writing the code for your help.
function decrementlife() {
var element = document.getElementById('lifepoint');
var value = element.innerHTML;
--value;
console.log(value);
document.getElementById('lifepoint').innerHTML = value;
if(value <= 0) { changeClass(); alert("Game Over!")};
}
function changeClass(){
$('.box').addClass('crackbox').removeClass('box');
}
Hope, it helps!!
The simplest way would be to use querySelectorAll and loop through the elements:
for(let i = 0, list = document.querySelectorAll(".box"); i < list.length; i++)
{
list[i].classList.toggle('crackbox');
}
Or shorter ES6 version:
[...document.querySelectorAll(".box")].forEach(el => el.classList.toggle('crackbox'))
I am trying to make me character moving left and up and I think jump() and slideLeft()
functions are working properly and the problem is in the controller(e) function (else if (e.KeyCode===37)) . The first function is avaible but it isn't able to acces the second conditon function. Also, I would want to make the grid solid after I will make an slideRight() similar function ,so if my character is jumping on it, the platform would sustain the square . Has anyone any ideea for either of my questions ?
Code snippet:
var square = document.querySelector('.square');
var grid = document.querySelector('.grid');
var bottom = 0;
let isJumping = false;
let isGoingLeft = false;
var newBottom;
let left = 0;
let leftTimerId;
function jump() {
if (isJumping) return
let timerUpId = setInterval(function() {
if (bottom > 250) {
clearInterval(timerUpId);
let timerDownId = setInterval(function() {
if (bottom < 0) {
clearInterval(timerDownId);
isJumping = false;
}
bottom -= 5;
square.style.bottom = bottom + 'px';
}, 20)
}
isJumping = true;
bottom += 30;
square.style.bottom = bottom + 'px';
}, 20)
}
function slideLeft() {
console.log('da');
isGoingLeft = true;
leftTimerId = setInterval(function() {
left -= 5;
square.style.left = left + 'px';
}, 20)
}
function controller(e) {
if (e.keyCode === 32)
jump();
else if (e.KeyCode === 37)
slideLeft();
}
document.addEventListener('keydown', controller);
.grid {
position: absolute;
background-color: chartreuse;
height: 20px;
width: 500px;
bottom: 100px;
left: 100px;
}
.square {
position: absolute;
background-color: darkblue;
height: 100px;
width: 100px;
bottom: 0px;
left: 150px;
}
`
<div class="grid"></div>
<div class="square"></div>
EDIT:
There is a typo:
The second time you've written KeyCode
function controller(e) {
if(e.keyCode===32) {
jump();
}
else if(e.keyCode===37) {
slideLeft();
}
}
I don't really understand what you mean by the second part of your question. If you want a character to have the ability to jump on a square, you'll have to implement a collision detection. Something like this:
if ( isNotOnGround() ) {
fall()
}
I'm attempting to create something that makes a button only work once. In order to do so, I created an if loop. In that if loop, I put it to a function called myFunction and then set a variable, button, to 0 (the if loop only runs if button is =2. It will not run in the first place. What am I doing wrong?
I've already attempted to recreate the variable(saying var button once out of the loop and then saying it again within).
function getRndInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var button = 2;
var x = 0
function ins() {
function removeElement(elementId) {
// Removes an element from the document
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
x = getRndInteger(0, window.innerWidth)
alert(x);
}
function button() {
if (button === 2) {
alert("k")
myFunction();
button = 0;
} else {}
}
function myFunction() {
var para = document.createElement("SPAN");
para.style.position = "absolute";
x = getRndInteger(0, (window.innerWidth - 60))
para.style.left = x + "px"
var p = getRndInteger(0, (window.innerHeight - 60))
para.style.top = p + "px"
para.style.display = "inline-block;"
para.style.height = "50px"
para.style.width = "50px"
para.style.backgroundColor = "red"
para.style.borderRadius = "50px"
para.style.border = "1px solid black"
para.style.animation = "1s a linear"
para.id = "a"
para.onclick = myFunction
document.getElementById("myDIV").appendChild(para);
}
#keyframes a {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
button {
background-color: #010417;
border-radius: 10px;
border: 4px solid white;
color: white;
padding: 10px 26px;
font-size: 20px;
}
<div id="myDIV"></div>
<center>
<button id="button" onClick="button();">Start</button>
</center>
EDIT: Ignore the delete function, doesn't mean anything
The issue with this code is that your event handler function, and the flag (that changes value between 2 and 0) are both named 'button'. Javascript is a relatively accommodating language, so this kind of dual declaration might not throw error right away, but it will obviously cause unexpected behaviour.
Looking at your code:
var button = 2;
function button() {
if (button === 2) {
alert("k")
myFunction();
button = 0;
} else {}
}
In this case (depending on the JS engine), button either refers to the function or the number. If it's the number, then type error will be thrown when button is clicked. Since the code will try to call the number like a function.
If it's a function, then the button === 2 comparison will always be false, and the (empty) else block will get executed. Either way you wouldn't get the expected behavior. You can simply change the variable name to something else, and it should work.
Please note that, as someone pointed out in comments, you should prefer adding disabled attribute to the button over this logic. Unless the aim is to do something other than blocking multiple clicks of the button.
I'm making a 2-D platformer style game with an HTML5 canvas. In it the character can jump and move side-to-side using the arrow keys, it works fine except for one problem. When I jump and move to the side at the same time the sprite goes up and doesn't move to the side. Only when it's coming down it moves properly. Is there a way to fix it? I've done research on other "move sprite diagonally" questions, but according to my code; when I let go of the 'up' key the sprite should move to the side, right? Take a look at my code and see what you think...
**note: act as if I've already defined the variables, because I have
window.addEventListener("keydown", checkKeyPressed, false);
//^don't proceed if you don't know what this means^
function checkKeyPressed(e) {
if (e.keyCode == "38" && jumpTime == 0) {
//checks if 'up' key is pressed then initiates the 'jump' sequence
refreshIntervalId = setInterval(jumpUp, 5);//calls the jump function
setTimeout(stopRefresh, 500);//sets time until character stops jumping
jumpCal();//temporarily disables jumping, and therefore a double-jump
}else if (e.keyCode == "37") {
//checks if 'left' key is pressed then moves sprite to the side
charX = charX - 8;//piece 1,
a = a - 8;//2,
c = c - 8;//and 3
}else if (e.keyCode == "39") {
//same thing, except to the right...
charX = charX + 8;
a = a + 8;
c = c + 8;
}
}
function jumpUp() {
charY = charY - 5;//moves up pieces 1,
b = b - 5;//2,
d = d - 5;//and 3, since the sprite is composed of three images
}
function stopRefresh() {
clearInterval(refreshIntervalId);
//stops the character from jumping
}
function jumpCal() {
jumpTime = 1;
setTimeout(jumpRes, 1750);
//times out the jumping action
}
function jumpRes() {
jumpTime = 0;
//resets the jumping action
}
function gravityControl() {
if (charY <= platformDetect) {
//checks if touching platform then moves all pieces down
charY = charY + 3;//piece 1
b = b + 3;//piece 2
d = d + 3;//piece 3
//this function is called multiple times in an unspecified piece of code, so no, I did not make an error here
}
}
function detectPlatform() {
platformDetect = 160;
//I've added this function because there will be platforms later in the game
}
Did you understand my code? Did I leave anything out? Was it too sloppy? If you have any suggestions not related to the question feel free to add it to the comments, I will accept any gladly.
Back to the topic on hand, was my code right? Because when I tap the 'up' key then let go and hold down on the 'right' key, my character's trajectory is as follows:
Step 1:
^
|
|
|
|
|
|
|
**Goes up fine, but doesn't move to side, as expected
Step 2:
|_
|_
|_
|_
|
|_
|
\ /
**Comes down and moves to side like it should
Can you help me please? If you didn't understand any part of my explanation I will accept criticism in the comments, after all I do want to become better.
_ _
|#| |#|
/_
---___ ___---
---_______---
**thnx in advance!!!
I didn't understand your code easily, I decided to write something from scratch, hope it can help. You might be interested in this answer as well: https://gamedev.stackexchange.com/a/29618/34073, and the related demo: http://jsfiddle.net/LyM87/.
// ex: if pressed[39] == true, walk to the right
var pressed = [];
// keyboard mapping
var keys = {
JUMP: 38,
RIGHT: 39,
LEFT: 37
};
// states of the black pixel
var pixor = {
el: $('#pixor'),
isJumping: false,
x: 10,
y: 0,
vy: 0,
vx: 0
}
// record user keystrokes
$(document).on('keydown keyup', function (e) {
pressed[e.which] = e.type === 'keydown';
e.preventDefault();
});
// classical game loop: update, render, redo after 1/60 sec
function loop () {
update();
render();
setTimeout(loop, 17);
}
// updates the states of the black pixel
function update () {
// vertical moves
if (!pixor.isJumping && pressed[keys.JUMP]) {
pixor.isJumping = true;
pixor.vy = 10;
}
if (pixor.isJumping) {
pixor.y += pixor.vy;
if (pixor.vy >= 0 && pixor.vy <= 0.5) {
pixor.vy = -0.5;
}
if (pixor.vy > 0) {
pixor.vy /= 1.25;
}
else {
pixor.vy *= 1.25;
}
if (pixor.y <= 0) {
pixor.isJumping = false;
pixor.y = 0;
pixor.vy = 0;
}
}
// horizontal moves
if (pressed[keys.RIGHT]) {
pixor.vx = 5;
}
else if (pressed[keys.LEFT]) {
pixor.vx = -5;
}
else {
pixor.vx = 0;
}
pixor.x += pixor.vx;
}
// repaints the screen based on the states of the black pixel
function render () {
pixor.el.css({
bottom: pixor.y,
left: pixor.x
});
}
body {
overflow: hidden;
}
#pixor {
position: absolute;
width: 40px;
height: 40px;
bottom: 0px;
left: 10px;
background: black;
}
#calltoaction {
position: absolute;
top: 0; right: 0;
bottom: 0; left: 0;
background: rgba(0,0,0,.5);
color: white;
text-align: center;
vertical-align: middle;
font: bold 24px Arial;
}
#calltoaction:after {
content: " ";
height: 100%;
display: inline-block;
vertical-align: middle;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pixor"></div>
<div id="calltoaction" onclick="$(this).remove();loop()">
Click here to start, then use UP, LEFT and RIGHT.
</div>
Since I don't have the full code, I can't be sure, but where you have else if (e.keyCode == "37") the else keyword is preventing moving side to side while holding jump.
Additionally, I recommend having a constant loop that handles movement rather than keypress event.
window.addEventListener("keydown", checkKeyPressed, false);
window.addEventListener("keyup", keyUp, false);
var jumpStarted = false;
var moveLeft = false;
var moveRight = false;
setInterval(function(){
if(leftDown === true)
//move Left
else if(rightDown === true)
//move Left
if(jumpStarted)
//Jump code
}, 10);
function checkKeyPressed(e) {
if (e.keyCode == "38" && jumpTime == 0) {
jumpStarted = true;
}if (e.keyCode == "37") {
moveLeft = true;
}else if (e.keyCode == "39") {
moveRight = true;
}
}
function keyUp(e){
if (e.keyCode == "37") {
moveLeft = false;
}else if (e.keyCode == "39") {
moveRight = false;
}
}
The benefit to this is that you move the entire time the key is down, not just when you press it. It also groups relative code together.