Author Topic: [NXT] Physics help needed!  (Read 3623 times)

0 Members and 1 Guest are viewing this topic.

Offline nxtboy III

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 795
  • Rating: +26/-1
  • NXT!
    • View Profile
    • Program NXT
[NXT] Physics help needed!
« on: September 29, 2012, 02:39:51 pm »
Hi,
I am making a little physics "engine" for my NXT Robot.
So far I have a lot of things covered, like gravity, velocity, bouncing, etc.
Except the problem is, is that when 2 objects collide, a lot of times they seem to get stuck together, so it takes a large velocity to break that bond. Also, if the player collides with another object from the top (Player on top, object on bottom), it seems to stop moving (It doesnt even bounce, and it should), but its Y velocity is still very low, even though it should be at 0.
BTW, This program was made possible by BuilderBoy (Thanks :D).

Here's my code:
Code: [Select]
//Made by NXT with major physics help from BuilderBoy

#define LEFT_OF_SCREEN_X 0
#define RIGHT_OF_SCREEN_X 99
#define TOP_OF_SCREEN_Y 63
#define BOTTOM_OF_SCREEN_Y 0
#define SCREEN_WIDTH 100
#define SCREEN_HEIGHT 64

#define TOTAL_OBJECTS 5

#define BOUNCE (0.5)
#define GRAVITY -0.2
#define FRICTION 0.3


//define the object
struct object
{
 float X;
 float Y;
 int width;
 int height;
 float mass;
 float velX;
 float velY;
 //Displaying stuff
 byte DRAW_OPT;
};

object box[TOTAL_OBJECTS];

bool Collide(object ob1, object ob2)
{
   if(((trunc(ob1.X) + ob1.width + 1) >= ob2.X) && (trunc(ob1.X) <= (trunc(ob2.X) + ob2.width + 1)) &&
      ((trunc(ob1.Y) + ob1.height + 1) >= trunc(ob2.Y)) && (trunc(ob1.Y) <= (trunc(ob2.Y) + ob2.height + 1)))
   {
      return(true);
   }

   return(false);
}

float muldiv(float _input, float _interval)
{
 _input = floor(_input * _interval);
 return(_input / _interval);
}


task main()
{
 bool collided;
 //Setting variables for boxes
 for(int c=0; c < TOTAL_OBJECTS; c++)
 {
  box[c].X = (40) + Random(5);
  box[c].Y = Random(40);
  box[c].width = Random(6) + 2;
  box[c].height = Random(5) + 2;
  box[c].velX = Random(3) - 1;
  box[c].velY = Random(2) - 1;
  box[c].mass = Random(4) + 1;
 }
 while(1)
 {
  collided = 0;
  for(int c=0; c < TOTAL_OBJECTS; c++)
  {
   for(int d=0; d < TOTAL_OBJECTS; d++)
   {
    if(d != c)
    {
     if(Collide(box[c],box[d]))
     {
      box[c].X = (40) + Random(5);
      box[c].Y = Random(40);
      collided = 1;
     }
    }
   }
  }
  if(collided == 0)
   break;
 }
 float backupBoxX;
 float backupBoxY;
 float backupBoxX2;
 float backupBoxY2;
 float backupVelX;
 float backupVelY;
 float backupVelX2;
 float backupVelY2;
 box[0].DRAW_OPT = DRAW_OPT_FILL_SHAPE | DRAW_OPT_LOGICAL_XOR;
 box[0].mass = 3;
 while(true)
 {
  SetDisplayFlags(DISPLAY_REFRESH_DISABLED);
  ClearScreen();
  if(ButtonPressed(BTNCENTER,0))
  {
   box[0].velY += 0.6;
  }
  else if(ButtonPressed(BTNEXIT,0))
  {
   box[0].velY -= 0.6;
  }
  if(ButtonPressed(BTNRIGHT,0))
  {
   box[0].velX += 0.6;
  }
  if(ButtonPressed(BTNLEFT,0))
  {
   box[0].velX -= 0.6;
  }
  //Processing for each box and displaying
  for(int c=0; c < TOTAL_OBJECTS; c++)
  {
   //Backs up X and Y Coordinates for collision
   backupBoxX = box[c].X;
   backupBoxY = box[c].Y;
   //Calculating X and Y Coordinates
   box[c].velY += GRAVITY;
   backupVelY2 = box[c].velY;
   backupVelX2 = box[c].velX;
   box[c].X += box[c].velX;
   box[c].Y += box[c].velY;
   //Collisions with walls of screen
   if(box[c].Y <= BOTTOM_OF_SCREEN_Y) //Collide with bottom of screen
   {
    box[c].Y = backupBoxY;
    if(abs(box[c].velX) < FRICTION)
    {
     box[c].velX = 0;
    }
    else if(box[c].velX < 0)
    {
     box[c].velX += FRICTION;
    }
    else
    {
     box[c].velX -= FRICTION;
    }
    box[c].velY = -box[c].velY*BOUNCE;
   }
   if(box[c].Y + box[c].height >= TOP_OF_SCREEN_Y) //Collide with bottom of screen
   {
    box[c].Y = backupBoxY;
    box[c].velY = -box[c].velY*BOUNCE;
   }
   if(box[c].X <= LEFT_OF_SCREEN_X) //Collide with left of screen
   {
    box[c].X = backupBoxX;
    box[c].velX = -box[c].velX*BOUNCE;
   }
   if(box[c].X + box[c].width >= RIGHT_OF_SCREEN_X) //Collide with right of screen
   {
    box[c].X = backupBoxX;
    box[c].velX = -box[c].velX*BOUNCE;
   }
   //Collisions with other objects
   for(int d=0; d < TOTAL_OBJECTS; d++)
   {
    if(d != c)
    {
     if(Collide(box[c],box[d]))
     {
      box[c].X = backupBoxX;
      backupVelY = box[c].velY;
      backupVelX = box[c].velX;
      if(Collide(box[c],box[d]))
      {
       //Collision on Y axis
       box[c].Y = backupBoxY;
       box[c].velX = backupVelX2;
       box[c].velY = backupVelY2;
       //V1 = (C*M2*(V2-V1)+M1*V1+M2*V2)/(M1+M2)
       box[c].velY = (BOUNCE*box[d].mass*(box[d].velY - backupVelY) + box[c].mass*backupVelY + box[d].mass*box[d].velY)/(box[c].mass+box[d].mass);
       box[d].velY = (BOUNCE*box[c].mass*(backupVelY - box[d].velY) + box[d].mass*box[d].velY + box[c].mass*backupVelY)/(box[d].mass+box[c].mass);
      }
      else
      {
       //Collision on X axis
       box[c].velX = backupVelX2;
       box[c].velY = backupVelY2;
       box[c].Y = backupBoxY;
       box[c].velX = (BOUNCE*box[d].mass*(box[d].velX - backupVelX) + box[c].mass*backupVelX + box[d].mass*box[d].velX)/(box[c].mass+box[d].mass);
       box[d].velX = (BOUNCE*box[c].mass*(backupVelX - box[d].velX) + box[d].mass*box[d].velX + box[c].mass*backupVelX)/(box[d].mass+box[c].mass);
      }
     }
    }
   }
   RectOut(trunc(box[c].X),trunc(box[c].Y),box[c].width,box[c].height,box[c].DRAW_OPT);
  }
  SetDisplayFlags(DISPLAY_REFRESH | DISPLAY_ON);
  Wait(17); //Waits 17ms to refresh the screen
 }
}

And also, in the video the player is the black box.
And here's a video:
« Last Edit: September 29, 2012, 02:40:23 pm by nxtboy III »

Offline Builderboy

  • Physics Guru
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5673
  • Rating: +613/-9
  • Would you kindly?
    • View Profile
Re: [NXT] Physics help needed!
« Reply #1 on: September 29, 2012, 02:47:42 pm »
Mmm try this.  When two boxes collide on an axis, only move the box backwards along the axis on which it collided.

Offline nxtboy III

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 795
  • Rating: +26/-1
  • NXT!
    • View Profile
    • Program NXT
Re: [NXT] Physics help needed!
« Reply #2 on: September 29, 2012, 02:50:15 pm »
I am already doing that. If it collided on the Y axis, it only goes on that axis, see:
Code: [Select]
if(Collide(box[c],box[d]))
      {
       //Collision on Y axis
       box[c].Y = backupBoxY;
       box[c].velX = backupVelX2;
       box[c].velY = backupVelY2;
       //V1 = (C*M2*(V2-V1)+M1*V1+M2*V2)/(M1+M2)
       box[c].velY = (BOUNCE*box[d].mass*(box[d].velY - backupVelY) + box[c].mass*backupVelY + box[d].mass*box[d].velY)/(box[c].mass+box[d].mass);
       box[d].velY = (BOUNCE*box[c].mass*(backupVelY - box[d].velY) + box[d].mass*box[d].velY + box[c].mass*backupVelY)/(box[d].mass+box[c].mass);
      }

Offline Builderboy

  • Physics Guru
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5673
  • Rating: +613/-9
  • Would you kindly?
    • View Profile
Re: [NXT] Physics help needed!
« Reply #3 on: September 29, 2012, 03:13:12 pm »
No you are not.  On both axis you are moving the box's Y position back to where it was before.  To test the axis of collision you move the box backwards along the X axis.  These two actions combined result in the box moving all the way backwards no matter the axis of collision.

Offline nxtboy III

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 795
  • Rating: +26/-1
  • NXT!
    • View Profile
    • Program NXT
Re: [NXT] Physics help needed!
« Reply #4 on: September 29, 2012, 04:17:03 pm »
I'm confused. So am I supposed to only move the Y axis back on 1 axis? Or on none of them??

Offline Builderboy

  • Physics Guru
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5673
  • Rating: +613/-9
  • Would you kindly?
    • View Profile
Re: [NXT] Physics help needed!
« Reply #5 on: September 29, 2012, 04:26:00 pm »
The final result of the collision should result in the object only moving along an axis that was not collided on.  So if there was a collision on the x axis, the object does not move in the x direction.  Additionally,  why are you backing up the velocities and restoring them before a collision is processed?  You should let the velocities process naturally so that simultaneous collisions work better

Offline nxtboy III

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 795
  • Rating: +26/-1
  • NXT!
    • View Profile
    • Program NXT
Re: [NXT] Physics help needed!
« Reply #6 on: September 29, 2012, 04:29:05 pm »
Hmm.....
It works, but....
For some weird reason sometimes objects go through eachother!!