Interesting and curious natural effect against intuition

Everything related to 3D programming
User avatar
Psychophanta
Addict
Addict
Posts: 4996
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Interesting and curious natural effect against intuition

Post by Psychophanta »

Found an issue in the physics engine.
Probably this is also in other engines.
There is a function to apply a torque to the bodies, but this function 'ApplyEntityTorque()' does not allow to input the center of the torque; instead, the center is always the center of the body.

So, I tried to perform a torque in a body, not centered in its center, but in other different point.
The result is not the expected one by intuition: when the actions are done like in the code below, the center of mass should move, but it doesn't.

Still not completely sure this is the correct beaviour. :?

Code: Select all

RX.u=1024:RY.u=768
InitEngine3D()
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite():InitKeyboard():InitMouse()
OpenWindow(0,0,0,RX,RY,"tip",#PB_Window_BorderLess|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,RX,RY,0,0,0,#PB_Screen_WaitSynchronization)
CreateLight(0,$EEEEEE,4,4,2,#PB_Light_Point)
CreateCamera(0,0,0,100,100)
MoveCamera(0,0,0,3,#PB_Absolute)
LoadTexture(0,"terrain_detail.jpg")
CreateMaterial(0,TextureID(0))
CreateCylinder(0,0.2,1.4)
CreateEntity(0,MeshID(0),MaterialID(0),0,0,0)

WorldGravity(0.0)
CreateEntityBody(0,#PB_Entity_CylinderBody)

Repeat
  WindowEvent()
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Right); the center of mass should move ??, but it doesn't
    ApplyEntityForce(0,0.1,0,0,0,2,0,#PB_World)
    ApplyEntityForce(0,-0.1,0,0,0,1,0,#PB_World)
  ElseIf KeyboardPushed(#PB_Key_Left); the center of mass should move ??, but it doesn't
    ApplyEntityForce(0,-0.1,0,0,0,2,0,#PB_World)
    ApplyEntityForce(0,0.1,0,0,0,1,0,#PB_World)
  EndIf
  RenderWorld()
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 289
Joined: Thu Jul 09, 2015 9:07 am

Re: Interesting and curious natural effect against intuition

Post by pf shadoko »

you apply a force on the right at 2 meters high and the same force on the left at 1 meter high
in other words, you apply a torque at a height of 1.5 meters
but be careful you're in pb_world
difficult to say if this behaviour is correct
User avatar
Psychophanta
Addict
Addict
Posts: 4996
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Interesting and curious natural effect against intuition

Post by Psychophanta »

Thank you pf shadoko, :)
you are very right.
Anyway, the physics engine is good enough.

+1

ADDed to this topic a well done behaviour, not using 3D engine neither physics engine:
here is a short torque impulse, but enough to see the bar center of masses moves, as it should. With the physics engine it doesn't.

Code: Select all

Procedure.d WrapAngle(angle.d); <- wraps a value into [-Pi,Pi] fringe
  !fldpi
  !fadd st0,st0; <- now i have 2*pi into st0
  !fld qword[p.v_angle]
  !fprem1
  !fstp st1
  ProcedureReturn
EndProcedure
Procedure.d myATan2(y.d,x.d)
  !fld qword[p.v_y]
  !fld qword[p.v_x]
  !fpatan
  ProcedureReturn
EndProcedure
Procedure CreateBallSprite(c.l,size.l,color.l)
  CreateSprite(c,size,size)
  StartDrawing(SpriteOutput(c))
  BackColor(0):R.w=color&$FF:G.w=color>>8&$FF:B.w=color>>16&$FF
  For t.l=size/2-1 To 1 Step -1
    R+160/size:G+160/size:B+160/size:If R>255:R=255:EndIf:If G>255:G=255:EndIf:If B>255:B=255:EndIf
    Circle(size/2,size/2,t,RGB(R,G,B))
  Next
  StopDrawing()
EndProcedure
Procedure ParticleAndBarbellShock(*results.double,l.d=0.1,R.d=0.65,W.d=0.91,m1.d=0.3411,m2.d=0.1411,V1.d=0.0,V2.d=0.0,K.d=1.0/3.0,e.d=1.0)
  ;l es la distancia a la que colisionan particula y barra, a medir desde el centro de esta.
  ;R es el radio de la barra (o disco, o esfera...).
  ;m1 es la masa de la particula.
  ;m2 es la masa de la barra.
  ;(V1x,V1y) es el vector velocidad de la particula antes del choque.
  ;(V2x,V2y) es el vector velocidad del centro de masas de la barra antes del choque.
  ;(V1xp,V1yp) es el vector velocidad de la partícula tras el choque.
  ;(V2xp,V2yp) es el vector velocidad del centro de masas de la barra tras el choque.
  ;W es la velocidad angular inicial de la barra
  ;Wp es la velocidad angular final de la barra
  ;e es un valor llamado "coeficiente de restitución" y es: e = -(V1p-(V2p+Wp*l))/(V1-(V2+W*l))
  ;K es un valor especifico de la geometría de la masa rotante (1/2 si es un disco rotando alrededor de su eje central y transversal; 1/3 si es una barra; etc).
  I.d=m2.d*K.d*R.d*R.d; <- momento de inercia
  ;Ecuaciones:
  ;m1·V1+m2·V2=m1·V1'+m2·V2'  ; <- conservación del momento lineal del sistema
  ;m1·V1·l+I·W=m1·V1'·l+I·W'  ; <- conservación del momento angular del sistema
  ;m1·V1^2+m2·V2^2+I·W^2+Q=m1·V1'^2+m2·V2'^2+I·W'^2  ; <- conservación de la energía del sistema. Q=0 para un choque completamente elástico
  ;V1'=V2'+W'·l-e·(V1-V2-W·l)
  CRV.d=e.d*(V1.d-V2.d-W.d*l.d)
  ;Incógnitas despejadas:
  Wp.d=(I.d*W.d*(m1.d+m2.d)+m1.d*m2.d*l.d*(V1.d-V2.d+CRV.d))/(I.d*(m1.d+m2.d)+m1.d*m2.d*l.d*l.d)
  V2p.d=(m1.d*V1.d+m2.d*V2.d-m1.d*Wp.d*l.d+m1.d*CRV.d)/(m1.d+m2.d)
  V1p.d=V2p.d+Wp.d*l.d-CRV.d
  ;
  *results\d=Wp.d:*results+SizeOf(double)
  *results\d=V2p.d:*results+SizeOf(double)
  *results\d=V1p.d
EndProcedure
Structure values
  omega.d
  VelocidadEfectiva0.d
  StructureUnion
    VelocidadEfectiva1.d
    VelocidadEfectiva2.d
  EndStructureUnion
EndStructure
gotvalues.values
Macro Collide(MassID)
  ;Unclip
  mass.d=M(0)\mass/(M(0)\mass+M(MassID#)\mass)
  Ball#MassID#x+Unclip#MassID#x.d*mass.d:Ball#MassID#y+Unclip#MassID#y.d*mass.d
  M(MassID#)\x+Unclip#MassID#x.d*mass.d:M(MassID#)\y+Unclip#MassID#y.d*mass.d
  mass.d=1-mass.d
  M(0)\x-Unclip#MassID#x.d*mass:M(0)\y-Unclip#MassID#y.d*mass.d
  ;
  Point#MassID#x.d=Ball#MassID#x.d+M(MassID#)\radius*DiffuX.d:Point#MassID#y.d=Ball#MassID#y.d+M(MassID#)\radius*DiffuY.d; <- vector (Eje de giro->punto de colisión)
  l.d=Abs(Point#MassID#x.d*-DiffuY.d+Point#MassID#y.d*DiffuX.d):l.d*l.d/(la.d+l.d)
  ;
  gotvalues\VelocidadEfectiva0=(M(0)\mx*Rightvx.d+M(0)\my*Rightvy.d):gotvalues\VelocidadEfectiva0=(M(0)\mx*Rightvx.d+M(0)\my*Rightvy.d); <- módulo de la componente en línea de choque de la velocidad lineal de la barra.
  gotvalues\VelocidadEfectiva#MassID#=(M(MassID#)\mx*Rightvx.d+M(MassID#)\my*Rightvy.d):gotvalues\VelocidadEfectiva#MassID#=(M(MassID#)\mx*Rightvx.d+M(MassID#)\my*Rightvy.d); <- componente en linea de choque de la velocidad lineal de la particula.
  M(0)\mx-gotvalues\VelocidadEfectiva0*Rightvx.d:M(0)\my-gotvalues\VelocidadEfectiva0*Rightvy.d; <- se deja a la barra solo con la componente de la velocidad normal a la linea de choque.
  M(MassID#)\mx-gotvalues\VelocidadEfectiva#MassID#*Rightvx.d:M(MassID#)\my-gotvalues\VelocidadEfectiva#MassID#*Rightvy.d; <- se deja a la partícula solo con la componente de la velocidad normal a la linea de choque.
  ;
  ;The calculation function:
  ParticleAndBarbellShock(@gotvalues.values,l,M(0)\HalfWidth,omega.d,M(MassID#)\mass,M(0)\mass,gotvalues\VelocidadEfectiva#MassID#,gotvalues\VelocidadEfectiva0)
  ;
  omega=gotvalues\omega
  M(0)\mx+gotvalues\VelocidadEfectiva0*Rightvx.d:M(0)\my+gotvalues\VelocidadEfectiva0*Rightvy.d; <- se suma la velocidad en la linea de choque obtenida.
  M(MassID#)\mx+gotvalues\VelocidadEfectiva#MassID#*Rightvx.d:M(MassID#)\my+gotvalues\VelocidadEfectiva#MassID#*Rightvy.d; <- se suma la velocidad en la linea de choque obtenida.
EndMacro
Macro CollideR(MassID)
  la.d=M(0)\HalfWidth
  Collide(MassID#)
EndMacro
Macro CollideL(MassID)
  la.d=M(0)\HalfWidth
  Collide(MassID#)
EndMacro
Macro CollideU(MassID)
  la.d=M(0)\HalfHeight
  Collide(MassID#)
EndMacro
Macro CollideD(MassID)
  la.d=M(0)\HalfHeight
  Collide(MassID#)
EndMacro
Macro BallOuter(MassID)
  Ball#MassID#x.d=M(MassID#)\x-M(0)\x:Ball#MassID#y.d=M(MassID#)\y-M(0)\y; <- vector centro de cápsula->bola
  Capsule#MassID#x.d=Cos(angle.d):Capsule#MassID#y.d=Sin(angle.d); <- vector-unidad Derecha de la cápsula
  Ball#MassID#rdist.d=(Ball#MassID#x*Capsule#MassID#x+Ball#MassID#y*Capsule#MassID#y); <- Proyección del vector bola sobre el vector Derecha de la cápsula
  Ball#MassID#udist.d=(Ball#MassID#x*Capsule#MassID#y+Ball#MassID#y*-Capsule#MassID#x); <- Proyección del vector bola sobre el vector Arriba de la cápsula
  ;
  If Ball#MassID#rdist>=0; <- Si la bola#MassID# está a la derecha:
    If Ball#MassID#udist>=0; <- Si la bola#MassID# está a la derecha y arriba:
      rdif.d=Ball#MassID#rdist-M(0)\HalfWidth:rdifmr.d=rdif.d-M(MassID#)\radius
      udif.d=Ball#MassID#udist-M(0)\HalfHeight:udifmr.d=udif.d-M(MassID#)\radius
      If udifmr.d<=0 And rdif.d<=0; <- Si hay colisión contra alguna arista o esquina superior derecha:
        Rightvx.d=-Capsule#MassID#y:Rightvy.d=Capsule#MassID#x
        angle.d+Abs(omega.d); <- to unclip
        DiffuX.d=-Capsule#MassID#y:DiffuY.d=Capsule#MassID#x; <- Vector unidad del sentido del choque.
        Unclip#MassID#x.d=udifmr.d*DiffuX.d:Unclip#MassID#y.d=udifmr.d*DiffuY.d
        CollideU(MassID#)
      ElseIf rdifmr.d<=0 And udif.d<=0; <- Si hay colisión contra la arista derecha:
        Rightvx.d=Capsule#MassID#x:Rightvy.d=Capsule#MassID#y
        angle.d-Abs(omega.d); <- to unclip
        DiffuX.d=-Capsule#MassID#x:DiffuY.d=-Capsule#MassID#y; <- Vector unidad del sentido del choque.
        Unclip#MassID#x.d=rdifmr*DiffuX.d:Unclip#MassID#y.d=rdifmr*DiffuY.d
        CollideR(MassID#)
      Else:ddif.d=Sqr(rdif.d*rdif.d+udif.d*udif.d)-M(MassID#)\radius
        If ddif.d<0
          incl.d=myATan2(-udif.d,-rdif.d)
          DiffuX.d=Cos(incl.d):DiffuY.d=Sin(incl.d); <- Vector unidad del sentido del choque.
          Unclip#MassID#x.d=ddif*DiffuX.d:Unclip#MassID#y.d=ddif*DiffuY.d
          Rightvx.d=Capsule#MassID#x:Rightvy.d=Capsule#MassID#y
          CollideR(MassID#)
          Rightvx.d=-Capsule#MassID#y:Rightvy.d=Capsule#MassID#x
          CollideU(MassID#)
        EndIf
      EndIf
    Else; <- Si la bola#MassID# está a la derecha y abajo:
      rdif.d=Ball#MassID#rdist-M(0)\HalfWidth:rdifmr=rdif-M(MassID#)\radius
      udif.d=-Ball#MassID#udist-M(0)\HalfHeight:udifmr=udif-M(MassID#)\radius
      If udifmr.d<=0 And rdif.d<=0; <- Si hay colisión contra la arista de abajo:
        Rightvx.d=-Capsule#MassID#y:Rightvy.d=Capsule#MassID#x
        angle.d-Abs(omega.d); <- to unclip
        DiffuX.d=Capsule#MassID#y:DiffuY.d=-Capsule#MassID#x; <- Vector unidad del sentido del choque.
        Unclip#MassID#x.d=udifmr*DiffuX.d:Unclip#MassID#y.d=udifmr.d*DiffuY.d
        CollideD(MassID#)
      ElseIf rdifmr.d<=0 And udif.d<=0; <- Si hay colisión contra la arista derecha:
        Rightvx.d=-Capsule#MassID#x:Rightvy.d=-Capsule#MassID#y
        angle.d+Abs(omega.d); <- to unclip
        DiffuX.d=-Capsule#MassID#x:DiffuY.d=-Capsule#MassID#y; <- Vector unidad del sentido del choque.
        Unclip#MassID#x.d=rdifmr.d*DiffuX.d:Unclip#MassID#y.d=rdifmr.d*DiffuY.d
        CollideR(MassID#)
      Else:ddif.d=Sqr(rdif.d*rdif.d+udif.d*udif.d)-M(MassID#)\radius
        If ddif.d<0
          incl.d=myATan2(udif.d,-rdif.d)
          DiffuX.d=Cos(incl):DiffuY.d=Sin(incl.d); <- Vector unidad del sentido del choque.
          Unclip#MassID#x.d=ddif.d*DiffuX.d:Unclip#MassID#y.d=ddif.d*DiffuY.d
          Rightvx.d=-Capsule#MassID#x:Rightvy.d=-Capsule#MassID#y
          CollideR(MassID#)
          Rightvx.d=-Capsule#MassID#y:Rightvy.d=Capsule#MassID#x
          CollideD(MassID#)
        EndIf
      EndIf
    EndIf
  Else; <- Si la bola está a la izquierda:
    If Ball#MassID#udist>=0; <- Si la bola está a la izquierda y arriba:
      rdif.d=-Ball#MassID#rdist-M(0)\HalfWidth:rdifmr.d=rdif.d-M(MassID#)\radius
      udif.d=Ball#MassID#udist-M(0)\HalfHeight:udifmr.d=udif.d-M(MassID#)\radius
      If udifmr<=0 And rdif<=0; <- Si hay colisión contra la arista de arriba:
        Rightvx.d=Capsule#MassID#y:Rightvy.d=-Capsule#MassID#x
        angle.d-Abs(omega.d); <- to unclip
        DiffuX.d=-Capsule#MassID#y:DiffuY.d=Capsule#MassID#x; <- Vector unidad del sentido del choque.
        Unclip#MassID#x.d=udifmr*DiffuX.d:Unclip#MassID#y.d=udifmr*DiffuY.d
        CollideU(MassID#)
      ElseIf rdifmr<=0 And udif<=0; <- Si hay colisión contra la arista izquierda:
        Rightvx.d=Capsule#MassID#x:Rightvy.d=Capsule#MassID#y
        angle.d+Abs(omega.d); <- to unclip
        DiffuX.d=Capsule#MassID#x:DiffuY.d=Capsule#MassID#y; <- Vector unidad del sentido del choque.
        Unclip#MassID#x.d=rdifmr.d*DiffuX.d:Unclip#MassID#y.d=rdifmr.d*DiffuY.d
        CollideL(MassID#)
      Else:ddif.d=Sqr(rdif.d*rdif.d+udif.d*udif.d)-M(MassID#)\radius
        If ddif.d<0
          incl=myATan2(-udif,rdif)
          DiffuX.d=Cos(incl):DiffuY.d=Sin(incl); <- Vector unidad del sentido del choque.
          Unclip#MassID#x.d=ddif*DiffuX.d:Unclip#MassID#y.d=ddif*DiffuY.d
          Rightvx.d=Capsule#MassID#x:Rightvy.d=Capsule#MassID#y
          CollideL(MassID#)
          Rightvx.d=Capsule#MassID#y:Rightvy.d=-Capsule#MassID#x
          CollideU(MassID#)
        EndIf
      EndIf
    Else; <- Si la bola está a la izquierda y abajo:
      rdif.d=-Ball#MassID#rdist-M(0)\HalfWidth:rdifmr.d=rdif.d-M(MassID#)\radius
      udif.d=-Ball#MassID#udist-M(0)\HalfHeight:udifmr.d=udif.d-M(MassID#)\radius
      If udifmr<=0 And rdif<=0; <- Si hay colisión contra la arista de abajo:
        Rightvx.d=Capsule#MassID#y:Rightvy.d=-Capsule#MassID#x
        angle.d+Abs(omega.d); <- to unclip
        DiffuX.d=Capsule#MassID#y:DiffuY.d=-Capsule#MassID#x; <- Vector unidad del sentido del choque.
        Unclip#MassID#x.d=udifmr*DiffuX.d:Unclip#MassID#y.d=udifmr*DiffuY.d
        CollideD(MassID#)
      ElseIf rdifmr.d<=0 And udif.d<=0; <- Si hay colisión contra la arista izquierda:
        Rightvx.d=-Capsule#MassID#x:Rightvy.d=-Capsule#MassID#y
        angle.d-Abs(omega.d); <- to unclip
        DiffuX.d=Capsule#MassID#x:DiffuY.d=Capsule#MassID#y; <- Vector unidad del sentido del choque.
        Unclip#MassID#x.d=rdifmr.d*DiffuX.d:Unclip#MassID#y.d=rdifmr.d*DiffuY.d
        CollideL(MassID#)
      Else:ddif.d=Sqr(rdif.d*rdif.d+udif.d*udif.d)-M(MassID#)\radius
        If ddif.d<0
          incl.d=myATan2(udif.d,rdif.d)
          DiffuX.d=Cos(incl):DiffuY.d=Sin(incl.d); <- Vector unidad del sentido del choque.
          Unclip#MassID#x.d=ddif.d*DiffuX.d:Unclip#MassID#y.d=ddif.d*DiffuY.d
          Rightvx.d=-Capsule#MassID#x:Rightvy.d=-Capsule#MassID#y
          CollideL(MassID#)
          Rightvx.d=Capsule#MassID#y:Rightvy.d=-Capsule#MassID#x
          CollideD(MassID#)
        EndIf
      EndIf
    EndIf
  EndIf
EndMacro
;-INITS:
#DEGTORAD=#PI/180.0:#RADTODEG=180.0/#PI
bitplanes.b=32
SCREENWIDTH.l=GetSystemMetrics_(#SM_CXSCREEN)
SCREENHEIGHT.l=GetSystemMetrics_(#SM_CYSCREEN)
If InitMouse()=0 Or InitSprite()=0 Or InitKeyboard()=0
  MessageRequester("Error","Can't access DirectX",0):End
EndIf
While OpenScreen(SCREENWIDTH,SCREENHEIGHT,bitplanes.b,"")=0
  If bitplanes.b>16:bitplanes.b-8
  ElseIf SCREENHEIGHT>600:SCREENWIDTH=800:SCREENHEIGHT=600
  ElseIf SCREENHEIGHT>480:SCREENWIDTH=640:SCREENHEIGHT=480
  ElseIf SCREENHEIGHT>400:SCREENWIDTH=640:SCREENHEIGHT=400
  ElseIf SCREENHEIGHT>240:SCREENWIDTH=320:SCREENHEIGHT=240
  ElseIf SCREENHEIGHT>200:SCREENWIDTH=320:SCREENHEIGHT=200
  Else:MessageRequester("Listen:","Can't open Screen!",0):End
  EndIf
Wend
Structure Masa
  mass.d
  x.d:y.d
  mx.d:my.d
  radius.d
  HalfWidth.d
  HalfHeight.d
EndStructure
#nummasses=3
Global Dim M.Masa(#nummasses-1)
M(0)\radius=256
M(0)\HalfWidth=M(0)\radius:M(0)\HalfHeight=M(0)\HalfWidth/20
M(1)\radius=M(0)\radius/16
M(2)\radius=M(0)\radius/16
#BallmovRadiusprop=0.9
CreateSprite(0,M(0)\radius*2,M(0)\radius*2); <- Disco cápsula frontal
StartDrawing(SpriteOutput(0))
BackColor(0)
Box(0,M(0)\radius-M(0)\HalfHeight,M(0)\HalfWidth*2,M(0)\HalfHeight*2,$6699DD)
For t.l=1 To M(0)\HalfHeight
  Box(t,M(0)\radius-M(0)\HalfHeight+t,M(0)\HalfWidth*2-2*t,M(0)\HalfHeight*2-2*t,$6699DD-t*16)
Next
Circle(M(0)\radius,M(0)\radius,3,$FAFAFA)
StopDrawing()
CreateBallSprite(1,M(1)\radius*2,$BBAA44); <- particula 1
CreateBallSprite(2,M(2)\radius*2,$AA8833); <- particula 2
;
angle.d=0:angledeg.d=angle.d*#RADTODEG; <- Initial inclination
angularforce.d=0.01333; <- Initial Force Momentum
omega.d=0.0;01; <- Initial Angular speed
alpha.d=0; <- Initial Angular acceleration
;
M(0)\x=SCREENWIDTH/2:M(0)\y=SCREENHEIGHT/2;<-Posición inicial de la cápsula
M(1)\x=SCREENWIDTH/2-150:M(1)\y=SCREENHEIGHT/2-201; <- Posición inicial de la masa intracápsula1 (Ball1)
M(2)\x=SCREENWIDTH/2-220:M(2)\y=SCREENHEIGHT/2+200; <- Posición inicial de la masa intracápsula2 (Ball2)
M(0)\mass=40; <- Masa de la cápsula
M(1)\mass=40; <- Masa de la Ball1
M(2)\mass=40; <- Masa de la Ball2
;-MAIN:
Repeat
  ExamineKeyboard():ExamineMouse():ClearScreen($250938)
  RotateSprite(0,angledeg.d,#PB_Absolute);<- cápsula
  DisplayTransparentSprite(0,M(0)\x-M(0)\radius,M(0)\y-M(0)\radius,200); <- cápsula
  DisplayTransparentSprite(1,M(1)\x-M(1)\radius,M(1)\y-M(1)\radius); <- particula interna
  DisplayTransparentSprite(2,M(2)\x-M(2)\radius,M(2)\y-M(2)\radius); <- particula externa
  ;
  ;;;;;;;;;;;;;;;;;;;;;;;Mouse buttons. If no mousebuttons are pressed, means that it leaves at dead-point
  If MouseButton(1); <- Acceleration happens to all:
    angularforce.d-1
    alpha.d=angularforce.d/(M(1)\mass*M(0)\radius*M(0)\radius+M(2)\mass*M(0)\radius*M(0)\radius)
    omega.d+alpha.d
  ElseIf MouseButton(2); <- Acceleration happens to all:
    angularforce.d+1
    alpha.d=angularforce.d/(M(1)\mass*M(0)\radius*M(0)\radius+M(2)\mass*M(0)\radius*M(0)\radius)
    omega.d+alpha.d
  ElseIf KeyboardReleased(#PB_Key_F5)
    M(0)\x=SCREENWIDTH/2:M(0)\y=SCREENHEIGHT/2;<-Posición inicial de la cápsula
    M(1)\x=SCREENWIDTH/2-150:M(1)\y=SCREENHEIGHT/2-201; <- Posición inicial de la masa intracápsula1 (Ball1)
    M(2)\x=SCREENWIDTH/2-220:M(2)\y=SCREENHEIGHT/2+200; <- Posición inicial de la masa intracápsula2 (Ball2)
    M(0)\mx=0
    M(0)\my=0
    M(1)\mx=0
    M(1)\my=0
    M(2)\mx=0
    M(2)\my=0
    alpha.d=0
    omega.d=0
    angularforce.d=0
    angledeg.d=0
    angle.d=0
  EndIf
  ;Mouse move:
  mousedeltax.l=MouseDeltaX():mousedeltay.l=MouseDeltaY()
  M(2)\my+mousedeltay.l/40
  M(1)\my-mousedeltay.l/40
  ;;;;;;;;;;;;;;;;;;;;;;;Update angles:
  angle.d=WrapAngle(angle.d+omega.d):angledeg.d=angle.d*#RADTODEG
  BallOuter(2); <- particula externa
  BallOuter(1); <- particula interna
  ;;;;;;;;;;Actualización de las posiciones:
  M(0)\x+M(0)\mx
  M(0)\y+M(0)\my
  M(1)\x+M(1)\mx
  M(1)\y+M(1)\my
  M(2)\x+M(2)\mx
  M(2)\y+M(2)\my
  ;Screen limits:
  For t.l=0 To #nummasses-1
    If M(t)\x<0:M(t)\mx=Abs(M(t)\mx):ElseIf M(t)\x>SCREENWIDTH:M(t)\mx=-Abs(M(t)\mx):EndIf
    If M(t)\y<0:M(t)\my=Abs(M(t)\my):ElseIf M(t)\y>SCREENHEIGHT:M(t)\my=-Abs(M(t)\my):EndIf
  Next
  ;
  If KeyboardReleased(#PB_Key_Space):While KeyboardReleased(#PB_Key_Space)=0:Delay(20):ExamineKeyboard():Wend:EndIf
  FlipBuffers():Delay(4)
Until KeyboardPushed(#PB_Key_Escape)
CloseScreen()
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
Post Reply