An intriguing challenge with physics
Blitz3D Forums/Blitz3D Programming/An intriguing challenge with physics
| ||
Lets see if this is solvable! :) Given two points in 2D (or 3D) space, we want to keep point two the same distance from point one, similar to simple string physics. However as point one (p1) moves towards point two (p2), p2 will prefer to rotate around to mantain the distance rather than merely be pushed away. At no point will p1 be affected by p2 in the simulation. Finally, p2 will be dragged into line and follow p1 if p1 moves away. Can you envision the sort of simple physics problem I'm trying to explain? It shouldn't take much to affect only p2 (p1 is under manual control at all times) but it has me completely stumped! |
| ||
SetBuffer BackBuffer() mx# = MouseX() my# = MouseY() px# = mx + 100 py# = my l# = 40.0 Repeat Cls mx# = MouseX() my# = MouseY() d# = Sqr((mx-px)^2 + (my-py)^2) dx# = ((mx-px)/d)*l dy# = ((my-py)/d)*l px# = mx - dx py# = my - dy Line mx,my,px,py Flip Until KeyHit(1)Will that do? |
| ||
I think he wants it so that if you push the control point towards the child point, the child will swing round so that it is behind. (I think) |
| ||
nearly perfect! I need to modify it so that it is more inclined to rotate about as you move closer - where do I do this? thanks for the quick reply! |
| ||
Well, that's what the code does :) (mostly) <-- In regards to pertubatio |
| ||
found it thanks ;) |
| ||
actually I got that wrong, here is the modified code that makes it turn more quickly and reponsive as we move closer:d# = Sqr((mx-px)^2 + (my-py)^2) If d#>l dx# = ((mx-px)/d)*l dy# = ((my-py)/d)*l px# = mx - dx py# = my - dy ElseIf d#<l a# = ATan2(mx-px,my-py)* 1.02 px# = mx + Sin(-a)*l py# = my - Cos(-a)*l End If I just multiply a# however it really jitters badly if you go up then down - any idea how to fix? |
| ||
pertubatio's right when you get a situation where you move towards it exactly - the point moves away. Any idea how to fix this would be appreciated :) |
| ||
Throw in a little randomness? |
| ||
No, because you need to continue the randomness. |
| ||
http://mathworld.wolfram.com/Circle-CircleIntersection.html A is your first point. B is the point that should circle it. C is the point you move A to. D is the point to which B should move to. R is the distance between point A and B. E is a circle centered at point A, with radius R. F is a circle centered at point C, with radius R. Find the point(s) where circles E and F intersect. If the circles intersect at one point, that point is point D. If the circles intersect at two points, determine the squared distance of each from point B. Choose the one with the smaller squared distance. That is point D. If the circles intersect at an imaginary point, subtract point A from point C to create a vector, calculate the length of the vector, divide the vector by it's length, and then multiply by R. That is point D. I think. |
| ||
Thats too complex for me. I'm doing a little bit of begging here, can someone help? :) |
| ||
It's too complex for me too. That's why I didn't explain how to do it in code. :-) I'm not sure how to calculate the intersections given those equations on that site. |
| ||
SetBuffer BackBuffer() mx# = MouseX() my# = MouseY() px# = mx + 100 py# = my l# = 40.0 Angle# = 180 Repeat Cls mx# = MouseX() my# = MouseY() d# = Sqr((mx-px)^2 + (my-py)^2) dx# = ((mx-px)/d)*l+Sin(Angle)*3 dy# = ((my-py)/d)*l+Cos(Angle)*3 px# = mx - dx py# = my - dy Line mx,my,px,py Flip Until KeyHit(1) hm? :\ |
| ||
Um... Isn't this really really simple?Graphics3D 640,480,16,2 MoveMouse 320,240 b1=CreateCube() b2=CreateCube() camera=CreateCamera() MoveEntity camera,0,0,-20 Repeat x#=(MouseX()-320)*.065 y#=(-MouseY()+240)*.065 PositionEntity b1,x,y,0 ; the complex maths bit PointEntity b2,b1 MoveEntity b2,0,0,EntityDistance(b1,b2)-5 ;where 5 is how far away you want it to be UpdateWorld RenderWorld Flip Until KeyHit(1) |
| ||
I can still push the child around by the parent moving directly towards it. |
| ||
cool piece of code, any area of use for this? |
| ||
The challenge is still open as no-one has been able to solve it by rotation only as you move towards it. Moving away always pulls it into line when dragged - thats easy. It's the rotation that has us stumped. |
| ||
dudes, how aboud adding more objects, so instead of 2 we have several more? I can see this in a commercial game: YOU take the role as a farmer and will drive your tractor with an other vehicle attached to it: You'll have to drive it around your farm from the garrage to certain fields to collect certain crops, coming back to garrage to change the second vehicle being different depending on the type of the crop you wish to collect. I know - it's a hit. =) |
| ||
Lets just solve the current problem, yeah? The point of this post is to find out how to rotate a single point around another as you move towards it instead of simply pushing it away. I know you mean well, but I'm fustrated at the moment trying to get it working :) |
| ||
Graphics3D 640,480,16,1 MoveMouse 320,240 b1=CreateCube() b2=CreateCube() camera=CreateCamera() MoveEntity camera,0,0,-20 Repeat x#=(MouseX()-320)*.065 y#=(-MouseY()+240)*.065 PositionEntity b1,x,y,0 d#=EntityDistance(b1,b2)-5 PointEntity b2,b1 ; this bit makes it rotate rather than move backwards If d<0 Then MoveEntity b2,-.1,0,0:d#=EntityDistance(b1,b2)-5 MoveEntity b2,0,0,d UpdateWorld RenderWorld Flip Until KeyHit(1) |
| ||
SetBuffer BackBuffer() mx# = MouseX() my# = MouseY() px# = mx + 100 py# = my l# = 40.0 Repeat Cls lmx# = mx# lmy# = my# mx# = MouseX() my# = MouseY() smx# = lmx-mx smy# = lmy-my d# = Sqr((mx-px)^2 + (my-py)^2) If d<l a# = ATan2(smx,smy)-ATan2(px-mx,py-my) dx# = Sin(a) dy# = Cos(a) px = px + dy py = py - dx d# = Sqr((mx-px)^2 + (my-py)^2) End If dx# = ((mx-px)/d)*l dy# = ((my-py)/d)*l px# = mx - dx py# = my - dy Line mx,my,px,py Flip Until KeyHit(1)Perfect Mk.III? :) |
| ||
Nice one dr av! Close, very close Fredborg, but no cigar! the line doesn't take the path of least resistance, it always attempts to rotate clockwise... can you fix it? :) |
| ||
Check above, I changed it. Better? |
| ||
It's the same as before! I'm not trying to annoy the hell out of you... but it would be nice, very nice :) in fact I'll even knock out some screenshots to say thanks if you get it working :) Basically, it doesn't seem to take the shortest rotation. |
| ||
This I gotta see :) Check above again! |
| ||
Fredborg: It looks almost right, but if you have the line pointing to the left and move left against the child, it doesn't rotate :/ |
| ||
SetBuffer BackBuffer() mx# = MouseX() my# = MouseY() px# = mx + 100 py# = my l# = 40.0 f# = 2.0 Repeat Cls lmx# = mx# lmy# = my# mx# = MouseX() my# = MouseY() smx# = mx-px+((mx-lmx)*f) smy# = my-py+((my-lmy)*f) d# = Sqr(smx*smx + smy*smy) px# = mx - ((smx/d)*l) py# = my - ((smy/d)*l) Line mx,my,px,py Flip Until KeyHit(1)Divine Mk. I! :) Adjust f# to set how fast it turns! |
| ||
That seems to be doing it. |
| ||
Ohhh he's done it! Simply Divine! See? Thats what you get if you buy gile[s]! Everyone BUY it today ;) |
| ||
Now gimme dem skweens! :D |
| ||
lol ok |
| ||
Ok, I've been suckered, I'm buying gile[s]... I'll call it my christmas present to myself :) *EDIT* But I expect lots of physics help too :) |
| ||
Baaah ;) You're registration code has been sent! Enjoy :) |
| ||
Why is it the simplest things are the most amusing ? It's also strange that these seemingly simple physic kind of problems are quite the challange to implement unless you have a firm grip on this kind of thing. It's also these seemingly simple things, when combined with other simple elements, tend to really bring a sense of realism. LifeForce/Salamander/Gradius/Nemesis have several of these kind of things that always boggled my mind to no end. Fredborg, Have you ever played/seen the Gradius series set of games. If so, you know the segmented arms that slowly move towards the player but the whole thing is locked down at it the base by the final segment ? Any chance you having a little more Holiday cheer in your bag of tricks and knocking that little bugger up ? Lastly, any recommended math/physics readings? |
| ||
Dr. is it something like this?SetBuffer BackBuffer() Type arm Field x#,y# Field s#,l# Field parent.arm End Type parm.arm = Null ; ; s# indicates how fast each joint can turn s# = 0.02 For i = 0 To 5 arm.arm = New arm arm\parent = parm If parm = Null arm\x = 200 arm\y = 150 End If arm\l = 20.0 arm\s = s# ; ; Set the next arm's parent to be this one parm = arm ; ; Increase s# for each new arm s# = s# * 1.5 Next Repeat Cls a# = a+2.0 tx# = MouseX() ty# = MouseY() For arm.arm = Each arm If arm\parent<>Null ; ; Vector between this arm's joint and the mouse dx# = tx-arm\x dy# = ty-arm\y d# = Sqr(dx*dx + dy*dy) If d = 0 Then d = 1.0 dx# = arm\parent\x+((dx/d)*arm\l) dy# = arm\parent\y+((dy/d)*arm\l) ; ; Turn the arm to be closer to the mouse arm\x = arm\x-(arm\parent\x-dx)*arm\s arm\y = arm\y-(arm\parent\y-dy)*arm\s ; ; Make sure the arm doesn't change length dx# = arm\x-arm\parent\x dy# = arm\y-arm\parent\y d# = Sqr(dx*dx + dy*dy) If d = 0 Then d = 1.0 arm\x# = arm\parent\x+((dx/d)*arm\l) arm\y# = arm\parent\y+((dy/d)*arm\l) ; ; Draw the arm Oval arm\x-2,arm\y-2,5,5,True Line arm\x,arm\y,arm\parent\x,arm\parent\y Else ; ; Just move the first joint around in a circle arm\x = 200+(Sin(a)*20.0) arm\y = 150+(Cos(a)*20.0) Oval arm\x-6,arm\y-6,13,13,False Oval arm\x-2,arm\y-2,5,5,True End If Next Flip Until KeyHit(1) EndAnd the funny thing is I don't really know what I'm doing either :) I don't really know about any books, just get some basic maths books about vectors, they will get you far if you are interested in it! |
| ||
This is even more fun :DGraphics 640,480,0,2 SetBuffer BackBuffer() Type arm Field x#,y# Field s#,l#,al# Field parent.arm End Type parm.arm = Null For i = 0 To 10 arm.arm = New arm arm\parent = parm ; Origin of the first arm If parm = Null arm\x = GraphicsWidth()/2.0 arm\y = GraphicsHeight()/2.0 End If ; Set the length of this arm arm\l = 20.0 ; Set the speed at which this arm can turn arm\s = (i+1)/50.0 ; angular limit arm\al = Sqr(arm\l*arm\l + arm\l*arm\l)*1.5 ; Set the next arm's parent to be this one parm = arm Next Repeat Cls tx# = MouseX() ty# = MouseY() For arm.arm = Each arm If arm\parent<>Null ; ; Vector between this arm's joint and the mouse dx# = tx-arm\x dy# = ty-arm\y d# = Sqr(dx*dx + dy*dy) If d = 0 Then d = 1.0 dx# = arm\parent\x+((dx/d)*arm\l) dy# = arm\parent\y+((dy/d)*arm\l) ; ; Turn the arm to be closer to the mouse arm\x = arm\x-(arm\parent\x-dx)*arm\s arm\y = arm\y-(arm\parent\y-dy)*arm\s ; ; Make sure the arm doesn't change length dx# = arm\x-arm\parent\x dy# = arm\y-arm\parent\y d# = Sqr(dx*dx + dy*dy) If d = 0 Then d = 1.0 arm\x# = arm\parent\x+((dx/d)*arm\l) arm\y# = arm\parent\y+((dy/d)*arm\l) ; ; Limit angle If arm\parent\parent <> Null dx# = arm\x-arm\parent\parent\x dy# = arm\y-arm\parent\parent\y d# = Sqr(dx*dx + dy*dy) If d>0.0 If d#<arm\al arm\x# = arm\parent\parent\x+((dx/d)*arm\al) arm\y# = arm\parent\parent\y+((dy/d)*arm\al) End If End If End If ; ; Draw the arm Oval arm\x-2,arm\y-2,5,5,True Line arm\x,arm\y,arm\parent\x,arm\parent\y Else ; ; The first joint/arm Oval arm\x-6,arm\y-6,13,13,False Oval arm\x-2,arm\y-2,5,5,True End If Next Flip Until KeyHit(1) End |
| ||
thats ultra-cool :D |
| ||
You can achieve the "swing around to the back" thingy by using verletphysics as well. Just apply gravity to Point 2 that is opposite to Point 1's velocity. This way you could make a very cool camera tracking thingy that tries to stay behind the player and if the player turns towards the camera and start walking at it, the camera swings around. The swing around behaviour can be controlled by setting different gravity and damping values. The camera will also "climb the walls" if the camera is cornered and collision against walls is applied. |
| ||
That is cool. You could make an octopus simulator with that :) |
| ||
Sweenie, thats what it's for ;) |
| ||
Rob, In that case try the verletcamera thingy, You won't be disappointed. :) |
| ||
Where is the verletcamera thingy ? :) |
| ||
sorry, I made it sound like there was a finished verletcamera solution. The only one I've seen in action, is the one lurking around in some of my own half-finished games. But it's very easy to get it up and running. Just add the verlet code, add two verlets and put a constraint between them. Then attach the first verlet to the object you want the camera to follow and attach the camera to the second verlet. You know what, I think i will make an example and add it to the codearchives instead. :) |
| ||
Chop chop :) |
| ||
Ahh! I love it! That IS 'ultra cool' thanks. |