started to learn a bit javascript and I ran into a mission to get a "ball" bigger and bigger when I am cliking it( the ball starts from 100 and grow by 50 each click). so when it's getting too 400 its should shrink its size by 50 till the ball gets again to 100 and then he grow.
so thats the code:
function onBall2Click() {
var ball2 = document.querySelector('.ball2');
if(ball2Size === 400) {
ball2Size -= 50;
} else if(ball2Size) {
ball2Size += 50;
}
ball2.innerText = ball2Size;
ball2.style.width = ball2Size;
ball2.style.height = ball2Size;
}
ball2Size defined to 100.
now the ball is getting to 400 when I click again it is getting to 350 but then it getting to 400 again since 350 isnt === to 400. I am frustrated I tried to play with it like an hour and got stucked thats why I posted it here..
would like if someone could give me an useful solution.
thank you!
Add a variable that holds the direction. direction = "growing" or direction = "shrinking". Or even simpler, a boolean (true=growing, false=shrinking).
let isGrowing = true;
const ball2 = document.querySelector('.ball2');
function onBall2Click() {
if (ball2Size === 400) {
isGrowing = false
} else if (ball2Size === 100) {
isGrowing = true
}
if (isGrowing) {
ball2Size += 50;
} else {
ball2Size -= 50;
}
ball2.innerText = ball2Size;
ball2.style.width = ball2Size;
ball2.style.height = ball2Size;
}
The code behave like this because once you shrink it first time, it's not 400 anymore, so it goes into ELSE and grow it again.
To achieve that you need to have a variable in outside scope of your function that will hold information if the ball is growing or not.
Ideally that should not be defined in the Global scope (as it would pollute global scope that is anti-pattern), however I can't see the rest of your code so I don't know into what closure the isGrowing variable should be placed.
var ball2SizeStep = 50;
function onBall2Click() {
var ball2 = document.querySelector('.ball2');
if(ball2Size === 400) {
ball2SizeStep = -50;
} else if(ball2Size === 100) {
ball2SizeStep = 50;
}
ball2Size += ball2SizeStep;
ball2.innerText = ball2Size;
ball2.style.width = ball2Size;
ball2.style.height = ball2Size;
}
Related
I am trying to make a little square on my screen "jump". It was all going smoothly until I tried to add a "fallSpeed" variable that would change the speed it's falling at slowly to imitate actual gravity (yes I understand it's not the most realistic representation of gravity but I'm just trying to keep it simple.) All of a sudden with this variable in place about half the time my code will work but then half the time it will get all glitchy and freak out (yes I am aware that that will happen if you hold or spam the space bar but that's not what I'm talking about, it happens just when you press the space bar.) What could be making it so inconsistent and weird, theres no randomization of anything?
<script>
document.addEventListener("keydown", function(event) {
jump(event);
})
var posX = 500;
var posY = 500;
var fallSpeed = 3;
function moveUp() {
if (posY > 250) {
posY -= 3;
document.getElementById('player').style.marginTop = posY + "px"
fallSpeed += 0.005;
setTimeout(() => {moveUp();}, 1);
}
else {
return true;
}
}
function moveDown() {
if (posY < 500) {
posY += fallSpeed;
document.getElementById('player').style.marginTop = posY + "px"
fallSpeed += 0.02;
setTimeout(() => {moveDown();}, 1);
}
else {
fallSpeed = 3;
return;
}
}
function jump(event) {
if (event.key === " ") {
moveUp();
setTimeout(() => {if (moveUp) {
moveDown();
}}, 399)
}
}
</script>
I just figured it out! I needed to change the delay in the second setTimeout() because it was too short because the block fell faster now.
I have been trying to make a simple "smoothscroll" function using location.href that triggers on the mousewheel. The main problem is that the EventListener(wheel..) gets a bunch of inputs over the span of ca. 0,9 seconds which keeps triggering the function. "I only want the function to run once".
In the code below I have tried to remove the eventlistener as soon as the function runs, which actually kinda work, the problem is that I want it to be added again, hence the timed function at the bottom. This also kinda work but I dont want to wait a full second to be able to scroll and if I set it to anything lover the function will run multiple times.
I've also tried doing it with conditions "the commented out true or false variables" which works perfectly aslong as you are only scrolling up and down but you cant scroll twice or down twice.
window.addEventListener('wheel', scrolltest, true);
function scrolltest(event) {
window.removeEventListener('wheel', scrolltest, true);
i = event.deltaY;
console.log(i);
if (webstate == 0) {
if (i < 0 && !upexecuted) {
// upexecuted = true;
location.href = "#forside";
// downexecuted = false;
} else if (i > 0 && !downexecuted) {
// downexecuted = true;
location.href = "#underside";
// upexecuted = false;
}
}
setTimeout(function(){ window.addEventListener('wheel', scrolltest, true); }, 1000);
}
I had hoped there was a way to stop the wheel from constantly produce inputs over atleast 0.9 seconds.
"note: don't know if it can help in some way but when the browser is not clicked (the active window) the wheel will registre only one value a nice 100 for down and -100 for up"
What you're trying to do is called "debouncing" or "throttling". (Those aren't exactly the same thing, but you can look up the difference in case it's going to matter to you.) Functions for this are built into libraries like lodash, but if using a library like that is too non-vanilla for what you have in mind, you can always define your own debounce function: https://www.geeksforgeeks.org/debouncing-in-javascript/
You might also want to look into requestanimationframe.
a different approach
okey after fiddeling with this for just about 2 days i got fustrated and started over. no matter what i did the browsers integrated "glide-scroll" was messing up the event trigger. anyway i decided to animate the scrolling myself and honestly it works better than i had imagined: here is my code if anyone want to do this:
var body = document.getElementsByTagName("BODY")[0];
var p1 = document.getElementById('page1');
var p2 = document.getElementById('page2');
var p3 = document.getElementById('page3');
var p4 = document.getElementById('page4');
var p5 = document.getElementById('page5');
var whatpage = 1;
var snap = 50;
var i = 0;
// this part is really just to read what "page" you are on if you update the site. if you add more pages you should remember to add it here too.
window.onload = setcurrentpage;
function setcurrentpage() {
if (window.pageYOffset == p1.offsetTop) {
whatpage = 1;
} else if (window.pageYOffset == p2.offsetTop) {
whatpage = 2;
} else if (window.pageYOffset == p3.offsetTop) {
whatpage = 3;
} else if (window.pageYOffset == p4.offsetTop) {
whatpage = 4;
} else if (window.pageYOffset == p5.offsetTop) {
whatpage = 5;
}
}
// this code is designet to automaticly work with any "id" you have aslong as you give it a variable called p"number" fx p10 as seen above.
function smoothscroll() {
var whatpagenext = whatpage+1;
var whatpageprev = whatpage-1;
var currentpage = window['p'+whatpage];
var nextpage = window['p'+whatpagenext];
var prevpage = window['p'+whatpageprev];
console.log(currentpage);
if (window.pageYOffset > currentpage.offsetTop + snap && window.pageYOffset < nextpage.offsetTop - snap){
body.style.overflowY = "hidden";
i++
window.scrollTo(0, window.pageYOffset+i);
if (window.pageYOffset <= nextpage.offsetTop + snap && window.pageYOffset >= nextpage.offsetTop - snap) {
i=0;
window.scrollTo(0, nextpage.offsetTop);
whatpage += 1;
body.style.overflowY = "initial";
}
} else if (window.pageYOffset < currentpage.offsetTop - snap && window.pageYOffset > prevpage.offsetTop + snap){
body.style.overflowY = "hidden";
i--
window.scrollTo(0, window.pageYOffset+i);
if (window.pageYOffset >= prevpage.offsetTop - snap && window.pageYOffset <= prevpage.offsetTop + snap) {
i=0;
window.scrollTo(0, prevpage.offsetTop);
whatpage -= 1;
body.style.overflowY = "initial";
}
}
}
to remove the scrollbar completely just add this to your stylesheet:
::-webkit-scrollbar {
width: 0px;
background: transparent;
}
I have a function, to make a div-Box "jump". The function works the first time, but after that I get the error "Uncaught TypeError: jump is not a function" after it gets used once. Can someone please explain why it doesn't work?
already = false;
function jump() {
if (already == false) { //So he can't jump 2 times in a row
try {
clearInterval(t); //<--this is my gravity function, where the div-Box falls down until it hits solid ground
} catch (err) {
console.log("not activated");
}
jump = setInterval("jump2();", 200);
already = true;
}
}
}
anz = 0;
function jump2() {
//Getting coordinates of div-Boy(they work)
var step = 10;
var bottom = getBottom("itBoy");
var right = getRight("itBoy");
var top = getTop("itBoy");
var left = getLeft("itBoy");
//lets see if he hits an object
if (anz <= 100) { //<-- anz = so he cant jump higher than 100 px
if (top - step >= 0) {
var a = hittest("itBoy", "up", 10); //if div wont hit a solid object --> return -1 | else return coordinates of bordes which collide (this function works too)
if (a == -1) {
anz += step;
document.getElementById("itBoy").style.top = (top -= step) + "px";
} else {
document.getElementById(itBoy).style.top = a + "px";
clearInterval(jump); // div stops moving upwards
t = setInterval("move('down');", 50); //gravity gets Activated again
}
}
} else {
clearInterval(jump);
t = setInterval("move('down');", 50);
}
}
It's because, you're overriding the jump:
function jump(){
// ...
jump = setInterval("jump2();",200);
// ^^ give it a different name
Also, a good approach to use function inside setInterval like:
setInterval(jump2, 200); // faster
Ok, so I have a game where I have some tree objects that need to be drawn in one side or another. The problem is, even though the condition is working and the trees are being drawn, they're not following the SIDES_RATE condition, specially on Side 2, they're going to the opposite direction while in Side 1 they're almost moving straight, instead of diagonal.
This is my Tree Class:
function Tree1(side, pos_x) {
this.speed = TREE_SPEED;
this.side = side;
this.height = 107;
this.width = 49.3;
this.pos_x = pos_x;
this.pos_y = 10;
this.tree1_image = tree_images[this.side];
}
This is my Tree controller
setInterval(generateTree, TREE_SPEED * 1000);
function generateTree() {
a = (Math.round(Math.random()));
if (a == 0){
tree1_array.push(new Tree1(Math.round(Math.random()),200));
} else {
tree2_array.push(new Tree2(Math.round(Math.random()),600));
}
}
function moveTree(tree){
tree.height += ZOOM_RATE;
tree.width += ZOOM_RATE;
if (tree.side == 0){
tree.pos_x -= SIDES_RATE;
} else if (tree.side == 1) {
tree.pos_x += SIDES_RATE;
}
tree.pos_y += TREE_SPEED;
}
function treeController(){
for (i = 0; i < tree1_array.length; i++){
if (tree1_array[i].pos_y > 900){
tree1_array.splice(i,1);
} else {
moveTree(tree1_array[i]);
}
}
}
This is where I draw them:
Game.draw = function() {
for (i = 0; i < tree1_array.length; i++) {
this.context.drawImage(tree1_array[i].tree1_image,
tree1_array[i].pos_x - tree1_array[i].width/2,
tree1_array[i].pos_y - tree1_array[i].height/2,
tree1_array[i].width,
tree1_array[i].height);
}
}
I don't know what's happening for it to happen. Anything helps.
I am hoping someone might be able to look at this javascript code I have been working on for a simple old-school Mario clone.
I have pieced together what I know about canvas from several tutorials and I am not able to get the collisions with blocks or the jumping working correctly.
the jumping seems to set Mario on an infinite loop of bouncing over and over, which looks funny but is not very conducive of playing a game!
function Player() {
this.srcX = 0;
this.srcY = 0;
this.drawX = gameWidth /2;
this.drawY = 0;
this.scaleWidth = 38;
this.scaleHeight = 50;
this.width = 48;
this.height = 60;
this.speed = 10;
this.maxJump = 50;
this.velY = 0;
this.velX = 0;
this.isJumpKey = false;
this.isRightKey = false;
this.isCrouchKey = false;
this.isLeftKey = false;
this.jumping = false;
this.grounded = false;
}
Player.prototype.draw = function(){
clearPlayer();
this.checkKeys();
ctxPlayer.drawImage(
player,
this.srcX,
this.srcY,
this.width,
this.height,
this.drawX,
this.drawY,
this.scaleWidth,
this.scaleHeight);
};
Player.prototype.checkKeys = function () {
if(this.isJumpKey){
if (!this.jumping && this.grounded ) {
this.jumping = true;
this.grounded = false;
this.velY = -this.speed * 2;
}
}
if(this.isRightKey){
if (this.velX < this.speed) {
this.velX++;
}
}
if(this.isLeftKey){
if (this.velX < this.speed) {
this.velX--;
}
}
if(this.isCrouchKey){
player1.grounded = true;
player1.jumping = false;
}
};
Here is a codepen with where I am at right now: http://codepen.io/AlexBezuska/pen/ysJcI
I really appreciate any help, I will continue to search and play around with this in the meantime, but any pointers you can give, even suggestions for formatting, prototype creation etc are really appreciated (I am quite new to both canvas and prototypes)
In your checkKeyDown() and checkKeyUp() functions, you have them checking for different 'jump' keys. From checkKeyDown():
if (keyID === 74) { //spacebar
e.preventDefault();
player1.isJumpKey = true;
}
From checkKeyUp():
if (keyID === 32) { // spacebar
player1.isJumpKey = false;
e.preventDefault();
}
So checkKeyUp() isn't properly resetting player1.isJumpKey. Set them both to the same, and it works fine for me.
As a general point, it might be worth setting up an object that holds all the parameters that have multiple instances in your code. Then write them into your code by referring to this object. That way you've only got to change them in a single place:
CONSTS = {
upKeyID: 32,
etc.
}
// then later:
if (keyID === CONSTS.upKeyID) {
player1.isJumpKey = false;
e.preventDefault();
}
I figured out the collision problem, I had the x position and y position vars in the player prototype named 'drawX' and 'drawY', but in the collision detection function, they were simply 'x' and 'y', now it works: http://codepen.io/AlexBezuska/pen/ysJcI w00t!