Page 1 of 1
[Solved] Shooting towards the mouse with rotated image
Posted: Fri Jul 31, 2020 9:25 am
by nikneym
Solved! Updated version:
Code: Select all
graphics = love.graphics
graphics.setDefaultFilter("nearest", "nearest")
local gun = {
img = graphics.newImage("gun.png"),
x = 100,
y = 100,
}
local angle = 0
local half_pi = math.pi / 2
local bul = {
x = 0,
y = 0,
vx = 0,
vy = 0,
speed = 500,
}
function love.update(dt)
bul.x = bul.x + bul.vx * dt
bul.y = bul.y + bul.vy * dt
end
function love.mousemoved(x, y)
angle = math.atan2(y - gun.y * 2, x - gun.x * 2)
end
function love.mousepressed(x, y, b)
if b == 1 then
bul.x = gun.x + 7 * math.cos(angle)
bul.y = gun.y + 7 * math.sin(angle)
bul.vx = bul.speed * math.cos(angle)
bul.vy = bul.speed * math.sin(angle)
end
end
function love.keypressed(key)
if key == "escape" then
love.event.quit()
end
end
function love.draw()
graphics.push()
graphics.scale(2)
graphics.draw(gun['img'], gun.x, gun.y, angle, 1, (angle > half_pi or angle < -half_pi) and -1 or 1, 6, 3)
graphics.circle("line", bul.x, bul.y, 1)
graphics.pop()
end
Re: Shooting towards the mouse with rotated image
Posted: Fri Jul 31, 2020 12:54 pm
by redsled
Use some trig with the angle instead of integer constants in love.mousepressed. Something like this:
Code: Select all
local radius = 22
local startX = (gun.x + math.cos(angle) * radius) * 2
local startY = (gun.y + math.sin(angle) * radius) * 2
The solution is to find a point on a circle with the angle calculated using a reference point (the gun origin) and the mouse position. Kinda like taking a string that's nailed down at one end and loose at the other, where you can freely pull the open end of the string around in a perfect circle. Where you would hold the string with your fingers would be the starting points for the bullets.
I would also recommend translating the gun image position in love.draw but I'm not quite sure how you specifically want the gun to look. I.e.
Code: Select all
local ox = gun['img']:getWidth() / 2
local oy = gun['img']:getHeight() / 2
if angle > -1.5 and angle < 1.5 then
graphics.draw(gun['img'], gun.x, gun.y, angle, 1, 1, ox, oy)
else
graphics.draw(gun['img'], gun.x, gun.y, angle, 1, -1, ox, oy)
end
Note: If the slopes of the bullets aren't parallel with the barrel of the gun, try making the gun barrel parallel with the x-axis when the sprite is drawn.
Re: Shooting towards the mouse with rotated image
Posted: Fri Jul 31, 2020 4:35 pm
by pgimeno
Hm, you're in a "chicken and egg" situation there. You need the angle to calculate the starting position of the bullet, but you need the starting position of the bullet to calculate the angle.
This can be dealt with by solving some equations to find out the correct formulas, or more easily, by aligning the origin of the gun image with the trajectory of the bullet, that is, placing the origin at the centre of the gun's barrel. The centre of the barrel is not necessarily the centre of the image, and it doesn't seem to be in this case, which is why getWidth/2 and getHeight/2 are not a good origin position.
Once the origin is at the centre of the barrel, the gun's position and the mouse position can be used to correctly determine the angle of the bullet. Otherwise the angle will be visibly off when the mouse is close to the gun.
Re: Shooting towards the mouse with rotated image
Posted: Fri Jul 31, 2020 4:55 pm
by nikneym
redsled wrote: ↑Fri Jul 31, 2020 12:54 pm
Use some trig with the angle instead of integer constants in love.mousepressed. Something like this:
Is it like creating an invisible circle around the gun and getting startX and Y according to it? I changed rad to 8 but because of the gun's origin, it still fires from beneath.
I updated the draw function same as you recommend and it looks a lot well now thanks!
pgimeno wrote: ↑Fri Jul 31, 2020 4:35 pm
Once the origin is at the centre of the barrel, the gun's position and the mouse position can be used to correctly determine the angle of the bullet. Otherwise the angle will be visibly off when the mouse is close to the gun.
In order to get the barrel coordinate, should i create a new variable like gun.x + 14 and move on? I know im being an ass with dumb questions but i really want to learn.
Re: Shooting towards the mouse with rotated image
Posted: Fri Jul 31, 2020 5:11 pm
by pgimeno
nikneym wrote: ↑Fri Jul 31, 2020 4:55 pm
In order to get the barrel coordinate, should i create a new variable like gun.x + 14 and move on? I know im being an ass with dumb questions but i really want to learn.
Look at this example. The image is 100 x 100. The red line marks the centre of the barrel which is at y=24 of the image, so I've picked x=28 y=24 as origin. The choice of x=28 was because it meets the centre of the grip approximately and looked like a good pivot point.
Edit: Forgot to say, 93 is the X coordinate within the image where the bullet should be placed, right past the end of the barrel. Since the origin is at x=28, the relative position of the bullet with respect to the origin is 93-28. Sorry for the magic numbers.
To run the example, save this as main.lua and the image as gun.png:
Code: Select all
local lg = love.graphics
local bullet_spd = 400
local gun
local half_pi = 1.5707963267948966
local gun_x, gun_y, gun_angle = lg.getWidth()/2, lg.getHeight()/2, 0
local bullet_x, bullet_y, bullet_vx, bullet_vy
function love.mousemoved(x, y)
gun_angle = math.atan2(y - gun_y, x - gun_x)
end
function love.mousepressed(x, y, b)
if b == 1 then
bullet_x = gun_x + (93-28) * math.cos(gun_angle)
bullet_y = gun_y + (93-28) * math.sin(gun_angle)
bullet_vx = bullet_spd * math.cos(gun_angle)
bullet_vy = bullet_spd * math.sin(gun_angle)
end
end
function love.keypressed(k)
if k == "escape" then return love.event.quit() end
end
function love.load()
gun = lg.newImage('gun.png')
end
function love.update(dt)
if bullet_x then
bullet_x = bullet_x + bullet_vx * dt
bullet_y = bullet_y + bullet_vy * dt
end
end
function love.draw()
lg.draw(gun, gun_x, gun_y, gun_angle,
1, (gun_angle > half_pi or gun_angle < -half_pi) and -1 or 1,
28, 24)
if bullet_x then
lg.rectangle("fill", bullet_x - 1, bullet_y - 1, 3, 3)
end
end
- gun.png (688 Bytes) Viewed 4606 times
Re: Shooting towards the mouse with rotated image
Posted: Sun Aug 02, 2020 10:55 am
by nikneym
I've worked on your example and was able to accomplish. Thank you so much,
another question of mine solved by pgimeno. Well, here is the updated code and gun image:
Code: Select all
graphics = love.graphics
graphics.setDefaultFilter("nearest", "nearest")
local gun = {
img = graphics.newImage("gun.png"),
x = 100,
y = 100,
}
local angle = 0
local half_pi = math.pi / 2
local bul = {
x = 0,
y = 0,
vx = 0,
vy = 0,
speed = 500,
}
function love.update(dt)
bul.x = bul.x + bul.vx * dt
bul.y = bul.y + bul.vy * dt
end
function love.mousemoved(x, y)
angle = math.atan2(y - gun.y * 2, x - gun.x * 2)
end
function love.mousepressed(x, y, b)
if b == 1 then
bul.x = gun.x + 7 * math.cos(angle)
bul.y = gun.y + 7 * math.sin(angle)
bul.vx = bul.speed * math.cos(angle)
bul.vy = bul.speed * math.sin(angle)
end
end
function love.keypressed(key)
if key == "escape" then
love.event.quit()
end
end
function love.draw()
graphics.push()
graphics.scale(2)
graphics.draw(gun['img'], gun.x, gun.y, angle, 1, (angle > half_pi or angle < -half_pi) and -1 or 1, 6, 3)
graphics.circle("line", bul.x, bul.y, 1)
graphics.pop()
end
- gun.png (131 Bytes) Viewed 4548 times