Generate projectiles within a game periodically

I've created a game that features a main character and enemy soldiers who shoot back. I'm facing an issue where only one enemy soldier shoots at intervals, even though I initially used setInterval for both of them. Any suggestions on how to fix this problem would be greatly appreciated!

            function enemies() {
        if (enemy_soldiers.length == 0) {
            level += 0.2;
            for (var i = 0; i<(1 + Math.floor(Math.round(level))); i++) {
                var gx = 1450
                var gy = getRandom(430, 630);
                enemy_soldiers.push({
                    x: gx,
                    y: gy,
                    l: gl,
                    d: getRandom(350, 600),
                    shooting: false,
                    interval: setInterval (function() {enemy.shooting = true;},fire_rate),
                    shoot: function() {
                        enemy_bullets.push({
                            x: enemy.x+40,
                            y: enemy.y+87,
                            vel: 10,
                    });
                    }
                });
            }
        }
        var enemy;
        gctx.clearRect(0, 0, 1400, 800);
        for (var i in enemy_soldiers) {
            enemy = enemy_soldiers[i];
            drawenemy(enemy.x, enemy.y, enemy.l);
            //ai
            if (distance(enemy.x, enemy.y, cx, cy) >= enemy.d && enemy.x>cx) {
                enemy.x-=vel;
            }
            else if (distance(enemy.x, enemy.y, cx, cy) >= enemy.d && enemy.x<cx) {
                enemy.x+=vel;
            }
            if (distance(enemy.x, enemy.y, cx, cy) <= 600) {
                if (enemy.shooting == true) {
                    enemy.shoot(enemy.x,enemy.y);
                    enemy.shooting = false;
                }
                gbctx.clearRect(0, 0, 1400, 800);
                for (var j in enemy_bullets) {
                    enemy_bullet = enemy_bullets[j];
                    enemy_bullet.x -= enemy_bullet.vel;
                if (enemy_bullet.x > 1400 || enemy_bullet.x < -5 || enemy_bullet.y > 800 || enemy_bullet.y < -5) {
                    enemy_bullets.splice(j,1);
                }
                drawEnemyBullet(enemy_bullet.x, enemy_bullet.y);
            }
        }
    }}

Answer №1

This method utilizes the Date.now() function to retrieve the current time in milliseconds. Each enemy is able to determine their next firing time independently, allowing for varying shot intervals.

A graphic has been included to visualize when enemies are firing, but it can be easily modified to use raycasting or projectile particle spawning instead.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}

canvas {
position: absolute;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
border: solid 1px white;
border-radius: 1px;
}
</style>
</head>

<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">

// Enemy constructor
function Enemy(x,y) {
this.x = x;
this.y = y;
this.isFiring = false;
this.fireDelay = (500 + Math.random() * 500) | 0; // Time between shots
this.lastFired = Date.now(); // Last time at which the enemy fired
}

/*
Enemy prototype
(All objects created using the constructor share these properties)

E.G.

var e1 = new Enemy(10,0);
var e2 = new Enemy(20,0);

if (e1.__proto__ === e2.__proto__) {
console.log("Match");
}

prints "Match"
*/
Enemy.prototype = {
WIDTH: 10,
HEIGHT: 20,

FIRE_DURATION: 100, // Amount of time 'fire' graphic is shown
FIRE_WIDTH: 10,
FIRE_HEIGHT: 10,

update: function() {
// If current time - time when I last fired > the amount of time between shots
if (Date.now() - this.lastFired > this.fireDelay) {
this.lastFired = Date.now();
this.isFiring = true;

// If you were using projectile particles, this is where you would spawn one
}

if (this.isFiring && Date.now() - this.lastFired > this.FIRE_DURATION) {
this.isFiring = false;
}
},

render: function(ctx) {
ctx.fillStyle = "darkred";
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.beginPath();

ctx.rect(
this.x,
this.y,
this.WIDTH,
this.HEIGHT
);

ctx.fill();
ctx.stroke();

if (this.isFiring) {
ctx.fillStyle = "yellow";
ctx.strokeStyle = "darkyellow";
ctx.lineWidth = 3;
ctx.beginPath();

ctx.rect(
this.x + this.WIDTH,
this.y + this.HEIGHT * 0.5 - this.FIRE_HEIGHT * 0.5,
this.FIRE_WIDTH,
this.FIRE_HEIGHT
);

ctx.fill();
ctx.stroke();
}
}
};

var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var ctx = null;

var enemies = [];

window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx = canvas.getContext("2d");

for (var i = 0; i < 5; ++i) {
enemies[i] = new Enemy(20 + i * 3,10 + i * 30);
}

loop();
}

function loop() {
// Update
for (var i = 0; i < enemies.length; ++i) {
enemies[i].update();
}

// Render
ctx.fillStyle = "gray";
ctx.fillRect(0,0,canvasWidth,canvasHeight);

for (var i = 0; i < enemies.length; ++i) {
enemies[i].render(ctx);
}

//
requestAnimationFrame(loop);
}

</script>
</body>
</html>

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

The issue with Node.js router failing to process delete requests

My Node.js router is handling all methods well except for the DELETE method. I can't figure out why the delete request does not reach the router. The AJAX request seems to be functioning correctly. AJAX request: function ajaxHelper(url, onSuccessAr ...

The supertest request body cannot be found

Testing my express server POST endpoint using supertest has been a challenge for me. Although everything works perfectly in postman, I encountered an issue when trying to pass body parameters into the test. It seems like the body parameters are not being p ...

Acquiring JSON-formatted data through the oracledb npm package in conjunction with Node.js

I am currently working with oracledb npm to request data in JSON format and here is the select block example I am using: const block = 'BEGIN ' + ':response := PK.getData(:param);' + 'END;'; The block is ...

Make sure to execute the fire directive only when ng-repeat has completed

Currently, I am utilizing owl carousel with data being fetched through an Ajax call. Once the data populates the HTML content using ng-repeat, I need to trigger the directive that initializes the owl carousel. How can I achieve this? One approach I consid ...

Adjusting ES2015 Map to accommodate the expected functionality

Exploring the capabilities of ES2015 Maps has been quite exciting, as I'm starting to see its potential. However, I've encountered a use case that has me stumped on whether Maps can handle it. Let's take a look at my class: class A { ...

Managing various dropdown select options in pure JavaScript

Consider the select element provided below: <select multiple="multiple"> <option value="car">car</option> <option value="scooter">scooter</option> <option value="bus">bus</option> </select> I ...

Is there a way to change the format of the date "Wed Jan 01 2020 00:00:00 GMT+0530 (India Standard Time)" to JAN 01, 2020 in JavaScript?

I am currently retrieving the date from the database in the format of Wed Jan 01 2020 00:00:00 GMT+0530 (India Standard Time), but I would like it to be displayed in the JAN O1,2020 format without using moment.js. Is there any alternative approach to ach ...

The function 'find' cannot be invoked on an undefined object

I'm currently working on implementing objects in my jQuery code. So far, I have the following: var options = { ul: $(this).find('.carousel'), li: options.ul.find('li') } The li property is causing an error - Cannot call meth ...

Should one consider using requirejs to enhance individual pages instead of relying solely on vanilla JavaScript applications?

I have a question regarding the practical use of RequireJS. After learning about purely JavaScript-driven web pages, I have been enhancing individually rendered views (often provided by a PHP Framework) with AngularJS to add more functionality. However, m ...

How to manage form submissions in Vue.js using inputs within child components

I'm working on a parent component that acts as a form. This form consists of multiple child components, each containing input fields. <template> <div class="form"> <generalData v-model="input" /> <textAreas v- ...

Sort and incorporate elements by multiple strings present in an array

Looking to filter and include strings in an array by matching them with items in another array? Here is a sample code snippet that filters based on a single string: const filteredString = `${this.filter}`.toLowerCase(); this.filteredCampaigns = this. ...

What is the best way to fetch HTML content using JavaScript?

I needed to incorporate JavaScript for fetching HTML code. I structured the HTML code in the following manner; <html> <div id="tesingCode"> <h1>Title</h1> <p>testOfCodetestOfCodetestOfCodetestOfCode</p> </div ...

What is the best way to create an animated, step-by-step drawing of an SVG path

I am interested in creating an animated progressive drawing of a line using CSS with SVG/Canvas and JS. You can view the specific line I want to draw here <svg width="640" height="480" xmlns="http://www.w3.org/2000/svg"> <!-- Created with cust ...

Information displays instantly in the initial milliseconds

When developing dynamic web pages with Nuxt, I encountered an issue in the pages directory where a file named _url.vue is located. The contents of this file are as follows: <template lang="pug"> div component( v-for= ...

What is preventing the function from successfully compiling text from various files that are uploaded using the HTML5 file reader into an array?

My current challenge involves attempting to upload two text files using the HTML 5 file reader. While I can successfully get the files into an array, encountering difficulty arises when trying to return that array from the function. One solution could be ...

Using "array_agg" in a "having clause" with Sequelize

I am facing a particular scenario with my database setup. I have three tables named computers, flags, and computerFlags that establish relationships between them. The structure of the computerFlags table is as follows: computerName | flagId computer1 | ...

Deliver real-time updates directly to clients using Django Channels and Websockets

Currently, I am working on a page that needs to display live-updating data to the client. The rest of the website is constructed using Django framework, so my approach involves utilizing Channels for this purpose. The data that needs to be showcased is st ...

Custom palette in Material UI design palette allows users to create

Hey there everyone! I've been working on a website using ReactJS and Material UI, starting with this cool template. One thing I'm trying to do is change the color of the TextField when it's focused. Right now it's blue, but I want it ...

Prisma Hack: excluding properties in type generation

EDIT hiding fields in the TypeScript definitions may pose a hidden danger: inaccessible fields during development with intellisense, but accidentally sending the full object with "hidden" fields in a response could potentially expose sensitive data. While ...

Utilizing PHP and MySQL to link an array of values to a single value in a database record

I am currently working on parsing a JSON file using PHP and then inserting the data into a MySQL database. One of the tables that I am dealing with is the Attendance table, which associates a person's ID ($constid) with the ID of the meeting they are ...