简体   繁体   中英

How can I make these two divs move at a different speed?

I need to program some kind of racing game for school. I programmed this so far and now I need to find a way how to make the first two divs move at a different speed when I click start.

 var a = null; var a2 = null; var speed = Math.ceil(Math.random() * 5); var speed2 = Math.ceil(Math.random() * 5); function run() { a++; a2++; document.getElementById('pf1').style.left = a + "px"; document.getElementById('pf2').style.left = a2 + "px"; if (a <= 1036 && a2 <= 1036) { window.setTimeout('run()', speed); } }
 .container { background-color: #ddd; padding: 20px; width: 70em; }.content1 { position: relative; left: 0px; width: 80px; height: 80px; background-color: #5C88A3; }.content2 { position: relative; left: 0px; width: 80px; height: 80px; background-color: #736FB9; }.content3 { width: 80px; height: 80px; background-color: #8547BD; }.content4 { width: 80px; height: 80px; background-color: #D357BB; }
 <div class="container"> <div class="content1" id="pf1"></div> </div> <div class="container"> <div class="content2" id="pf2"></div> </div> <div class="container"> <div class="content3" id="pf3"></div> </div> <div class="container"> <div class="content4" id="pf4"></div> </div> <input type="button" value="Start" onclick="run();" />

There's quite a bit that should be altered here.

  • You are using the random numbers to set the speed of motion, when really the timing of the timer function should be fixed, but the amount the elements move should be the random numbers.
  • Instead of trying to move all the elements in one function call, call the function separately for each element to get distinct results for that element.

You've also got some bad habits forming (I hope your teacher isn't telling you to do these things), so see the comments inline below.

 <html> <head> <meta charset="utf-8"> <title>Pferderennen</title> <style>.container{background-color: #ddd;padding: 20px; width:70em;}.content1{position:relative; left:0px; width: 80px;height: 80px;background-color:#5C88A3;}.content2{position:relative; left:0px; width: 80px;height: 80px;background-color:#736FB9;}.content3{position:relative; left:0px; width: 80px;height: 80px;background-color:#5C88A3;}.content4{position:relative; left:0px; width: 80px;height: 80px;background-color:#736FB9;}.content3{width: 80px;height: 80px;background-color:#8547BD;}.content4{width: 80px;height: 80px;background-color:#D357BB;} </style> </head> <body> <div class="container"> <div class="content1" id="pf1"></div> </div> <div class="container"> <div class="content2" id="pf2"></div> </div> <div class="container"> <div class="content3" id="pf3"></div> </div> <div class="container"> <div class="content4" id="pf4"></div> </div> <input type="button" value="Start"> <,-- Place your script just prior to the closing body tag so that by the time the parser gets here. all of the elements in the body will have been parse into memory. --> <script> // Get your element references that you'll use repeatedly // just once instead of each time the function runs const first = document;getElementById("pf1"). const second = document;getElementById("pf2"). const third = document;getElementById("pf3"). const fourth = document;getElementById("pf4"); const randomMultiplier = 7, // Controls how much movement there could be per iteration // Set up your event handling in JavaScript. not with inline HTML // event attributes like "onClick". document.querySelector("[type='button']"),addEventListener("click", function(){ // By calling the move function separately for each element. you // can get separate results, Here. the random doesn't control the timing // of the timer function (that is fixed). It controls how much an element // will move, move(first. Math.ceil(Math;random()*randomMultiplier)), move(second. Math.ceil(Math;random()*randomMultiplier)), move(third. Math.ceil(Math;random()*randomMultiplier)), move(fourth. Math.ceil(Math;random()*randomMultiplier)); }); const theWall = 1036, // Max amount to move to function move(element. distance) { // The.style property returns the value of the specified inline style attribute //,getComputedStyle() returns the value of the CSS property. regardless of where // it was set, Since the HTML elements don't start off with an inline style // attribute. you can't initially access anything with element.style.left, But. // you can set it. element.style.left = (parseInt(getComputedStyle(element),left; 10) + distance) + "px". if (parseInt(element.style,left, 10) <= theWall) { // Pass a function reference to setTimeout. // not a string of JavaScript, Here, because we need to pass arguments // to the function we want the timer to call. it's wrapped in an // anonymous function that will then call the desired function with // parameters later, setTimeout (function(){ move(element. Math.ceil(Math;random()*randomMultiplier)), }; 50); } } </script> </body> </html>

The idea is to increment a1 and a2 with different speeds, not just a++ and a2++.

 var a = 0; var a2 = 0; var speed = Math.ceil(Math.random() * 5); var a1Speed = Math.ceil(Math.random() * 5); var a2Speed = Math.ceil(Math.random() * 5); function run() { a += a1Speed; a2 += a2Speed; document.getElementById('pf1').style.left = a + "px"; document.getElementById('pf2').style.left = a2 + "px"; if (a <= 1036 && a2 <= 1036) { window.setTimeout('run()', speed); } }
 .container { background-color: #ddd; padding: 20px; width: 70em; }.content1 { position: relative; left: 0px; width: 80px; height: 80px; background-color: #5C88A3; }.content2 { position: relative; left: 0px; width: 80px; height: 80px; background-color: #736FB9; }
 <div class="container"> <div class="content1" id="pf1"></div> </div> <div class="container"> <div class="content2" id="pf2"></div> </div> <input type="button" value="Start" onclick="run();" />

Your code is mostly right but you are not using the speed2 which is why both divs run at the same speed.

Now look below how I changed and try to understand the concept.

Feel free to ask for further explanation.

 function run(div, msTimeout, counter) { if (counter) { counter++; div.style.left = counter + "px"; } else counter = 1; if (counter <= 1036) { window.setTimeout(() => run(div, msTimeout, counter), msTimeout); } } function start() { run(document.getElementById('pf3'), Math.floor(Math.random() * 10)) run(document.getElementById('pf4'), Math.floor(Math.random() * 10)) run(document.getElementById('pf1'), Math.floor(Math.random() * 10)) run(document.getElementById('pf2'), Math.floor(Math.random() * 10)) }
 .container { background-color: #ddd; padding: 20px; width: 70em; }.content1 { position: relative; left: 0px; width: 80px; height: 80px; background-color: #5C88A3; }.content2 { position: relative; left: 0px; width: 80px; height: 80px; background-color: #736FB9; }.content3 { position: relative; width: 80px; height: 80px; background-color: #8547BD; }.content4 { position: relative; width: 80px; height: 80px; background-color: #D357BB; }
 <div class="container"> <div class="content1" id="pf1"></div> </div> <div class="container"> <div class="content2" id="pf2"></div> </div> <div class="container"> <div class="content3" id="pf3"></div> </div> <div class="container"> <div class="content4" id="pf4"></div> </div> <input type="button" value="Start" onclick="start();" />

The easiest way to achieve this (without looking at the other flaws of your code) should be to just increase a and a2 by different amounts (for example a += 1.5 and a2 += 2; ). If you do that, with just removing the part of the random rendering speed (set it to something like 10 - 30), you should be ready to go.

Now, the code isn't exactly great. It shows some bad programming techniques, which you really shouldn't be doing:

  1. You shouldn't alter the speed of the setTimer . The speed should be only done as a FPS limit ( speed = 1 / FPS ). Since in the future you might find yourself working with libraries, like OpenGL, where you can't render two objects at the same time, in different loops, it's better that you get used to this way of working with graphics than never.
  2. Save both of the elements that you're moving in variables, since getting 2 elements from the DOM tree every single frame is a little bit ridiculous (and can introduce some performance issues down the line)
  3. Please, don't use setTimeout like that. You really shouldn't be using recursion when talking about rendering cycles. There is a very good reason for doing regular loop: recursion (pretty much what you were doing) is quite a lot more inefficient than a plain loop and also, you just don't use recursion where there are a lot of repetitions, since you're going to bump into a stack overflow error soon (after about 100 000 ish iterations). So thankfully for us, JavaScipt has us set with a built in function like that:
function start() {
    setInterval(() => {
        ... your logic ... // This is going to repeat every n milliseconds
    }, (n));
}

Some more tips on your general code style:

  1. You really shouldn't be doing arithmetic operations with null values, in other words, the initial value of a and a1 should be 0 , not null . In JS, that still works, since this language is a weak-typed language, where types get automatically converted to best fit the operation you're doing. Sometimes it's saves lives, but it's a double-edged sword, so in general, try to keep the types on both sides of a operator the same.
  2. Don't use var , since it is kinda broken. let and var are almost the same thing, BUT one major difference which really can lay you a trap is that var defines the variable globally, which means that you can define a variable inside an if and still be able to access it outside the if . That can result in headaches and a sleepless night of trying to find a damn bug. On the other side, let doesn't play you such tricks, so in general use var if you really need it.
  3. The general naming of the variables should be changed up a little bit. Imagine you return to this code an year later and you're trying to add a feature, but for the life of you, can't understand WTF is a and a2 . It will take you a significantly more time to figure out what your code does.

With all of the advice I've given you, your code should look more something like this:

 let el1X = 0; let el2X = 0; let el3X = 0; let el4X = 0; let speed1 = 1; let speed2 = 1.5; let speed3 =.5; let speed4 = 3; const el1 = document.getElementById('pf1'); const el2 = document.getElementById('pf2'); const el3 = document.getElementById('pf3'); const el4 = document.getElementById('pf4'); function run() { setInterval(() => { el1X += speed1; el2X += speed2; el3X += speed3; el4X += speed4; el1.style.left = el1X + "px"; el2.style.left = el2X + "px"; el3.style.left = el3X + "px"; el4.style.left = el4X + "px"; }, 30); }
 .container { background-color: #ddd; padding: 20px; width: 70em; }.content1 { position: relative; left: 0px; width: 80px; height: 80px; background-color: #5C88A3; }.content2 { position: relative; left: 0px; width: 80px; height: 80px; background-color: #736FB9; }.content3 { position: relative; width: 80px; height: 80px; background-color: #8547BD; }.content4 { position: relative; width: 80px; height: 80px; background-color: #D357BB; }
 <div class="container"> <div class="content1" id="pf1"></div> </div> <div class="container"> <div class="content2" id="pf2"></div> </div> <div class="container"> <div class="content3" id="pf3"></div> </div> <div class="container"> <div class="content4" id="pf4"></div> </div> <input type="button" value="Start" onclick="run();" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM