someone with mad math skills, help please
|
Author |
Message |
mikshaw
Senior Member
   
Posts: 522
Group: Registered
Joined: Apr 2007
Status:
Offline
Reputation: 5
|
someone with mad math skills, help please
Actually, it's probably not mad skills needed, but I have next to none =o)
I've been messing around with a "gravity" test today, and although I came up with something cool to look at, it's not what I was trying for.
I can get the x,y position of the mouse, the x,y position of the object I want to move, and from there get the distance between the two points:
xdistance=math.abs(Fl:event_x()-object:x())
ydistance=math.abs(Fl:event_y()-object:y())
distance=math.sqrt(xdistance*xdistance+ydistance*ydistance)
What I would really like to do now is use that distance as a way to increase the motion of the object toward the mouse as the distance gets shorter. Essentially I'm looking for a single (floating point?) value that gradually increases as distance decreases. The problems I'm having are as follows:
1) I suck at math
2) The target speed should get larger as the distance gets smaller
3) The target speed should always be a fairly small non-negative number
Is there anyone who might be able to help?
Thanks.
This is the last thing I do before releasing the widgets-demo beta1
|
|
01-23-2008 09:39 AM |
|
 |
Juergen
Member
  
Posts: 81
Group: Registered
Joined: May 2007
Status:
Offline
Reputation: 0
|
RE: someone with mad math skills, help please
If you want to have a linear dependency you could use something like that:
speed=v_min+a/(distance+c) where v_min is the minimal speed and v_min+a/c is the maximal speed. You need the c because for distance=0 the equation would become v_min+1/0 which does not work. So your c is c=a/(v_max - v_min)
Juergen
|
|
01-23-2008 10:17 AM |
|
 |
mikshaw
Senior Member
   
Posts: 522
Group: Registered
Joined: Apr 2007
Status:
Offline
Reputation: 5
|
RE: someone with mad math skills, help please
I only just read this, so haven't tried it yet, but I've already got "if distance > 0" before doing anything. I don't know if that makes it easier.
What is a?
This post was last modified: 01-23-2008 11:28 AM by mikshaw.
|
|
01-23-2008 11:25 AM |
|
 |
mikshaw
Senior Member
   
Posts: 522
Group: Registered
Joined: Apr 2007
Status:
Offline
Reputation: 5
|
RE: someone with mad math skills, help please
I tried it assuming that 'a' was maximum speed, and came up with something different, but not very different than what I already had. Actually it was farther away from my goal.
Here is the curent loop I have, with this change:
function grav_loop()
local my_x,bx=Fl:event_x(),0
local my_y,by=Fl:event_y()-demo_bh,0
local c=math.random(1,255)
local b=math.random(1,balls)
ball[b]:color(c)
for i=1,balls do
local xdistance=math.abs(my_x-ball[i]:x())
local ydistance=math.abs(my_y-ball[i]:y())
local distance=math.sqrt(xdistance*xdistance+ydistance*ydistance)
local speed=1+5/distance
if distance > 0 then
if my_x > ball[i]:x() then
bx=ball[i]:x()+speed
else
bx=ball[i]:x()-speed
end
if my_y > ball[i]:y() then
by=ball[i]:y()+speed
else
by=ball[i]:y()-speed
end
ball[i]:position(bx,by)
end
end
demo_widget:redraw()
grav_timer:doWait(.05)
end
ball is a table of randomly placed circles
EDIT: Actually I kinda like that one too. I'm going to keep it in the mix as stage 3. Thanks.
This post was last modified: 01-23-2008 12:27 PM by mikshaw.
|
|
01-23-2008 12:18 PM |
|
 |
mikshaw
Senior Member
   
Posts: 522
Group: Registered
Joined: Apr 2007
Status:
Offline
Reputation: 5
|
RE: someone with mad math skills, help please
Holy crap! No, wait, it makes a HUGE difference just by changing the minimum and maximum to various values. This could keep me busy for a while.
Thank you Juergen! I think this is exactly what I was looking for.
|
|
01-23-2008 12:41 PM |
|
 |
Juergen
Member
  
Posts: 81
Group: Registered
Joined: May 2007
Status:
Offline
Reputation: 0
|
RE: someone with mad math skills, help please
Holy crap! No, wait, it makes a HUGE difference just by changing the minimum and maximum to various values. This could keep me busy for a while.
Thank you Juergen! I think this is exactly what I was looking for.
Of course this doesn't model gravitation. Gravitational forces go with 1/r^2.
If you want to make a simulation a N-body problem with randomly placed masses also is very problematic, because if you use fixed time steps (delta t) then the model will break because when 2 masses come very close the steps will be to big and when you select smaller dt then you won't see anything.
I can post an example in a few minutes.
Therefore it would make sense to simulate just a few bodies with a fixed setup (like a planetary system)
Juergen
|
|
01-24-2008 08:01 AM |
|
 |
Juergen
Member
  
Posts: 81
Group: Registered
Joined: May 2007
Status:
Offline
Reputation: 0
|
RE: someone with mad math skills, help please
It might be possible to tweak it a little, so that it works better, but the main problem will prevail. Such a simple simulation won't work very good with so many bodies and a random initial setup. At least not if you want to see anything with a decent machine.
Juergen
P.S.: For some reason I can't attach it.
So here it is:
demo_widget:color(0)
balls=34
bsize=10
function grav_loop()
local planet_new={},g,m,r,sqr_r,rx,ry,m_j
time_step=max_slider:value()
for i=1,balls do -- for every planet
g={0,0}
m=planet[i][1] -- with mass m
for j=1,balls do -- with every other planet
if i~=j then -- planets do not influence itself
rx=planet[i][2]-planet[j][2]
ry=planet[i][3]-planet[j][3]
sqr_r=rx*rx+ry*ry
r=math.sqrt(sqr_r) -- distance
m_j=planet[j][1] -- mass of the second planet
g[1]=g[1]+(r>1 and m_j/sqr_r*rx/r or m_j*rx) -- gravitational field value (acceleration of the mass for time_step)
g[2]=g[2]+(r>1 and m_j/sqr_r*ry/r or m_j*rx) -- of course a vector, we also don't want to use too small r values --> planets normally have a radius. Also r=0 is forbidden.
end
end
g[1]=g[1]*grav_const -- we take to liberty to change the gravitational constant.
g[2]=g[2]*grav_const -- not possible in real life!
planet_new[i]={planet[i][1], -- the mass doesn't change
planet[i][2]+planet[i][4]*time_step+g[1]*time_step*time_step*.5, -- x_1=x_0+v_0*t+g/2*t^2 which is the new position of the object
planet[i][3]+planet[i][5]*time_step+g[2]*time_step*time_step*.5, -- the same
planet[i][4]+g[1]*time_step, -- v_1=v_0+g*t , which is the new speed of the object
planet[i][5]+g[2]*time_step} -- of course the same
ball[i]:position(planet_new[i][2]/scale,planet_new[i][3]/scale)
end
planet=planet_new -- everything starts from the beginning
demo_widget:redraw()
grav_timer:doWait(.05)
end
fltk.fl_define_FL_PLASTIC_UP_BOX()
math.randomseed(os.time())
scale=1000
max_x=(demo_widget:w()-bsize)*scale
max_y=(demo_widget:h()-bsize)*scale
max_m=20000000
min_m=1000000
max_ivx=50
max_ivy=50
grav_const=-1
ball={}
planet={}
for i=1,balls do
-- planets[i]={mass,pos_x,pos_y,v_x,v_y}
planet[i]={math.random(min_m,max_m),math.random(1,max_x),math.random(1,max_y),math.random(-max_ivx,max_ivx),math.random(-max_ivy,max_ivy)}
ball[i]=fltk:Fl_Box(planet[i][2]/scale,planet[i][3]/scale,bsize,bsize)
if fltk._FL_PLASTIC_ROUND_UP_BOX then ball[i]:box(fltk._FL_PLASTIC_ROUND_UP_BOX) else ball[i]:box(fltk.FL_PLASTIC_ROUND_UP_BOX) end
ball[i]:color(planet[i][1]/max_m*255)
end
max_slider=fltk:Fl_Hor_Value_Slider(0,demo_widget:h()-20,demo_widget:w(),20)
max_slider:minimum(1)
max_slider:maximum(100)
max_slider:value(.1)
max_slider:step(.1)
grav_timer = murgaLua.createFltkTimer()
grav_timer:callback(grav_loop)
grav_timer:do_callback()
|
|
01-24-2008 08:31 AM |
|
 |
mikshaw
Senior Member
   
Posts: 522
Group: Registered
Joined: Apr 2007
Status:
Offline
Reputation: 5
|
RE: someone with mad math skills, help please
I haven't looked at your script yet, but I've been messing around with various equations and come up with a handful of interesting pieces. Here's one that is cosest to my current goal:
balls=1500
bsize=2
min_grav=0
max_grav=6
function grav_loop()
local my_x,bx=Fl:event_x(),0
local my_y,by=Fl:event_y(),0
local c=math.random(1,255)
for i=1,balls do
local xdistance=math.abs(my_x-ball[i]:x())
local ydistance=math.abs(my_y-ball[i]:y())
local distance=math.sqrt(xdistance*xdistance+ydistance*ydistance)
local xspeed=(min_grav+max_grav)/distance*xdistance
local yspeed=(min_grav+max_grav)/distance*ydistance
if distance <= 25 then
ball[i]:color(c)
-- need a better formula here
xspeed=xspeed*max_x/distance*math.random(2,3)
yspeed=yspeed*max_y/distance*math.random(2,3)
end
if my_x > ball[i]:x() then bx=ball[i]:x()+xspeed else bx=ball[i]:x()-xspeed end
if my_y > ball[i]:y() then by=ball[i]:y()+yspeed else by=ball[i]:y()-yspeed end
ball[i]:position(bx,by)
end
w:redraw()
grav_timer:doWait(.05)
end
w=fltk:Fl_Double_Window(Fl:w(),Fl:h(),"gravity test")
w:color(0)
math.randomseed(os.time())
max_x=w:w()-bsize
max_y=w:h()-bsize
ball={}
for i=1,balls do
ball[i]=fltk:Fl_Box(math.random(1,max_x),math.random(1,max_y),bsize,bsize)
ball[i]:box(fltk.FL_FLAT_BOX)
end
grav_timer = murgaLua.createFltkTimer()
grav_timer:callback(grav_loop)
grav_timer:do_callback()
w:fullscreen()
w:show()
Fl:run()
|
|
01-24-2008 09:25 AM |
|
 |
iGame3D
Moderator
  
Posts: 231
Group: Moderators
Joined: Apr 2007
Status:
Offline
Reputation: 0
|
RE: someone with mad math skills, help please
ooh ahh thats so cool!
Comment that script, what a neat intro to murgaLua that makes!
|
|
01-24-2008 12:03 PM |
|
 |
mikshaw
Senior Member
   
Posts: 522
Group: Registered
Joined: Apr 2007
Status:
Offline
Reputation: 5
|
RE: someone with mad math skills, help please
I like this version best so far
EDIT: I think the warp equations might be in need of even more work. It looks fine on my 1024x768 resolution, but I think higher resolutions might end up with a lot of empty space.
balls=1500 -- number of dots
bsize=2 -- dot size
max_grav=6 -- maximum gravity
hole=20 -- distance from cursor within which dots warp
function grav_loop()
local my_x,my_y=Fl:event_x(),Fl:event_y() -- cursor location
local xspeed,yspeed,bx,by -- initialize some local vars
local c=math.random(1,255) -- random color (except black)
for i=1,balls do
-- find distance of dots from the cursor
local xdistance=math.abs(my_x-ball[i]:x()) -- horz distance from cursor
local ydistance=math.abs(my_y-ball[i]:y()) -- vert distance
local distance=math.sqrt(xdistance^2+ydistance^2) -- as the crow flies
if distance <= hole then
ball[i]:color(c) -- set the color of the dot about to be warped
-- These equations have no defined mathematical logic behind them.
-- I was just playing with numbers until something cool happened.
-- xspeed and yspeed are actually distance measurements (how far to move the dot in one loop)
-- random offset prevents the dots from eventually converging on a single x-y intersection
xspeed=distance*xdistance*2+math.random(-50,50)
yspeed=distance*ydistance*2+math.random(-50,50)
else
-- thanks to Juergen for help with this
xspeed=max_grav/distance*xdistance
yspeed=max_grav/distance*ydistance
end
-- move the dot according to its relative position to cursor
if my_x > ball[i]:x() then bx=ball[i]:x()+xspeed else bx=ball[i]:x()-xspeed end
if my_y > ball[i]:y() then by=ball[i]:y()+yspeed else by=ball[i]:y()-yspeed end
ball[i]:position(bx,by)
end
w:redraw()
grav_timer:doWait(.05)
end
-- make the window the size of your screen
w=fltk:Fl_Double_Window(Fl:w(),Fl:h(),"gravity test")
w:color(0)
math.randomseed(os.time()) -- set a seed for upcoming math.random()
-- set up dots in random locations
ball={}
for i=1,balls do
ball[i]=fltk:Fl_Box(math.random(1,w:w()),math.random(1,w:h()),bsize,bsize)
ball[i]:box(fltk.FL_FLAT_BOX)
end
grav_timer = murgaLua.createFltkTimer()
grav_timer:callback(grav_loop)
grav_timer:do_callback()
w:fullscreen()
w:show()
w:cursor(66) -- cross
Fl:run()
This post was last modified: 01-25-2008 02:43 AM by mikshaw.
|
|
01-25-2008 02:36 AM |
|
 |
|