Pages: 1
Author Topic: action_move  (51,272 Views)
Offline (Unknown gender) IsmAvatar

LateralGM Developer
LGM Developer
Joined: Apr 2008
Posts: 877
View profile
Posted on: November 03, 2010, 03:44:10 PM
I'm trying to write up the action_move function, since it doesn't really have a direct GML equivalent, due to the direction argument being multiple-choice which then gets randomly selected.
I'm also working on an educated assumption here, trying to recall from when I still had access to GM, how it behaved.

Assumption 1: It will randomly select one of the depressed directional buttons, but will not select a between value (so the resulting direction will always be a multiple of 45).
Assumption 2: The directional string directly corresponds with the directions in the dirs array. (I've done a bit of testing, so I think it is correct)

Code (C++) Select
void action_move(const char dir[9], int argspeed) {
int dirs[9] = {  225, 270, 315, 180, -1, 0, 135, 90, 45 };
int chosendirs[9];
int choices = 0;
for (int i = 0; i < 9; i++)
  if (dir[i] == '1') chosendirs[choices++] = dirs[i];
if (choices == 0) return;
choices = int(random(choices)); //choices is now chosen

//We use rval.d for efficiency, so hspeed/vspeed aren't set twice.
const double newdir =
((enigma::object_planar*)enigma::instance_event_iterator->inst)->direction.rval.d = chosendirs[choices];
if (argument_relative)
  argspeed += ((enigma::object_planar*)enigma::instance_event_iterator->inst)->speed;
const double newspd =
((enigma::object_planar*)enigma::instance_event_iterator->inst)->speed.rval.d = chosendirs[choices] == -1 ? 0 : argspeed;
((enigma::object_planar*)enigma::instance_event_iterator->inst)->hspeed.rval.d = newspd * cos(newdir);
((enigma::object_planar*)enigma::instance_event_iterator->inst)->vspeed.rval.d = newspd * sin(newdir);
}


Note 1: The first argument should always be an array of characters of size 9. Longer strings are fine, but only the first 9 characters will be examined. Shorter strings may cause this to look at memory beyond the string.
Note 2: This code makes use of the random(x) function.

Note 3: A few minor optimizations can be made around random.
3a: To avoid the use of random when there's only 1 choice. Replace:
choices = int(random(choices)); //choices is now chosen
With
Code (C++) Select

if (choices == 1) choices = 0;
else choices = int(random(choices)); //choices is now chosen

3b: Replace random with randomInt if it's more efficient (and if it exists).
3c: Replace random with integrated choose() function once it's implemented, if it's more efficient.
Offline (Unknown gender) RetroX

Master of all things Linux
Contributor
Joined: Apr 2008
Posts: 1,055
View profile
Reply #1 Posted on: November 03, 2010, 08:57:55 PM
Instead of using a string of 9 bytes, why not just use unsigned char with flags?

const unsigned char e  = 1;
const unsigned char ne = 2;
const unsigned char n  = 4;
const unsigned char nw = 8;
const unsigned char w  = 16;
const unsigned char sw = 32;
const unsigned char s  = 64;
const unsigned char se = 128;
Offline (Unknown gender) IsmAvatar

LateralGM Developer
LGM Developer
Joined: Apr 2008
Posts: 877
View profile
Reply #2 Posted on: November 03, 2010, 09:25:54 PM
Because the DND action direction argument is passed as a string of 9 bytes. Changing it would require a change in the underlying mechanism, and then a backwards compatibility mechanism to get it to still work with GM.
Offline (Unknown gender) RetroX

Master of all things Linux
Contributor
Joined: Apr 2008
Posts: 1,055
View profile
Reply #3 Posted on: November 03, 2010, 09:55:52 PM
Oh.

In that case, never mind.
Offline (Unknown gender) Josh @ Dreamland

Prince of all Goldfish
Developer
Joined: Feb 2008
Posts: 2,950
View profile
Reply #4 Posted on: November 04, 2010, 05:06:06 AM
I don't know off the top of my head the implications of taking const char[9] as a parameter; I am relatively certain that's the same as just const char*. Whatever the actual case, you really wanted const char[10] for the NULL at the end of the literal. :P

My other beef is that, despite this being a function instead of a macro, it does not take advantage of non-EDL optimizations; namely setting direction.dval and speed.dval manually, then manipulating hspeed.dval and vspeed.dval manually.

I'm actually too tired and lazy right now to do the trivial amount of text insertion required to put that to code. >.<

-sigh-

Code (C++) Select
const double dir = ((enigma::object_planar*)enigma::instance_event_iterator->inst)->direction.dval = chosendirs[choices];
((enigma::object_planar*)enigma::instance_event_iterator->inst)->speed.dval = chosendirs[choices] == -1 ? 0 : argspeed;
hspeed.dval = speed.dval * cos(dir), vspeed.dval = speed.dval * sin(dir);


Assuming all the rest of your code is right, and that I'm remembering the name of my own class member correctly.
Offline (Unknown gender) IsmAvatar

LateralGM Developer
LGM Developer
Joined: Apr 2008
Posts: 877
View profile
Reply #5 Posted on: November 04, 2010, 05:08:08 PM
The [9] was to emphasize that only 9 characters will be considered. I'm not sure if that'd cause any problems for the null at the end or not, but I don't even look at the null; it doesn't matter to me.

As for macro, good luck writing that. I also haven't been able to get #define to work quite right in definitions for defining dnd actions. It's like it gets ignored.

As for hspeed and vspeed, I wasn't sure how that worked.

As for whether the rest of the code is right, I've already been using it for a while in a new catch-the-clown d&d version, and it works great.
Offline (Unknown gender) Josh @ Dreamland

Prince of all Goldfish
Developer
Joined: Feb 2008
Posts: 2,950
View profile
Reply #6 Posted on: November 04, 2010, 05:17:03 PM
- Like I said, shouldn't matter.
- Until choose is implemented, the macro isn't possible.
- Well, now you know. Have you implemented it?
- (Y)
Offline (Unknown gender) IsmAvatar

LateralGM Developer
LGM Developer
Joined: Apr 2008
Posts: 877
View profile
Reply #7 Posted on: November 04, 2010, 06:27:25 PM
Implemented that (it's rval.d, not dval).
I also made a couple more notes about the use of random.
Offline (Unknown gender) IsmAvatar

LateralGM Developer
LGM Developer
Joined: Apr 2008
Posts: 877
View profile
Reply #8 Posted on: November 12, 2010, 05:00:33 PM
I just realized that action_move has a relative checkbox. I'm investigating what it does right now. Assuming that it only effects the speed, insert this:

if (argument_relative)
  argspeed += ((enigma::object_planar*)enigma::instance_event_iterator->inst)->speed;

right before
const double newspd =


Edit: Investigation complete. It does only effect the magnitude, and magnitudes set with the Stop direction are not retained. I've implemented this into the code.
Pages: 1