A collection of tips for making shooters

I’m currently in the process of creating a shooter, and I’ve decided to collect my findings (mostly math and weapon spread related) into one cohesive topic for others to use. To preface all of this, I’m using a modified version of Thienbao2109’s FE Weapon Kit - but this should all apply regardless.

Calculating Weapon Spread from Effective Range

By default, FE Weapon Kit uses a single value - expressed in degrees - to control weapon spread. This solution isn’t very tunable, and has some room for improvement.

Valve Software’s Counter-Strike: Global Offensive and Counter-Strike 2 determine weapon spread based on a different factor - accurate range. In these editions of Counter-Strike, a weapon’s accurate range determines the distance in which a bullet is guaranteed to hit a 30cm dinner plate (roughly the size of a human head). But how do we implement this ourselves? Some very simple math.

function weaponSpreadAngleFromRange(accurateRange:number, spreadRadius:number):number
  return math.atan(spreadRadius/accurateRange)
end

In this function, we have two input variables and one output variable. The two inputs represent two sides of a right triangle - accurateRange is the adjacent, spreadRadius is the opposite. From here, we apply SOHCAHTOA. We know both the opposite and tangent, so we can find the angle with the inverse tangent of their quotient.

In Roblox, standard character heads have a size of 1.2, 1.2, 1.2, so we can use weaponSpreadAngleFromRange(accurateRange:number, .6) to get a weapon’s spread angle from it’s guaranteed headshot range. Similarly, we might use weaponSpreadAngleFromRange(accurateRange:number, 1) for determining weapon spread based on the weapon’s ability to hit the torso (good for shotguns and SMGs!), or weaponSpreadAngleFromRange(accurateRange:number, 5) for weapons meant for larger targets (tanks, helicopters, dragons).

On Zooming

In most games, zooming in (or scoping) is accomplished by modifying the field of view value (FOV).

local zoomFov = fov / zoomFactor

It’s simple, but there are still a couple things to keep in mind.

  • Magnification
    Did you know that dividing your FOV by two actually magnifies objects by four times? In school, you might have learned that doubling the width and length of a rectangle quadrupled the area, and the same principle applies here. This isn’t a problem, but if you want to set the FOV based on magnification, simply use the square root of the magnification level.
local zoomFov = fov / math.sqrt(magnification)
  • Customizable FOV
    Many games offer customizable FOV settings for players to tweak to their preference. This, of course, intersects with modifying FOV to zoom. There are two paths you might take here. 1. You handle zooming by dividing the player’s FOV setting; or 2. you handle zooming by dividing a global default FOV setting.
local zoomFov = defaultFov / zoomFactor
Actually Accurate Crosshair Size (WIP)

You don’t need to spend hours tweaking crosshair size to fit a weapon, when you can set it based on weapon spread.

Details coming soon

I’m still working on my game, and I’ll try to keep updating this thread with whatever tidbits I discover that might be useful to others. Stay tuned for more : )

9 Likes