Log In  

I'm trying to get a enemy ship to shoot several bullets out at once in a spread pattern. The bullets aren't being targeted at any specific object or point (not a homing missile)...I just want them to shoot out at various angles, like 180 45 and 225*

Ideally, I'd like to have a function that lets you pass in a origin x/y, an angle and speed...

--shootBullet(x, y, angle, speed)
shootBullet(25,25,45,2)

...then I could put that as part of the a larger collection of functions for my shooting routines. I just

I felt that I had some of the answer in the bullet trajectory math here, but after trying to change different variables and stuff, I just couldn't get it right. This is what I get for not going beyond Algebra I in school ;P

If anyone has a method or can share the math, I'd appreciate it. Thanks!

P#20415 2016-05-10 22:33 ( Edited 2016-05-12 00:55)

Sounds like you should google up some bullet hell patterns.

For getting an angle into x and y, you want something like
dx=cos(angle)speed
dy=sin(angle)
speed

edit: pico-8 doesn't work in degrees or radians; it uses rotations. (360deg==2pi==1rot)

P#20416 2016-05-10 22:51 ( Edited 2016-05-11 22:59)

That's the math I'm using but the Y never changes...X does though. I read through the P8 manual and see that sin() is inverted, so it sounds like I have to convert that? I dunno. I'll keep digging...believe me, I've been Googling...

I don't think it helps that the Lua math library in P8 is limited or missing or whatever. I can't do radians.

speed=2
angle=45
x += speed * cos(angle)
y += speed * sin(angle)
P#20417 2016-05-10 23:08 ( Edited 2016-05-11 03:26)

Disclaimer - I still haven't made anything pico yet. (just bought yesterday) This might compile, but no promises

You'll probably want to keep a table just for dumb bullets like these, and use a single update function that runs through them to update since all they need is x,y and dx,dy. (Another point - front loading the sin and cos at creation time means less math on every update, which is usually a good thing)

function makedumbbullet(x,y,a,s)
local newb={}
newb.x=x
newb.y=y
newb.dx=cos(a)s
newb.dy=-sin(a)
s
return newb
end

which you call with a quick "add(dumbbullettable, makedumbbullet(x,y,angle,speed))"

function updatedumbbullets()
for b in all dumbbullettable
b.x+=b.dx
b.y+=b.dy
end
end

P#20418 2016-05-10 23:19 ( Edited 2016-05-11 03:23)

function bulletring(x,y,number,speed)
for i=1,number do
add(dumbbullettable, makedumbbullet(x,y,i/number,speed))
end

edited for proper angle value

P#20419 2016-05-10 23:28 ( Edited 2016-05-11 23:00)

You can still use degrees, just be sure to plug in
degrees * 3.14159 / 180 = radians
someplace

edit: and the inverted sin is because of the direction y pixels are numbered (top to bottom, I assume like most video functions)

edit edit: Not guaranteeing pi is available, so I'll check... and it isn't. So punch in those digits! (I guess)

P#20420 2016-05-10 23:34 ( Edited 2016-05-11 03:43)

Cool, I never thought about having a pre-loaded table...good idea.

Here's how I took your snippets and applied it, it's still not moving the object in the right direction, but I feel I'm missing something. Do I need to convert the angle into something? Is that where the radians come in?

The result here is X changes but Y stays constant, so the ball just moves to the right.

dumbbullettable={}

-- start with ball in the bottom-left corner, try to move it to top-right
x=10
y=120
s=1
angle=45

function makedumbbullet(x,y,a,s)
    local newb={}
    newb.x= x
    newb.y= y
    newb.dx= cos(a)*s
    newb.dy= -sin(a)*s

    return newb
end

-- Shoot at 45* angle (if north is up, this should go northeast)
add(dumbbullettable, makedumbbullet(x,y,angle,s))

--LOOPS

function _update()
    foreach(dumbbullettable, function(obj) 
        obj.x+=obj.dx
        obj.y+=obj.dy
    end)
end

function _draw()
    cls()
    foreach(dumbbullettable, function(obj) 
        print(obj.x.." x "..obj.y,80,5,7)
        circfill(obj.x,obj.y,3,7)
    end)
end
P#20421 2016-05-10 23:49 ( Edited 2016-05-11 03:49)

exactly right. Any built in function that expects an angle expects it to be in radians. So just convert it before you get to the sin and cos.

function makedumbbullet(x,y,a,s)
  [b]a=a/360[/b]
  local newb={}
  newb.x= x
  newb.y= y
  newb.dx= cos(a)*s
  newb.dy= sin(a)*s

  return newb
end

should do the trick

edit: and totally change that table and function name. All those repeated letters are just begging for typos... (I keep having to fix it just writing posts)

edit edit - fixed the worst typo on the first line.

final edit - fixed angle value

P#20422 2016-05-10 23:57 ( Edited 2016-05-11 23:02)

Gotcha...so I added the radians math and now the X and Y change (yay) but the ball certainly isn't moving at 45 angle. It's more like a 10 angle looks like, very narrow. It's weird.

I'm assuming 0 is straight up, 90 is right, 180 down and 270 is left.

-- start with ball in the middle, try to move it to top-right
x=60
y=60
s=1
angle=45
pi=3.14159265359

function makedumbbullet(x,y,a,s)
    rad=a*pi/180
    local newb={}
    newb.x= x
    newb.y= y
    newb.dx= cos(rad)*s
    newb.dy= -sin(rad)*s

    return newb
end

-- Shoot at 45* angle (if north is up, this should go northeast)
add(dumbbullettable, makedumbbullet(x,y,angle,s))
P#20423 2016-05-11 00:04 ( Edited 2016-05-11 04:04)

0 degrees is straight right, and goes ccw as the angle increases.

edit: pico-8 uses "turns": 1 turn == 360 deg

P#20424 2016-05-11 00:09 ( Edited 2016-05-11 23:04)

Don't forget that Pico-8 is weird and takes the range [0,1] instead of [0,2PI]. If you have radians, divide by 2PI first.

print(sin(0.25))
-1

print(sin(0.75))
1

for t=0,1,0.1 do print(sin(t)) end
0
-0.5877
-0.9511
-0.9511
-0.588
-0.0003738
0.5877
0.951
0.9512
0.5883
0.0003891
P#20427 2016-05-11 02:19 ( Edited 2016-05-11 06:19)

As seen in dddaaannn's example, note that sin() returns an already-inverted value to match screen space, so you don't need to re-invert the y.

The quirks with pico-8's trig functions are documented here: https://www.lexaloffle.com/pico-8.php?page=manual (search for "Quirks")

P#20428 2016-05-11 04:22 ( Edited 2016-05-11 08:22)

Instead of thinking of pico-8's sin and cos as being in radians, think of them as being in "turns".

P#20429 2016-05-11 07:19 ( Edited 2016-05-11 11:20)

So if I want to provide a function with a "human" angle value, like 45 or 270, I need to convert that into radians before I give it to sin() and cos()...right?

But if I give sin() and cos() a decimal value between 0 and 1, I can skip the extra calculation?

So in decimal world, 0 is right, so .25 is straight up, .50 is left and .75 is down?

I'm at work so I can't test it anything here but tonight I'll try all of these snippets out.

P#20440 2016-05-11 10:00 ( Edited 2016-05-11 14:00)
So in decimal world, 0 is right, so .25 is straight up, .50 is left and .75 is down?

Totally.
When you code with pico8 you dont have to bother with degrees or radians.
1 is equal to a full turn.

P#20442 2016-05-11 10:54 ( Edited 2016-05-11 14:54)

Here's what I mashed together that got things working in a way I understood and was easy to implement. In short, instead of providing "human" angle numbers, I just give it decimals and everything works fine.

So worst case, I have a little cheat sheet that reminds me which decimals go with which angles. Easy enough.

Thanks to everyone that chimed in. I'm a little smarter and my game will be a little better thanks to everyone's help.

bullets={}

-- settings, start in the center and create an X shot
x=60
y=60
s=2

function createBullet(x,y,a,s)
    local newb={}
    newb.x=x
    newb.y=y
    newb.dx=cos(a)*s
    newb.dy=sin(a)*s

    return newb
end

--LOOPS

function _update()
    foreach(bullets, function(obj) 
        obj.x+=obj.dx
        obj.y+=obj.dy
    end)
end

function _draw()
    cls()
    circfill(x,y,3,1)
    foreach(bullets, function(obj) circfill(obj.x,obj.y,3,7) end)
end

-- Create bullets
-- This will shoot 4 bullets in a X pattern from the center point
-- Angles: 0=right/0*, .25=up/90*, .50=left/180*, .75=down/270*, .125=45*

add(bullets, createBullet(x,y,.125,s)) --45*
add(bullets, createBullet(x,y,.375,s)) --135*
add(bullets, createBullet(x,y,.625,s)) --225*
add(bullets, createBullet(x,y,.875,s)) --315*
P#20476 2016-05-11 20:55 ( Edited 2016-05-12 00:55)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-29 06:35:35 | 0.011s | Q:27