Endless fun with a twist: Dealing with setTimeout in a Javascript

I am just starting to learn javascript and programming, so please keep that in mind.

I am working on a basic html5 javascript game where vehicles are moving down a highway towards the player (represented by canvas rectangles). Right now, I am focusing on creating the vehicle spawning and movement mechanics. My objective is to have the vehicles spawn with a consistent gap between them regardless of their speed.

My current setup works fine unless there's lag or if the speed variable is set to around four or lower. After doing some research, I suspect the issue lies with the setTimeout function not accounting for lag. Since I'm new to this, I'm unfamiliar with many functions and unable to find a solution online.

You can test a live demo of my code here. Try opening multiple tabs or causing lag-inducing processes to see the problem when setting the speed variable below 5. Any assistance would be greatly appreciated.

<!DOCTYPE html>
<html>
<body>
<canvas id="ctx" width="480" height="320" style="border:1px solid #000000;"></canvas>
<script>
        var ctx = document.getElementById("ctx").getContext("2d");

            function setIntervalX(callback, delay, repetitions) {
                var x = 0;
                var intervalID = window.setInterval(function () {
                    callback();
                    if (++x === repetitions) {
                       window.clearInterval(intervalID);
                   }
                }, delay);
            }

            var speed = 50


            function game() {
                var yAxis
                var selectType = Math.floor((Math.random()*6)+1)
                switch (selectType){
                    case 1: //semi
                    case 2:
                        yAxis = -80
                        var lane = Math.floor((Math.random()*3)+1)
                            switch (lane)
                                {
                                    case 1: //left lane
                                        setIntervalX(function () {
                                        ctx.fillStyle = "white";
                                        ctx.fillRect(200,yAxis,15,80);
                                        yAxis = yAxis + 2
                                        ctx.fillStyle = "black";
                                        ctx.fillRect(200,yAxis,15,80);
                                        }, speed, 400);
                                    break;
                                    case 2: //middle lane
                                        setIntervalX(function () {
                                        ctx.fillStyle = "white";
                                        ctx.fillRect(230,yAxis,15,80);
                                        yAxis = yAxis + 2
                                        ctx.fillStyle = "black";
                                        ctx.fillRect(230,yAxis,15,80);
                                        }, speed, 400);
                                    break;
                                    case 3: //right lane
                                        setIntervalX(function () {
                                        ctx.fillStyle = "white";
                                        ctx.fillRect(260,yAxis,15,80);
                                        yAxis = yAxis + 2
                                        ctx.fillStyle = "black";
                                        ctx.fillRect(260,yAxis,15,80);
                                        }, speed, 400);
                                    break;
                                }
                        setTimeout(function() {game()}, speed * 80) 
                    break;      
                    case 3: //bike
                        yAxis = -10
                        var lane = Math.floor((Math.random()*3)+1)
                            switch (lane)
                                {
                                    case 1: //left lane
                                        setIntervalX(function () {
                                        ctx.fillStyle = "white";
                                        ctx.fillRect(200,yAxis,10,10);
                                        yAxis = yAxis + 2
                                        ctx.fillStyle = "black";
                                        ctx.fillRect(200,yAxis,10,10);
                                        }, speed, 400);
                                    break;
                                    case 2: //middle lane
                                        setIntervalX(function () {
                                        ctx.fillStyle = "white";
                                        ctx.fillRect(230,yAxis,10,10);
                                        yAxis = yAxis + 2
                                        ctx.fillStyle = "black";
                                        ctx.fillRect(230,yAxis,10,10);
                                        }, speed, 400);
                                    break;
                                    case 3: //right lane
                                        setIntervalX(function () {
                                        ctx.fillStyle = "white";
                                        ctx.fillRect(260,yAxis,10,10);
                                        yAxis = yAxis + 2
                                        ctx.fillStyle = "black";
                                        ctx.fillRect(260,yAxis,10,10);
                                        }, speed, 400);
                                    break;
                                }
                        setTimeout(function() {game()}, speed * 45)     
                    break;  
                    case 4: //car
                    case 5:
                    case 6:
                        yAxis = -20
                        var lane = Math.floor((Math.random()*3)+1)
                        switch (lane)
                                {
                                    case 1: //left lane
                                        setIntervalX(function () {
                                        ctx.fillStyle = "white";
                                        ctx.fillRect(200,yAxis,10,20);
                                        yAxis = yAxis + 2
                                        ctx.fillStyle = "black";
                                        ctx.fillRect(200,yAxis,10,20);
                                        }, speed, 400);
                                    break;
                                    case 2: //middle lane
                                        setIntervalX(function () {
                                        ctx.fillStyle = "white";
                                        ctx.fillRect(230,yAxis,10,20);
                                        yAxis = yAxis + 2
                                        ctx.fillStyle = "black";
                                        ctx.fillRect(230,yAxis,10,20);
                                        }, speed, 400);
                                    break;
                                    case 3: //right lane
                                        setIntervalX(function () {
                                        ctx.fillStyle = "white";
                                        ctx.fillRect(260,yAxis,10,20);
                                        yAxis = yAxis + 2
                                        ctx.fillStyle = "black";
                                        ctx.fillRect(260,yAxis,10,20);
                                        }, speed, 400);
                                    break;
                                }
                        setTimeout(function() {game()}, speed * 50)         
                    break;}
                }           
            game()

    </script>

    </body>
    </html>

Answer №1

It's recommended to maintain a single primary setInterval function that handles all updates.
Don't worry about lag, it shouldn't be a problem for a project of this scale.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting the integration of Text Mask Library with Vue - issue: no export named 'default' available

I was able to implement the vanilla JavaScript version: var maskedInputController = vanillaTextMask.maskInput({ inputElement: document.querySelector('.myInput'), mask: [/\d/, /\d/, '/', /\d/, /\d/, '/ ...

Tips for loading internal JSON data using $http.get instead of using an external JSON file

I am currently facing an issue where I use a code snippet to load strings from an external json-file. While everything works fine, running the function locally triggers a 'cross origin' problem. As a solution, I attempted to input the strings dir ...

The error in React's useEffect occurs when trying to access the property 'map' of an undefined value

import { handleResponse, handleError } from "./apiUtils"; const baseUrl = process.env.REACT_APP_API_URL; export function getAllNotes() { return fetch(baseUrl + "/notes", { method: "GET", headers: { 'Accept': 'application/j ...

Modify the specified pattern with regex only if it does not appear in a particular location in the content

Our tool development heavily relies on regex for various functionalities. One key aspect involves replacing placeholders with actual values dynamically using standard JavaScript's `RegExp`. All placeholder formats are similar to this: {{key}} In mo ...

Having trouble importing NPM packages (e.g. Faker) in TypeScript?

Currently I am encountering an issue while attempting to import Faker into my project. The file structure is as follows: import * as faker from 'faker'; interface Test { FirstName: String, LastName: String } function create() { le ...

Converting timeofday to numeric values in Google Line Chart

Working on a line chart presents a challenge as the format of the line remains unchangeable: function drawChart(){ var data = new google.visualization.DataTable(); data.addColumn('timeofday','quarter'); The desire ...

Cannot confirm checkbox status in ASP.NET after retrieving data from webmethod using Jquery AJAX

Implementing Jquery ajax to call a webmethod, the webmethod interacts with the database and returns either true or false. The goal is to determine whether the checkbox should be checked or unchecked based on this boolean value. Here is the server-side cod ...

Web Audio API functions are encountering a playback issue on iOS 13.3, despite working smoothly on previous iOS versions

I have been developing an audio visualizer using the web audio API. It was functioning smoothly on PC, however, after upgrading to iOS 13.3, it no longer operates on Apple mobile devices. The root cause of this issue remains a mystery to me. The problem s ...

Personalized data based on the language within Next.js

Is there a way to customize Metadata for users based on search engine keywords? To enhance SEO performance on my website, I am working on setting up unique Metadata for the two languages my website supports: English and Portuguese. Specifically, I aim to ...

What methods can be used to obfuscate my JavaScript code within the developer console?

Currently looking for a method to hide my JavaScript code from being visible in the browser's developer console while maintaining its functionality. Alternatively, I would like to restrict it to run only on a particular website. Grateful for any insig ...

The Loading Screen Is Lagging

I hope I'm not overwhelming you with too much (or too little!) information. It's a bit tricky for me to share code when it spans multiple files like this. So, in my small project, I have my app.js server using express and ejs. There's a &qu ...

Can you tell me the meaning of this error message: "The variable 'ParsedQs' cannot be assigned to a variable of type 'string'."

Hey there, I'm facing an issue with using the search query of mongoose. I want to make a get request using a query, but it seems that it's not possible. I'm puzzled by this error as I'm currently working with version 5.10.0 of mongoose. ...

Instructions for removing a single key value pair from every object in an array and transferring it to a designated object within the same array

I need to update an array of objects by adding a key and value (e.g., age:15) to an object with the name email, while removing the age property from other objects in the array. [ { name: 'test', lname: 'last', age: 5 }, ...

Ways to retrieve the specified data in Javascript in string format

I'm facing an issue where the data I passed from a JavaScript array to a Java servlet and back to JavaScript is showing as "undefined." Check out my JavaScript code below: var buildingNumbers = []; // Let's assume the values of buildingNumbers ...

The function Angular.isArray(data) will evaluate to false when checking if the data is

Using angular's $resource to retrieve data from an API. The configuration of the angular $resource is as follows: Priorities: $resource (baseUrl + 'priorities/:priorityType/:uuid/all', {}, { query: { method: 'GET', ...

AJAX Username verification failing to validate

Working with PHP and MySQL, I created a basic form which includes a textfield for the username and a submit button. The page is named checkusername.php. Additionally, I implemented an AJAX function for handling this process. Subsequently, there is another ...

Rails-powered web application for voice over IP services

My initial project idea involved implementing VoIP functionality between a mobile app client and web browser using Rails as the back-end. However, after conducting some research, I found myself with a number of questions. Firstly, in my search, I noticed ...

React encountered an unexpected end of JSON input while streaming JSON data

Currently, I am facing a challenge with streaming a large amount of data from a NodeJS server that retrieves the data from Mongo and forwards it to React. Due to the substantial volume of data involved, my approach has been to stream it directly from the s ...

What is the proper way to invoke a function in the code-behind using JavaScript?

I need to invoke a function in the code behind from JavaScript Button : <button class = "btn btn-outline btn-danger dim" type = "button" onclick = "confirmDelete ()"> <i class = "fa fa-trash"> </i> ...

Create a regular expression that matches a combination of alphabets and spaces, but does not allow for

Can anyone provide a regular expression that allows for a combination of alphabets and spaces, but not only spaces? After searching extensively and reading numerous articles, I came across the expression /^[a-zA-Z\s]*$/, which unfortunately permits j ...