/[enigma]/enigma/src/world.cc
ViewVC logotype

Diff of /enigma/src/world.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.65 by reallysoft, Mon Jul 21 08:21:35 2003 UTC revision 1.66 by dheck, Tue Aug 12 18:28:05 2003 UTC
# Line 261  V2 RubberBand::get_p2() const Line 261  V2 RubberBand::get_p2() const
261          return stone->get_pos().center();          return stone->get_pos().center();
262  }  }
263    
   
   
264  //----------------------------------------  //----------------------------------------
265  // Field  // Field
266  //----------------------------------------  //----------------------------------------
# Line 324  namespace Line 322  namespace
322  StoneContact::StoneContact(Actor *a, GridPos p,  StoneContact::StoneContact(Actor *a, GridPos p,
323                             const V2 &cp, const V2 &n)                             const V2 &cp, const V2 &n)
324  : actor(a), stonepos(p),  : actor(a), stonepos(p),
325    response(STONE_REBOUND),    response(STONE_PASS),
326    contact_point(cp),    contact_point(cp),
327    normal(n),    normal(n),
328    is_collision(false),    is_collision(false),
329    fake_collision(false),    fake_collision(false),
330      new_collision(false),
331    is_contact(true)    is_contact(true)
332  {}  {}
333    
334  StoneContact::StoneContact()  StoneContact::StoneContact()
335  : is_collision(false),  : is_collision(false),
336    fake_collision(false),    fake_collision(false),
337      new_collision(false),
338    is_contact(false)    is_contact(false)
339  {}  {}
340    
# Line 519  enigma::Timer world::g_timer; Line 519  enigma::Timer world::g_timer;
519  //      PUZZLE SCRAMBLING  //      PUZZLE SCRAMBLING
520  //======================================================================  //======================================================================
521    
522  void WorldImpl::add_scramble(GridPos p, Direction dir) {  void WorldImpl::add_scramble(GridPos p, Direction dir)
523    {
524      // fprintf(stderr, "scrambles.size()=%i ; add_scramble(%i, %i, %s)\n", scrambles.size(), p.x, p.y, to_suffix(dir).c_str());      // fprintf(stderr, "scrambles.size()=%i ; add_scramble(%i, %i, %s)\n", scrambles.size(), p.x, p.y, to_suffix(dir).c_str());
525      scrambles.push_back(Scramble(p, dir, scrambleIntensity));      scrambles.push_back(Scramble(p, dir, scrambleIntensity));
526  }  }
527  void WorldImpl::scramble_puzzles() {  
528    void WorldImpl::scramble_puzzles()
529    {
530      // fprintf(stderr, "scramble_puzzles: scrambles.size()=%i\n", scrambles.size());      // fprintf(stderr, "scramble_puzzles: scrambles.size()=%i\n", scrambles.size());
531      while (!scrambles.empty()) {      while (!scrambles.empty()) {
532          list<Scramble>::iterator i = scrambles.begin();          list<Scramble>::iterator i = scrambles.begin();
# Line 617  get_accel (Actor *a, const V2 & x, const Line 620  get_accel (Actor *a, const V2 & x, const
620      }      }
621    
622      ActorInfo *ai = a->get_actorinfo();      ActorInfo *ai = a->get_actorinfo();
623      f += ai->forceacc;      f += ai->force;
624    
625      return f / ai->mass;      return f / ai->mass;
626  }  }
# Line 647  advance_actor(Actor *a, double time, dou Line 650  advance_actor(Actor *a, double time, dou
650     with information about the closest feature on the stone and     with information about the closest feature on the stone and
651     `is_contact' is set to false. */     `is_contact' is set to false. */
652  static void  static void
653  find_contact_with_stone(Actor *a, StoneContact &contact, int x, int y)  find_contact_with_stone (Actor *a, StoneContact &contact, int x, int y)
654  {  {
655      contact.actor = a;      contact.actor      = a;
656      contact.stonepos = GridPos(x, y);      contact.stonepos   = GridPos(x, y);
657      contact.is_contact = false;      contact.is_contact = false;
658    
659      Stone *stone = world::GetStone(contact.stonepos);      Stone *stone = world::GetStone(contact.stonepos);
# Line 710  find_contact_with_stone(Actor *a, StoneC Line 713  find_contact_with_stone(Actor *a, StoneC
713          contact.normal        = normalize(b);          contact.normal        = normalize(b);
714          contact.contact_point = corner + contact.normal*erad;          contact.contact_point = corner + contact.normal*erad;
715      }      }
716        
717      contact.is_collision  = contact.normal*ai.vel < 0;      contact.is_collision  = contact.normal*ai.vel < 0;
718      contact.response = stone->collision_response(contact);      contact.response = stone->collision_response(contact);
719      contact.sound = stone->collision_sound();      contact.sound = stone->collision_sound();
# Line 717  find_contact_with_stone(Actor *a, StoneC Line 721  find_contact_with_stone(Actor *a, StoneC
721    
722  /* Enigma's stones have rounded corners; this leads to realistic  /* Enigma's stones have rounded corners; this leads to realistic
723     behaviour when a marble rebounds from the corner of a single stone.     behaviour when a marble rebounds from the corner of a single stone.
724     But it's annyoing when there are two adjacent stones and a marble     But it's annoying when there are two adjacent stones and a marble
725     rebounds from any one (or even both) corners, because it changes     rebounds from any one (or even both) corners, because it changes
726     the direction of the marble quite unpredictably.     the direction of the marble quite unpredictably.
727    
# Line 792  find_stone_contacts (Actor *a, StoneCont Line 796  find_stone_contacts (Actor *a, StoneCont
796     these functions.  (Incidentally, this is why StoneContact only     these functions.  (Incidentally, this is why StoneContact only
797     contains a 'stonepos' and no 'stone' entry.)     contains a 'stonepos' and no 'stone' entry.)
798  */  */
799  static V2  static void
800  handle_stone_contact(V2 normal, StoneContact &sc)  handle_stone_contact (StoneContact &sc, double total_dtime)
801  {  {
802      Actor *a = sc.actor;      Actor *a = sc.actor;
803      ActorInfo *ai = a->get_actorinfo();      ActorInfo &ai = *a->get_actorinfo();
804    
805      if (sc.is_collision) {      if (sc.is_collision) {
806          if (Stone *stone = world::GetStone(sc.stonepos))          if (!sc.fake_collision && sc.response == STONE_REBOUND) {
807              stone->actor_hit(sc);              
808          if (!sc.fake_collision && sc.response != STONE_PASS) {              bool new_collision = false;
809              normal += sc.normal;              if (total_dtime != 0) {
810              normal /= length(normal);                  double vn = (ai.pos - ai.last_pos)/total_dtime * sc.normal;
811                    new_collision = (vn < -0.5);
812              if (length(ai->vel) > 0.1) {              }
813                
814                if (new_collision) {
815                    if (Stone *stone = world::GetStone(sc.stonepos))
816                        stone->actor_hit(sc);
817    //             if (length(ai->vel) > 0.1) {
818                  display::AddEffect (sc.contact_point, "ring-anim");                  display::AddEffect (sc.contact_point, "ring-anim");
819                  sound::PlaySound(sc.sound.c_str(), sc.contact_point);                  sound::PlaySound(sc.sound.c_str(), sc.contact_point);
820    //             }
821              }              }
822                double restitution = 0.8;
823                ai.vel -= (1 + restitution)*(ai.vel*sc.normal)*sc.normal;
824                ai.pos = ai.oldpos;         // Reset actor position
825          }          }
826      }      }
827      else if (sc.is_contact) {      else if (sc.is_contact) {
828          if (Stone *stone = world::GetStone(sc.stonepos))          if (Stone *stone = world::GetStone(sc.stonepos))
829              stone->actor_contact(sc.actor);              stone->actor_contact(sc.actor);
830      }      }
     return normal;  
831  }  }
832    
833  static void  static void
834  handle_contacts(Actor *a)  handle_contacts(Actor *a, double total_dtime)
835  {  {
836      ActorInfo &a1 = *a->get_actorinfo();      ActorInfo &a1 = *a->get_actorinfo();
837    
# Line 828  handle_contacts(Actor *a) Line 840  handle_contacts(Actor *a)
840      */      */
841      StoneContactList cl;      StoneContactList cl;
842      find_stone_contacts(a, cl);      find_stone_contacts(a, cl);
843      if (!cl.empty()) {      for (StoneContactList::iterator i=cl.begin();
844          V2 normal = accumulate(cl.begin(), cl.end(), V2(), handle_stone_contact);           i != cl.end(); ++i)
845        {
846          double n = length(normal);          handle_stone_contact (*i, total_dtime);
         if (n != 0) {  
             double restitution = 0.8;  
             normal /= n;  
             a1.vel -= (1 + restitution)*(a1.vel*normal)*normal;  
         }  
847      }      }
848    
849      /*      /*
# Line 858  handle_contacts(Actor *a) Line 865  handle_contacts(Actor *a)
865          bool contactp = length(p1-p2) < r1+r2;          bool contactp = length(p1-p2) < r1+r2;
866          if (contactp)          if (contactp)
867          {          {
868              V2 n  = normalize(p1-p2); // normal to contact surface              V2 n  = normalize(p1-p2);   // normal to contact surface
869              V2 v1 = n * (a1.vel*n);              V2 v1 = n * (a1.vel*n);
870              V2 v2 = n * (a2.vel*n);              V2 v2 = n * (a2.vel*n);
871    
872                a1.pos = a1.oldpos;         // Reset actor position
873                
874              bool collisionp = (v2-v1)*(p2-p1) < 0;              bool collisionp = (v2-v1)*(p2-p1) < 0;
875              if (collisionp) {              if (collisionp) {
876                  double m2 = a2.mass;                  double m2 = a2.mass;
# Line 884  static void Line 893  static void
893  tick_actor(Actor *a, double dtime)  tick_actor(Actor *a, double dtime)
894  {  {
895      ActorInfo &ai = * a->get_actorinfo();      ActorInfo &ai = * a->get_actorinfo();
896    
897        ai.last_pos = ai.pos;
898      ai.oldpos = ai.pos;      ai.oldpos = ai.pos;
899      ai.oldvel = ai.vel;      ai.oldvel = ai.vel;
900    
901      double rest_time = dtime;      double rest_time = dtime;
902      double dt = 0.005; //dtime;      double dt = 0.005; //dtime;
903    
904      handle_contacts(a);      handle_contacts(a, 0.0);
905      while (rest_time > 0 && !ai.grabbed)      while (rest_time > 0 && !ai.grabbed)
906      {      {
907          advance_actor(a, dtime-rest_time, dt);          advance_actor(a, dtime-rest_time, dt);
# Line 907  tick_actor(Actor *a, double dtime) Line 918  tick_actor(Actor *a, double dtime)
918    
919          // ok, accept this step          // ok, accept this step
920          a->move();          a->move();
         handle_contacts(a);  
   
921          rest_time -= dt;          rest_time -= dt;
922    
923            handle_contacts(a, dtime-rest_time);
924    
925          ai.oldpos  = ai.pos;          ai.oldpos  = ai.pos;
926          ai.oldvel  = ai.vel;          ai.oldvel  = ai.vel;
927    
# Line 1592  world::Tick(double dtime) Line 1604  world::Tick(double dtime)
1604    
1605      timeaccu += dtime;      timeaccu += dtime;
1606    
1607      while (timeaccu >= timestep) {      while (timeaccu >= timestep)
1608        {
1609            // Move actors
1610          for (ActorList::iterator i=level->actorlist.begin(); i!=level->actorlist.end(); ++i) {          for (ActorList::iterator i=level->actorlist.begin(); i!=level->actorlist.end(); ++i) {
1611              ActorInfo *ai = (*i)->get_actorinfo();              ActorInfo *ai = (*i)->get_actorinfo();
1612              if (!ai->grabbed && !(*i)->is_dead())              if (!ai->grabbed && !(*i)->is_dead())
1613              {              {
1614                    ai->force= ai->forceacc;
1615                    ai->forceacc = V2();
1616                  tick_actor(*i, timestep);                  tick_actor(*i, timestep);
1617              }              }
             ai->forceacc = V2();  
1618          }          }
1619    
1620          /* Handle delayed impulses */          // Handle delayed impulses
1621          for (ImpulseList::iterator i = delayed_impulses.begin(); i != delayed_impulses.end(); ) {          for (ImpulseList::iterator i = delayed_impulses.begin(); i != delayed_impulses.end(); ) {
1622              // should the impulse take effect now ?              // should the impulse take effect now ?
1623              if (i->tick(timestep)) {              if (i->tick(timestep)) {

Legend:
Removed from v.1.65  
changed lines
  Added in v.1.66

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26