War Battles bullet spread (SOLVED)

Hey!

I’m new to Defold, I just finished the War Battles tutorial and I try to modify and extend it a bit, for example by adding some random bullet spread to the shooting to make it less accurate. My guess is that this part of the code should be modified (correct me if I’m wrong). Could you please provide me some pointers how to implement this feature?

This is in player.script:

if self.firing then
		local angle = math.atan2(self.dir.y, self.dir.x)
		local rot = vmath.quat_rotation_z(angle)
		local props = { dir = self.dir }
		factory.create("#bulletfactory", nil, rot, props)
		print(rot, props)
		self.firing = false 
	end

Thanks in advance!

Yes, that looks about right. So you have an angle for the rocket, and now you want to add a bit of randomness to the angle to simulate spread. Ok, let’s start:

	local angle = math.atan2(self.dir.y, self.dir.x)

The angle you get from math.atan2() is in radians. We can convert to and from radians using math.rad() and math.deg():

print(math.rad(45)) -- 0.78539816339745
print(math.rad(180)) -- 3.1415926535898 (pi)
print(math.deg(0.78539816339745)) -- 45
print(math.deg(math.pi)) -- 180

You create random numbers using math.random():

math.random() -- a value between 0.0 and 1.0
math.random(100) -- a value between 0 and 100
math.random(20, 40) -- a value between 20 and 40
math.random(-20, -20) -- a value between -20 and 20

Let’s use that to create some spread!

local angle = math.atan2(self.dir.y, self.dir.x)
local spread = math.rad(math.random(-10, 10)) -- -10 to 10 degrees, converted to radians

-- add the spread to the original angle
angle = angle + spread

-- the rest is the same
local rot = vmath.quat_rotation_z(angle)
local props = { dir = self.dir }
factory.create("#bulletfactory", nil, rot, props)

One important thing to note is that math.random() will always return the same sequence of numbers. You can influence which sequence of number that will get generated by providing the algorithm with what’s called a seed. This seed is used as the basis for the random number algorithm. It’s quite common to use the current time as the seed:

math.randomseed(os.time())

Remember to call this function only once, perhaps in the init() function of some script.

4 Likes

Thanks for the quick answer!
Maybe I’m missing something but the bullets only rotate around their center point but their trajectory stays the same: https://imgur.com/a/nRSRWxS
I would like to decrease its accuracy so the bullets don’t always fly on the same line.

the modified script:

if self.firing then
		local angle = math.atan2(self.dir.y, self.dir.x)
		local spread = math.rad(math.random(-50, 50))
		angle = angle + spread
		local rot = vmath.quat_rotation_z(angle)
		local props = { dir = self.dir }
		factory.create("#bulletfactory", nil, rot, props)
		print(angle, rot, props)
		self.firing = false 
	end

Haha, yes, that’s my mistake. The direction of travel is still the same:

local props = { dir = self.dir }

This also needs to be adjusted. I think it will be enough to do like this:

local dir = vmath.vector3(math.cos(angle), math.sin(angle), 0)
local props = { dir = dir  }

You may need to swap sin and cos, but that should do it.

2 Likes

Works like a charm! https://imgur.com/a/MufhQWx
Thanks a lot!

1 Like

Looks great!

1 Like