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.

Coding > Event/Trigger Detection??

#143435 - Ruben - Sun Oct 21, 2007 10:02 am

How would I go about making my map have 'events'? By events, I mean as in:
*Player steps into tile located at 22, 44*
*Script 'foo' executes*
I used to do this with a 'void*' array but that took up too much room for every map to be placed in EWRAM. I was wondering how I should do this. Any ideas??

#143441 - silent_code - Sun Oct 21, 2007 6:29 pm

it depends on what exactly you're trying to do. that means if it's enough to write some simple "configurable" (through parameters) functions that are quite general and thus commonly used, or if you need rather complex "scripts" with very individual behaviour.

the latter involves a lot of work, while the first is rather unflexible (which might be enough for its purpose, though!).

#143469 - sajiimori - Mon Oct 22, 2007 1:55 am

Are you saying you have something working, but it doesn't fit in RAM? If so, why don't you put it in ROM?

#143470 - Dwedit - Mon Oct 22, 2007 2:10 am

You don't need a space filling 2D array of events, you can get by fine with just a list of coordinates and events. Use a binary search algorithm to check if the player is standing on an event tile.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#143472 - tepples - Mon Oct 22, 2007 3:06 am

sajiimori wrote:
Are you saying you have something working, but it doesn't fit in RAM? If so, why don't you put it in ROM?

Because players 2 through 4 don't have ROM, nor does the GBA Movie Player.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#143482 - Ruben - Mon Oct 22, 2007 8:03 am

Dwedit wrote:
You don't need a space filling 2D array of events, you can get by fine with just a list of coordinates and events. Use a binary search algorithm to check if the player is standing on an event tile.
... and how would I do this??
So you mean like store some const array like:
Code:
const u8 eventfoo() {
 //do something
}

const u8 eventbar() {
 //do something
}

const u8* (EventArray[])() = {
 //Map 1 (2x2)
 0, 0,
 &eventfoo, 0,
 //Map 2 (2x3)
 0, &eventbar, 0,
 0, 0, 0,
};


PS: Sorry but I'm not THAT advanced lol...

#143490 - tepples - Mon Oct 22, 2007 11:37 am

That's still a 2D space-filling array. Try this:
Code:

typedef int (*EventFunc)(Map *m, void *esto);

typedef struct EventTrigger {
  unsigned short left, top, right, bottom;
  EventFunc code;
  void *esto;
} EventTrigger;

Then every time the player character takes a step, look through the array of EventTrigger elements associated with the map and find the first one where the character is within the rectangle described by left, top, right, and bottom. The 'esto' argument is good for passing data to the event function.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#143494 - Ruben - Mon Oct 22, 2007 12:39 pm

YAY!!!!! Thanks man! Just to show people what I ended up with (typical me :p):
Code:
//This is the 'typedef' for a map event
typedef int (*_pFuncInt)();
typedef struct _MapEventTrigger {
 u16 L, X, Y;
 _pFuncInt code;
 bool used;
} _MapEventTrigger;

_MapEventTrigger _MapBG2Triggers[99];
_MapEventTrigger _MapBG3Triggers[99];
u8 _MapBG2TriggersSize = 0;
u8 _MapBG3TriggersSize = 0;

void _MapAddTrigger(u8 l, u16 x, u16 y, _pFuncInt c) {
 switch(l) {
  case 0: //BG layer
   if(_MapBG2TriggersSize > 99) return;
   _MapBG2Triggers[_MapBG2TriggersSize].L = l;
   _MapBG2Triggers[_MapBG2TriggersSize].X = x;
   _MapBG2Triggers[_MapBG2TriggersSize].Y = y;
   _MapBG2Triggers[_MapBG2TriggersSize].code = c;
   _MapBG2Triggers[_MapBG2TriggersSize].used = true;
   _MapBG2TriggersSize++;
   break;
  case 1: //FG layer
   if(_MapBG3TriggersSize > 99) return;
   _MapBG3Triggers[_MapBG3TriggersSize].L = l;
   _MapBG3Triggers[_MapBG3TriggersSize].X = x;
   _MapBG3Triggers[_MapBG3TriggersSize].Y = y;
   _MapBG3Triggers[_MapBG3TriggersSize].code = c;
   _MapBG3Triggers[_MapBG3TriggersSize].used = true;
   _MapBG3TriggersSize++;
   break;
 }
}

//This checks for events when the player's not moving
void _MapEventCheck() {
 int i;
 if(_PlayerEvent) return;
 if(_PlayerX < 0) _PlayerX += _MapSizeX/2;
 if(_PlayerY < 0) _PlayerY += _MapSizeY/2;
 
 switch(_PlayerLayer) {
  case 0:
   for(i=0;i<_MapBG2TriggersSize;i++) {
    if(_MapBG2Triggers[i].X == _PlayerX && _MapBG2Triggers[i].Y == _PlayerY && _MapBG2Triggers[i].used) {
     _PlayerEvent = 1;
     _MapBG2Triggers[i].code();
    }
    break;
   }
   break;
  case 1:
   for(i=0;i<_MapBG3TriggersSize;i++) {
    if(_MapBG3Triggers[i].X == _PlayerX && _MapBG3Triggers[i].Y == _PlayerY && _MapBG3Triggers[i].used) {
     _PlayerEvent = 1;
     _MapBG3Triggers[i].code();
    }
    break;
   }
   break;
 }
}
I didn't use the parser function as I don't think I'll EVER need that lolz... anyways... thanks again!

BTW: I know a lot of the code here isn't really nescesary for a 'normal' game but it's nescesary for me beleive it or not! _PlayerEvent tells the system whether the event should be triggered EVEN IF the person was just 'warped' there and stuff... lol...

#143500 - kusma - Mon Oct 22, 2007 2:19 pm

A linear search might not scale well if you get many triggers. Either keep the trigger-count low, or use a hash-table or something like that.

Keeping the trigger-count low is most likely a good-enough solution, hashing quickly requires some linked lists and memory-pools and so on.