Rockbox

  • Status Unconfirmed
  • Percent Complete
    0%
  • Task Type Patches
  • Category Games
  • Assigned To No-one
  • Operating System All players
  • Severity Low
  • Priority Very Low
  • Reported Version Daily build (which?)
  • Due in Version Undecided
  • Due Date Undecided
  • Votes
  • Private
Attached to Project: Rockbox
Opened by atwupack - 2008-06-03

FS#9068 - [chessbox] Playing with touchpad

This patch adds more touchpad functionality to the game. It is possible to play by selecting the pieces directly instead of using the simulated buttons.
The changes are:
1. Added touchpad_get_mode to the plugin API.
2. Added menu entry for touchpad devices the switch between button mode and direct mode.
3. The user’s default touchpad mode is save during start-up of the plugin and restored after quitting.
4. The direct input mode is set only during the game (not in menu or view).
5. Extended play loop to handle BUTTON_TOUCHPAD event.
6. A piece is selected by clicking twice on it, moving is also done by clicking the target field twice.

The patch has been tested on the COWON D2 and also seems to compile fine for devices w/o touchpad. The patch has been created with

svn diff -x -w apps > touch_chess.diff

in the root directory. It would be nice if someone could test this (also on non-touchpad devices) and give me some feedback (bugs and improvements).

Nice patch!

The way I see the best implementation for this is something like this:

[code]
function map_touch(…)
{
[GET X,Y]
if( button == (BUTTON_REPEAT|BUTTON_REL) )
{
[MOVE "TO-BE-MOVED" TO HERE]
return;
}

if(button & BUTTON_REPEAT)
{
[SELECT CURRENT ITEM AS TO-BE-MOVED ITEM]
}
elseif(button == BUTTON_REL) /* BUTTON_REL means release *after* short press */
{
[YOUR IMPLEMENTATION]
return;
}

[SHOW SQUARE AROUND SELECTED ITEM]
}
[/code]

This would allow selecting and moving pieces as you would do in real chess, but the problem is currently BUTTON_REPEAT & BUTTON_REL aren't available in the button driver for touch screens I think, only in action.c (through action_get_touchpad_press) which has to move to the button driver I presume.
I'll probably do this when I get my touchscreen device and/or free time.

I don't know which implementation should be used, but we could always implement the two merged, so yours will react on a BUTTON_TOUCHPAD|BUTTON_REL event while mine only handles BUTTON_REPEAT events.

Any thoughts on this?

I also have thought about implementing some kind of drag&drop input while implementing this. I have decided against it for two reasons:
1. I think it is quite easy to make an unwanted move using drag&drop (especially on the small screen). Even by selecting source and target position of the pieces, you sometimes still have problems to enter the move you want.
2. It was easier to be done as a first implementation ;-)

I think that the user of Rockbox should have the choice to use your method if he/she wants to. But instead of implementing all of it into chessbox, I propose the following procedure:
1. Wait until some people here have tested this patch and if there are some objections against it.
2. Extend the API with some functions to handle the touchpad input. This would first contain some stuff from the chessbox patch like defining sensitive areas (e.g. the fields of the chessboard), handling the user input and handling the input mode. In the game the current call to button_get() would be replaced with a new function input_get() which will provide information about the user's input like: What has been done (pressed a button, selected a tile) and the field where it has been done.
By doing this not every plugin has to implement all the low level button/touchpad handling again, but will only have to react on the information provided by the new API functions.
3. Change at least one more plugin to use the new stuff to see if there is everything we need.
4. After this works, the new API can be extended to handle more input methods like drag&drop. It would return a new input event (TOUCHPAD_DRAG_DROP) and some information about the start and the target field. Plugin would only have to handle the new event and perform the move accordingly.

That way the complex stuff like mapping screen coordinates to certain areas and finding out what the user has done will be mostly invisible to the plugins and migrating all the plugins for the touchscreen should be easier (hopefuly!).

What do you think about that? All comments are welcome!

I agree with moving several stuff up, but I wouldn't make it too high-level i.e. TOUCHPAD_DRAG_DROP should be an optional event/function because almost every plugin needs different X/Y handling because of the different UI structure.

What should be done is moving the touchpad handling code in apps/action.c to firmware/drivers/button.c.
What could be done is implementing some standard functions library in apps/plugins/lib/ (I don't know how binsize increase is handled here: is it added to the main binary or to every plugin or to every plugin which uses the specific .c file/functions?)

You said drag&drop behaviour isn't really useful as the screen is to small: as I currently don't have a touchscreen device I didn't know this, but I don't believe this implementation can't be used for other targets (with bigger screens).

About 2.: some kind of mapping interface could indeed be added, I'm thinking something like this:
[code]
LIB CODE


struct ts_mapping
{
int type;
union
{

struct
{
 int tl_x; /* top left */
 int tl_y;
 int width;
 int height;
} rectangle;
...

}
};

struct ts_mappings
{
struct *ts_mapping mappings;
int amount;
}

unsigned int touchscreen_map(struct *ts_mappings map, short x, short y, …)
{
int i;
for(i=0; i < map→amount; i++)
{
#define _MAP(x) (struct ts_mapping*)(&map→mappings+sizeof(struct mapping)*x)

switch(_MAP(i)->type)
{
 case 1: /* rectangle */
  [BOUNDARY CHECKING OF X ,Y]
  break;
 ...
}

}
}


GAME CODE


static ts_mapping _main_menu[5] =
{
{1, {10, 10, 50, 30}}, /* New Game */
… };
static ts_mappings main_menu = {&_main_menu, 5};

void handle_button()
{
int button = rb→button_get(true);
unsigned int result;
short x, y;
switch(button)
{

case BUTTON_TOUCHPAD:
  button = rb->button_ts_get(&x, &y);
  result = touchscreen_map(&main_menu, x, y);
  if(result == -1)
   [ERROR HANDLING CODE]
  switch(result)
  {
    case 0: /* New Game */
      [GAME UI HANDLING CODE]
    break;
    ...
  }
 break;

}
}


[/code]
What do you think?

woops… Of course that _MAP() macro wouldn't work as the size of a ts_mapping will be dynamic, an other solution should be found for that; but you get the main idea :)

I've made an example of what I meant and tried it on pegbox which seems to work perfectly.
Comments?

P.S.: the original touch_chess.diff is included in the diff

The mapping stuff is what I had in mind, good work.
About the TOUCHPAD_DRAG_DROP: Something like that would be based on the mappings each plugin defined and would not return XY-coordinates but the numbers of start and target map.
The plugin would get something like the following struct as a result:

[code]
in the library

struct input_action
{

  int action; /*can be a simple button, a click on a map area or drag&drop between two map areas
  int area_number; /* ==-1 for a button, set if something on a map area happened */
  int target_area_number /* set if drag&drap */

}
[/code]

and the plugin

[code]
void handle_input()
{
struct input_action input;
rb→input_get(&input,&main_menu); /* this function will be provided by the library and handle all user input */
unsigned int result;
short x, y;
switch(input.action)
{

  case BUTTON_TOUCHPAD:
      switch(input.area_number)
      {
          case 0: /* New Game */
          [GAME UI HANDLING CODE]
          break;
          ...
      }
   case TOUCHPAD_DRAG_DROP:
      /* do things with both area numbers */
      break;
   case BUTTON_?:  /* here comes the stuff for the standard buttons */
       break;

}

}
[/code]

I don't know if it is understandable what I mean. I'm not so good at giving code examples on the fly.
But I think such a complex library would be too much for now. The chessbox plugin should be completed first including the drag&drop and then there should be done a working implementation of your mapping idea. After that I can try if my idea of putting all of the input work into its own library works at all or if it is just some crazy idea of me.

I will try out you patch later (when I have some more time) and give you some feedback on it.

About action.c and button.c: It seems to be right to move the touchpad functions into button.c as it is too low-level for action.c. But I'm quite new at rockbox, so maybe there was a reason to put it into action.c.
About a standard functions library in apps/plugins/lib/: No opinion here due to lack of knowledge about rockbox. I guess I need to work some more time with it and learn more. Maybe someone else knows how putting stuff there will increase the binsize of plugins etc.

This is v3:
* pegbox isn't working yet but bugfixing it won't take long I think (I'll look into it later)
* code isn't commented yet so things may look strange
* chessbox is completely working (with library code) apart from drag&drop

rold commented on 2008-11-18 16:09

Hi, I jsut got rockbox and I am not able to find how to change the code of the chess game so I can use touch chess. I know it is probably write somewhere else, but I am not able to find it. I would really appreciate if you can tell me where or how to do it. Thanks

@mcuelenaere, is this all in SVN now hence the task can be closed?

It looks like the touchscreen lib part was committed, but not the chessbox stuff.

Loading...

Available keyboard shortcuts

Tasklist

Task Details

Task Editing