ROBOTC.net forums
http://robotc.net/forums/

Physics Game
http://robotc.net/forums/viewtopic.php?f=15&t=5562
Page 1 of 1

Author:  Coder A [ Fri Mar 01, 2013 4:55 pm ]
Post subject:  Physics Game

This is a little program I made up a couple of days ago. It's a projectile motion simulator, and it is still in its infancy, but I hope to improve it soon. Here's the first version:

Code:
typedef struct
{
   // Sz means sub zero.  Cu means current.
   short xpossz; // X position of object at last interference
   short ypossz; // Y position of object at last interference
   float velosz; // velocity of object at last interference
   short thetsz; // angle of travel at last interference
   short timdif; //
   short xposcu; // current X position
   short yposcu; // current Y position
   float velocu; // current total velocity
   short thetcu; // current angle of travel
   float velxcu; // current X velocity
   float velycu; // current Y velocity
}
projectile;

const float g = -9.8;

short degrees = 30;

task get_theta()
{
   while(true)
   {
      while(nNxtButtonPressed!=kLeftButton&&nNxtButtonPressed!=kRightButton)
      {}
      while(nNxtButtonPressed==kLeftButton)
      {
         degrees++;
         if(degrees==360)
            degrees = 0;
         wait10Msec(5);
      }
      while(nNxtButtonPressed==kRightButton)
      {
         degrees--;
         if(degrees==-1)
            degrees = 359;
         wait10Msec(5);
      }
      while(nNxtButtonPressed!=kNoButton)
      {}
   }
}

task main()
{
   nNxtExitClicks = 2;
   projectile p1;
   p1.xpossz = 10;
   p1.ypossz = 10;
   p1.timdif = 0;
   p1.velosz = 40;
   StartTask(get_theta);
   short targetx;
   short targety;
   while(nNxtButtonPressed!=kExitButton)
   {
      targetx = abs(rand())%100;
      targety = abs(rand())%64;
      while(nNxtButtonPressed!=kEnterButton)
      {
         eraseDisplay();
         nxtDrawCircle(targetx-6,targety+6,12);
         nxtDrawLine(p1.xpossz,p1.ypossz,(cosDegrees(degrees)*10)+p1.xpossz,(sinDegrees(degrees)*10)+p1.ypossz);
         nxtDisplayStringAt(0,7,"%d",degrees);
         wait10Msec(1);
      }
      eraseDisplay();
      nxtDrawCircle(targetx-6,targety+6,12);
      p1.thetsz = degrees;
      ClearTimer(T1);
      p1.xposcu = p1.xpossz;
      p1.yposcu = p1.ypossz;
      float time;
      while(p1.xposcu>-1&&p1.xposcu<100&&p1.yposcu>-1&&pow(p1.xposcu-targetx,2)+pow(p1.yposcu-targety,2)>25)
      {
         time = (float)time1[T1]/1000;
         p1.xposcu = round(((p1.velosz*cosDegrees(p1.thetsz)*time)+p1.xpossz));
         p1.yposcu = round((((g*(time*time))/2)+(p1.velosz*sinDegrees(p1.thetsz)*time)+p1.ypossz));
         nxtSetPixel(p1.xposcu,p1.yposcu);
      }
      if(pow(p1.xposcu-targetx,2)+pow(p1.yposcu-targety,2)<=25)
         nxtDisplayStringAt(0,63,":)");
      else
         nxtDisplayStringAt(0,63,":(");
      nxtDisplayStringAt(69,7,"Next>");
      while(nNxtButtonPressed==kNoButton)
      {}
   }
   StopAllTasks();
}



Gameplay:

1. Use the arrow buttons to aim at the target(circle).
2. Press enter to fire.
3. You get a smile for a hit, and a frown for a miss.
4. Press right to play again.

Like I said, It is very primitive. More stuff will hopefully come soon!

Author:  JohnWatson [ Fri Mar 01, 2013 5:04 pm ]
Post subject:  Re: Physics Game

This is pretty awesome; I just tried it out and it worked flawlessly. How long did it take you to come up with this?

Author:  Coder A [ Fri Mar 01, 2013 5:08 pm ]
Post subject:  Re: Physics Game

Thanks! It took an evening and a morning. I'm planning to incorporate rebounding off walls; then, I'll create levels and make it a full-blown game. That, however, could take a while :)

Author:  JohnWatson [ Fri Mar 01, 2013 5:19 pm ]
Post subject:  Re: Physics Game

Definitely keep us updated; once you have it at a state you're comfortable with, we would like to publish it on our blog (with your permission, of course).

Author:  Coder A [ Fri Mar 01, 2013 5:22 pm ]
Post subject:  Re: Physics Game

Neat! Yes, I will continue to post updated versions to this topic. You have my permission!

Author:  mightor [ Sat Mar 02, 2013 2:11 am ]
Post subject:  Re: Physics Game

Hey, that is very cool! I like the trace of the "bullet" as it travels. Nice work!

= Xander

Author:  Coder A [ Sat Mar 02, 2013 9:31 am ]
Post subject:  Re: Physics Game

Thank you! The trace of the bullet is basically where the bullet used to be, so as long as the screen is not erased the trace automatically stays up. It would actually be harder to get rid of the trace or have a trace of x length, but that's what I'm shooting for.


Updates coming soon!

Author:  Coder A [ Thu Apr 11, 2013 5:48 pm ]
Post subject:  Re: Physics Game

Coder A wrote:
Updates coming soon!



O.K. , so I guess I spoke too "soon" ! :-) But, here is some more:

Code:
typedef struct
{
   // Sz means sub zero.  Cu means current.
   short xpossz; // X position of object at last interference
   short ypossz; // Y position of object at last interference
   float velosz; // velocity of object at last interference
   float velxsz; // X velocity of object at last interference
   float velysz; // Y velocity of object at last interference
   short thetsz; // angle of travel at last interference
   float timdif; // used in computing timecu
   float timecu; // time since last interference
   short xposcu; // current X position
   short yposcu; // current Y position
   float velocu; // current total velocity
   short thetcu; // current angle of travel
   float velxcu; // current X velocity
   float velycu; // current Y velocity
   bool intrsct; // if projectile is on wall
   float gysz;   // g force felt by object along y axis at last interference
   float gxsz;   // g force felt by object along x axis at last interference
   float gycu;   // g force felt by object along y axis currently
   float gxcu;   // g force felt by object along x axis currently
}
projectile;

const float g = -9.8;

short degrees = 30;

task get_theta()
{
   while(true)
   {
      while(nNxtButtonPressed!=kLeftButton&&nNxtButtonPressed!=kRightButton)
      {}
      while(nNxtButtonPressed==kLeftButton)
      {
         degrees++;
         if(degrees==360)
            degrees = 0;
         wait10Msec(5);
      }
      while(nNxtButtonPressed==kRightButton)
      {
         degrees--;
         if(degrees==-1)
            degrees = 359;
         wait10Msec(5);
      }
      while(nNxtButtonPressed!=kNoButton)
      {}
   }
}

//---------------------------------------------------------------------------------------------------------------------//

short get_thetcu(float velx, float vely)
{
   short thetcugot =
   velx == 0 ?
      vely < 0 ?
         270 :
         90
   :
      velx < 0 ?
         round(radiansToDegrees(atan(vely/velx))+180) :
         round(radiansToDegrees(atan(vely/velx)));
   if(thetcugot < 0)
      thetcugot += 360;
   return thetcugot;
}

//---------------------------------------------------------------------------------------------------------------------//

void get_gs(projectile proj)
{
   if(proj.xposcu<=32)
   {
      proj.gycu = 1*g;
      proj.gxcu = 0;
   }
   else
   {
      if(proj.xposcu>=33&&proj.xposcu<=66)
      {
         proj.gycu = 0;
         proj.gxcu = 0;
      }
      else
      {
         if(proj.xposcu>=67)
         {
            proj.gycu = 0;
            proj.gxcu = 2 * g;
         }
      }
   }
}

//---------------------------------------------------------------------------------------------------------------------//
projectile p1;
task main()
{
   nNxtExitClicks = 2;

   p1.xpossz = 10;
   p1.ypossz = 10;
   p1.timdif = 0;
   p1.velosz = 30;
   p1.gxcu   = 0;
   p1.gycu   = 1 * g;
   StartTask(get_theta);
   while(nNxtButtonPressed!=kEnterButton)
   {
      eraseDisplay();
      nxtDisplayStringAt(0,7,"%d",degrees);
      nxtInvertLine(p1.xpossz,p1.ypossz,(cosDegrees(degrees)*10)+p1.xpossz,(sinDegrees(degrees)*10)+p1.ypossz);
      wait10Msec(1);
   }
   StopTask(get_theta);
   alive();

   eraseDisplay();
   p1.thetsz = degrees;
   ClearTimer(T1);
   p1.xposcu = p1.xpossz;
   p1.yposcu = p1.ypossz;
   p1.gxcu = p1.gxsz;
   p1.gycu = p1.gysz;
   nxtDrawRect(0,63,99,0);

   while(nNxtButtonPressed!=kExitButton)
   {
      p1.velxsz = (float)p1.velosz*cosDegrees(p1.thetsz);
      p1.velysz = (float)p1.velosz*sinDegrees(p1.thetsz);

      while(p1.xposcu>=0&&p1.xposcu<=99&&p1.yposcu>=0&&p1.gycu==p1.gysz&&p1.gxcu==p1.gxsz)
      {
         p1.timecu = (float)((time1[T1]-p1.timdif)/1000);
         p1.xposcu = round(((p1.gxsz*p1.timecu*p1.timecu)/2)+(p1.velxsz*p1.timecu)+p1.xpossz);
         p1.yposcu = round(((p1.gysz*p1.timecu*p1.timecu)/2)+(p1.velysz*p1.timecu)+p1.ypossz);
         nxtSetPixel(p1.xposcu,p1.yposcu);
         get_gs(p1);
      }

      // Calculate new information.
      p1.xpossz = p1.xposcu;
      p1.ypossz = p1.yposcu;
      if(p1.thetsz<0)
         p1.thetsz += 360;
      p1.velxcu = p1.gxsz*p1.timecu+p1.velxsz;
      p1.velycu = p1.gysz*p1.timecu+p1.velysz;
      p1.gysz = p1.gycu;
      p1.gxsz = p1.gxcu;
      p1.thetsz = get_thetcu(p1.velxcu,p1.velycu);
      p1.velosz = round(sqrt(pow(p1.velxcu,2)+pow(p1.velycu,2)) * 0.99);
      p1.velxsz = (float)p1.velosz*cosDegrees(p1.thetsz);
      p1.velysz = (float)p1.velosz*sinDegrees(p1.thetsz);
      p1.timdif = time1[T1];
      // New information has been calculated.
   }

   StopAllTasks();
}


What got changed:

1. I have added the concept of different "gravity zones" on the screen. the first third has 1 y-g(g force felt along the y-axis) and 0 x-gs. The middle third has no gs at all. The rightmost third has 0 y-gs and 2 x-gs(the projectile curves back to the left).

2. More variables were added to the projectile struct compensate for the gravity zones.

3. I currently have not put the target functionality back into the game, but don't worry, it's just a matter of time(hopefully not that much time, heh heh).

I am sorry about the lack of comments. I do not promise to ever comment it.

Updates coming! (maybe not as soon as you'd like them!)

-Coder A

Page 1 of 1 All times are UTC - 5 hours [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/