Need help with shotgun blast logic

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
pikuchan
Prole
Posts: 16
Joined: Wed Jan 09, 2013 1:01 am

Need help with shotgun blast logic

Post by pikuchan »

Hey everyone. I need some help and I have a feeling that either there is some fancy math that I need, or I am just overthinking it. I am making a smash tv type of overhead shooter where the player tracks the mouse and you click to fire a bullet in that direction. All of my rotation and shooting is working fine, even found some fancy math to determine the origin point. The problem that I am having is I am trying to make some different guns now and I want some type of a shotgun type of blast. When the player clicks, one bullet should go straight, and then I want additional bullets that spread out. It's pretty easy to get it going for one direction, like Contra or a flying shooter, but I can't seem to figure out the logic to determine what the players rotation is and make a decision based on that. Thanks in advance for any help.

Shoot logic (also detects the point of the gun

Code: Select all

if mouseDownTime >= rateOfFire then
      XofGun = player.x + (14 * math.cos(player.direction)) - (5 * math.sin(player.direction))
      YofGGun = player.y + (5 * math.cos(player.direction)) + (14 * math.sin(player.direction))

      local x = love.mouse.getX()
      local y = love.mouse.getY()
      CreateNewBullet(x, y, XofGun, YofGGun)

      mouseDownTime = 0
    end
Create bullet logic

Code: Select all

function CreateNewBullet(x, y, startX, startY)

  local bulletDx, bulletDy = CalculateDxDy(x, y, startX, startY)

  bulletBoundingBox = {x = startX - (bulletSize/2), y = startY - (bulletSize/2), w = bulletSize, h = bulletSize}

  table.insert(bullets, {x = startX, y = startY, dx = bulletDx, dy = bulletDy, bulletBoundingBox })
Bullet update. I don't think it's relevant, but just in case

Code: Select all

function BulletUpdate(dt)
  for i=#bullets, 1, -1 do
    bullets[i].x = bullets[i].x + (bullets[i].dx * dt)
    bullets[i].y = bullets[i].y + (bullets[i].dy * dt)

    bullets[i].bulletBoundingBox = {x = bullets[i].x - (bulletSize/2), y = bullets[i].y - (bulletSize/2), w = bulletSize, h = bulletSize}

    if CheckBulletPosition(bullets[i]) == true then
      table.remove(bullets, i)
    end
  end
end
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Need help with shotgun blast logic

Post by raidho36 »

Compute the angle towards your target, and for each shoot pellet add a small random angle. Or a fixed specific angle for each individual pellet if you want uniform repeatable pattern.
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Need help with shotgun blast logic

Post by zorg »

So, as you said, all of your rotation and shooting is working fine; so, the logic behind spread shots would be simply this:
- Spawn more than one bullet
- From the "base" angle of the player, have a spread parameter (in degrees or radians, whichever you use already) and a fragment count parameter (or two if you want to randomize the count between two values) for your type of gun;
Then, in a loop, from 1 to a random amount between min and max fragment count, spawn projectiles that have their angles be the base angle plus/minus some random amount between 0 and the spread parameter.

This is one way of doing it; try to code it yourself, it really helps! :3
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
pikuchan
Prole
Posts: 16
Joined: Wed Jan 09, 2013 1:01 am

Re: Need help with shotgun blast logic

Post by pikuchan »

hmmmmm....I've tried manipulating the mouseX and mouseY origin points and i've also tried manipulating the bullets.dx and bullets.dy values and I can't quite get the end result that I am looking for, maybe I need to change my create bullet logic. I should have posted the code for that calculation as well, it is

Code: Select all

function CalculateDxDy(x, y, startX, startY)
  local mouseX = x
  local mouseY = y

  local angle = math.atan2((mouseY - startY), (mouseX - startX))

  local bulletDx = bulletSpeed * math.cos(angle)
  local bulletDy = bulletSpeed * math.sin(angle)

  return bulletDx, bulletDy
end
Maybe it has something to do with the math.cos or math.sin, I honestly don't fully understand the math.
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Need help with shotgun blast logic

Post by zorg »

You should really store the data for individual bullets in separate table entries though... as with everything else, otherwise it will be infinitely more harder than it needs to be.

Code: Select all

function CalculateDxDy(x, y, startX, startY)
  local mouseX = x
  local mouseY = y

  -- the "base" angle for a shot
  local angle = math.atan2((mouseY - startY), (mouseX - startX))

  -- modify the angle based on other parameters
  -- minSpread should be greater or equal to 0, and less or equal to maxSpread.
  angle = angle + love.math.random(minSpread, maxSpread * 2.0) - maxSpread -- spread both clockwise and counterclockwise.

  local bulletDx = bulletSpeed * math.cos(angle)
  local bulletDy = bulletSpeed * math.sin(angle)

  return bulletDx, bulletDy
end
The issue with the above code is that you generally only want to calculate that random number once, when you spawn a projectile, not each time you update it, otherwise it will do weird things... not that that can't be an interesting mechanic. :P
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
pikuchan
Prole
Posts: 16
Joined: Wed Jan 09, 2013 1:01 am

Re: Need help with shotgun blast logic

Post by pikuchan »

Thanks a ton, I'll try that out and see how it works. Looks like I was probably just way overthinking it :)

Regarding your comment on the tables, can you elaborate a little bit as to what I am doing wrong? I've done professional programming for a LOOOONG time and tend to use tables like I would use a custom class. I'm always up for learning more proper ways of doing things.

Thanks again!
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Need help with shotgun blast logic

Post by zorg »

Actually, now that i look at the above function, it's just that i'm a bit too used to seeing methods instead of "global" functions like that, called with minimal parameters. (Like, each entity, player or mook, having their own functions; whereas that calculating one could basically be re-used; both have their upsides and downsides... though OOP-like design with metatables would work too, since the code wouldn't be duplicated, yet all similar objects could use the same function, while it wouldn't hang around as a "global".)

And to be completely honest, i just noticed the table.insert in your createNewBullets function too... so there goes my foot in my mouth. :P

In any case, here's another part of your code altered a tiny bit, to support the fragment count part of my idea:

Code: Select all

if mouseDownTime >= rateOfFire then
      XofGun = player.x + (14 * math.cos(player.direction)) - ( 5 * math.sin(player.direction))
      YofGun = player.y + ( 5 * math.cos(player.direction)) + (14 * math.sin(player.direction))

      local x = love.mouse.getX()
      local y = love.mouse.getY()

      -- This works, since the limiting value will only be calculated once.
      for fragments =1, love.math.random(minFragmentCount, maxFragmentCount) do

          -- Then in CreateNewBullet, add in the angle parameter i mentioned above, that way it will be created on spawn, and not be randomized each update.
          CreateNewBullet(x, y, XofGun, YofGGun)

      end

      mouseDownTime = 0
    end
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
pikuchan
Prole
Posts: 16
Joined: Wed Jan 09, 2013 1:01 am

Re: Need help with shotgun blast logic

Post by pikuchan »

haha, no worries at all. I just figured there's a good chance I was doing something goofy so I was just taking the opportunity to learn from it. Playing around with that code you provided and I don't have it perfect yet, but getting some really cool effects just by tweaking the values some. Thanks for all the help.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Need help with shotgun blast logic

Post by ivan »

The code might work, but it's not super efficient or clear.
Here are my suggestions:

Code: Select all

-- check if we are allowed to fire
if cooldown > 0 then
  cooldown = cooldown - dt
  return
end

-- angle
local a = player.direction
-- speed
local s = 100
-- offset
local xo, yo = 14, 5
local x = player.x + math.cos(a)*xo
local y = player.y + math.sin(a)*yo

-- adjust cooldown
cooldown = rateoffire

-- spawn new bullet(s) here
CreateNewBullet(x, y, a, s)
You don't need to store the bounding boxes:

Code: Select all

function CreateNewBullet(x, y, a, s, r)
  local dx = math.cos(a)*s
  local dy = math.sin(a)*s
  table.insert(bullets, {x = x, y = y, dx = dx, dy = dy, radius = r or 5 })
end
For the bullet update function, you are creating a new table each frame which is not ideal:

Code: Select all

function BulletUpdate(dt)
  for i=#bullets, 1, -1 do
    local b = bullets[I]
    b.x = b.x + b.dx*dt
    b.y = b.y + b.dy*dt

    -- did we hit something?
    if QueryMapAABB(b.x, b.y, b.radius, b.radius) == true then
      table.remove(bullets, i)
    end
  end
end
Post Reply

Who is online

Users browsing this forum: No registered users and 60 guests