random movement linear impulse

I have 4 static borders surrounding the edges of the screen and I want a ball object to bounce off these randomly using linear impulse but I’m having issues with getting it to randomly move off when the impulse begins. The whole point is to get the ball to move and after a few seconds it will have stopped wherever it was last. Just can’t get it to move randomly and how math.random works for xForce and yForce directions.

Can anyone help with this? Thanks!

post minimal-runable code of what you’ve got, then someone would be better able to suggest changes

in the absence of that, and if you’re not “picky” about distribution then something like the following might be all you need

(this isn’t equally distributed, but it’s a common approach anyway)

-- you will have to "tune" the following value -- to account for unspecified mass as well as desired velocity range, etc local impulseMagnitude = 100 -- tune this local ix = math.random() \* 2 - 1 local iy = math.random() \* 2 - 1 body:applyLinearImpulse(ix\*impulseMagnitude, iy\*impulseMagnitude, body.x, body.y)

Hi davidbollinger, thanks for the reply. I tried your code and it is moving really well but I am having an issue with the speed, which might be something to do with how impulse works.

What happens is that the ball will sometimes move a shorter distance and will move slowly as a result, whereas other times it moves the speed it should. I understand that it is because of the distance but is there a way to avoid those shorter movements and make sure it hits the edges always? 

Before your code I was using brute force to make it travel the screen lengths (Max and Min) which isn’t the best way but you can see what I was trying to achieve. This also eliminated those slow downs in the middle but the movement was stiff. 

bx = math.random(2) == 1 and 320 or -320 by = math.random(2) == 1 and 480 or -480

that sounds like you don’t in fact want random impulses…

ie, what you appear to want is an impulse of a given magnitude at a random orientation, which is quite different, fe:

local theta = math.random() \* 2.0 \* math.pi local ix = math.cos(theta) local iy = math.sin(theta) -- now apply, multiplying by the "tuned" impulseMagnitude as before 

@davebollinger, that is more like it, thanks for that and being patient with me even though what I wanted was different in the OP. Its working really well now. 

I think I need to look into math.sin/cos/pi more. 

@dip, check out the Math is Fun interactive circle.  It will give you sense of how sin, cos, pi and radians fit together.  In @davebollinger’s example, the calculation is in radians.  pi * 2 is equal to the radius of the circle in radians so in degrees, theta would be somewhere between 1 and 360 degrees (the radius of a circle).

As you first start out with sin/cos you might find it easier to think in degrees, in which case you should use math.rad to convert your values from degrees to radians before interacting with sin and cos (which require radians).  The example below picks a random point on a circle in degrees and then converts it to radians

[lua]

math.rad(math.random(1, 360))

[/lua]

post minimal-runable code of what you’ve got, then someone would be better able to suggest changes

in the absence of that, and if you’re not “picky” about distribution then something like the following might be all you need

(this isn’t equally distributed, but it’s a common approach anyway)

-- you will have to "tune" the following value -- to account for unspecified mass as well as desired velocity range, etc local impulseMagnitude = 100 -- tune this local ix = math.random() \* 2 - 1 local iy = math.random() \* 2 - 1 body:applyLinearImpulse(ix\*impulseMagnitude, iy\*impulseMagnitude, body.x, body.y)

Hi davidbollinger, thanks for the reply. I tried your code and it is moving really well but I am having an issue with the speed, which might be something to do with how impulse works.

What happens is that the ball will sometimes move a shorter distance and will move slowly as a result, whereas other times it moves the speed it should. I understand that it is because of the distance but is there a way to avoid those shorter movements and make sure it hits the edges always? 

Before your code I was using brute force to make it travel the screen lengths (Max and Min) which isn’t the best way but you can see what I was trying to achieve. This also eliminated those slow downs in the middle but the movement was stiff. 

bx = math.random(2) == 1 and 320 or -320 by = math.random(2) == 1 and 480 or -480

that sounds like you don’t in fact want random impulses…

ie, what you appear to want is an impulse of a given magnitude at a random orientation, which is quite different, fe:

local theta = math.random() \* 2.0 \* math.pi local ix = math.cos(theta) local iy = math.sin(theta) -- now apply, multiplying by the "tuned" impulseMagnitude as before 

@davebollinger, that is more like it, thanks for that and being patient with me even though what I wanted was different in the OP. Its working really well now. 

I think I need to look into math.sin/cos/pi more. 

@dip, check out the Math is Fun interactive circle.  It will give you sense of how sin, cos, pi and radians fit together.  In @davebollinger’s example, the calculation is in radians.  pi * 2 is equal to the radius of the circle in radians so in degrees, theta would be somewhere between 1 and 360 degrees (the radius of a circle).

As you first start out with sin/cos you might find it easier to think in degrees, in which case you should use math.rad to convert your values from degrees to radians before interacting with sin and cos (which require radians).  The example below picks a random point on a circle in degrees and then converts it to radians

[lua]

math.rad(math.random(1, 360))

[/lua]