gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS Misc > Stylus & PAD-friendly GUI's

#141920 - keldon - Mon Oct 01, 2007 5:37 pm

How do you generally go about implementing GUI's on the DS where the user interface is more in the form of an application than a game in regards to GUI element navigation.

I could tackle it by allowing each screen to have both dynamic navigation hints, and to be able to read from a file. This is how I did my uni project; I edit not_so_easily_computable (or at least quicker to etch in GIMP) via SVG editing, and leave anything with a uniform arrangement down to algorithms. Of course you can also have a search method that will search for the best candidate in a particular direction using simple distance heuristics.

Having said that, I've just examined the approach used in Windows; it just goes for the shortest distance within 45 degrees in the direction you are aiming at!

#141969 - keldon - Tue Oct 02, 2007 5:34 pm

After a quick jot on the paper and examination of Windows' implementation, I decided that I might as well just write a simple search method. I haven't tested it with anything other than two items, but Windows appears to be doing nothing other than finding the nearest object clipped to a view of 45 degrees!

I've inserted the code in case anybody wanted to look at it (for whatever reason).
Code:
   GUI_OBJ* find_next_object ( DIRECTION direction, GUI_OBJ& current_object, GUI_OBJ** obj_list, int obj_list_cnt )
   {
      int min_dist = 1024*1024 + 1024*1024;   // The maximum distance should be 256*256 + 384*384
      GUI_OBJ* nearest_object = NULL;
      
      const int current_object_x = current_object.get_x() + (current_object.get_width()/2);
      const int current_object_y = current_object.get_y() + (current_object.get_height()/2);
      
      for ( int i = 0; i < obj_list_cnt; ++i )
      {
         GUI_OBJ& potential_object = *obj_list[i];
         DIRECTION current_direction;
         
         const int potential_object_x = potential_object.get_x() + (potential_object.get_width()/2);
         const int potential_object_y = potential_object.get_y() + (potential_object.get_height()/2);
         const int x = potential_object_x - current_object_x;
         const int y = potential_object_y - current_object_y;
         const int xx = x*x;
         const int yy = y*y;
         
         if ( &current_object == &potential_object )
         {
            continue;
         }
         
         /*
         *   Identify direction between current_object and potential_object
         */
         if ( (y>=0) & (xx<=yy) )
         {
            current_direction = DIR_DOWN;
         }
         else if ( (x>=0) & (yy<=xx) )
         {
            current_direction = DIR_RIGHT;
         }
         else if ( (y<0) & (xx<=yy) )
         {
            current_direction = DIR_UP;
         }
         else if ( (x<0) & (yy<=xx) )
         {
            current_direction = DIR_LEFT;
         }
         else
         {
            K_ASSERT(FALSE, "Direction of object is uncertain, which should be impossible!\n");
         }
         
         if ( current_direction != direction )
         {
            continue;
         }
         
         if ( (xx+yy) <= min_dist || (NULL == nearest_object) )
         {
            nearest_object = &potential_object;
            min_dist = xx+yy;
         }
      }
      
      return nearest_object;
   } // find_next_object (DIRECTION,GUI_OBJ&,GUI_OBJ**,int)

#145535 - keldon - Sat Nov 17, 2007 11:25 am

Although this is the type used in Windows it does provide some odd behaviour which may not be desirable for gui navigation.

I haven't put it here, but my code is updated to alter the distance of along a particular plane based on the direction (while still keeping the 45 degree window). I multiplied the distance in the direction adjacent to where you are facing by 10.