ENIGMA Forums

Contributing to ENIGMA => Function Peer Review => Topic started by: RetroX on October 24, 2010, 08:23:45 PM

Title: move_towards_point + move_snap
Post by: RetroX on October 24, 2010, 08:23:45 PM
Randomly found a function that was needed.

Here you go.

Code: [Select]
void move_towards_point(double x, double y, double spd)
{
  double angle = atan2(y - ((object_planar*)enigma::instance_event_iterator->inst)->y,
                       x - ((object_planar*)enigma::instance_event_iterator->inst)->x);
  ((object_planar*)enigma::instance_event_iterator->inst)->x += cos(angle) * speed;
  ((object_planar*)enigma::instance_event_iterator->inst)->y -= sin(angle) * speed;
}
void move_snap(double x, double y)
{
  ((object_planar*)enigma::instance_event_iterator->inst)->x = round(((object_planar*)enigma::instance_event_iterator->inst)->x * x) / x;
  ((object_planar*)enigma::instance_event_iterator->inst)->y = round(((object_planar*)enigma::instance_event_iterator->inst)->y * y) / y;
}

Haven't tested it, but I'm sure that it can easily be modified to work.

EDIT: And I tested it and it didn't work.  Josh, make it work.
Title: Re: move_towards_point + move_snap
Post by: TGMG on October 25, 2010, 04:39:31 AM
Code: [Select]
void motion_set(int dir, double speed);
#define motion_set(newdirection,newspeed) direction=(newdirection); speed=newspeed;

void motion_add(double dir, double speed);
#define motion_add(newdirection,newspeed) hspeed+= (newspeed) * cos(degtorad(newdirection)); vspeed-= (newspeed) * sin(degtorad(newdirection));

bool place_snapped(int hsnap, int vsnap);
#define place_snapped(hsnap,vsnap)  (((int) x) % ((int) hsnap) == 0 &&  ((int) y) % ((int) vsnap)==0)

void move_snap(int hsnap, int vsnap) {

int modX = ((int)((enigma::object_graphics*)enigma::instance_event_iterator->inst)->x) % hsnap;
int modY = ((int)((enigma::object_graphics*)enigma::instance_event_iterator->inst)->y) % vsnap;

if (modX > (hsnap / 2))
((enigma::object_graphics*)enigma::instance_event_iterator->inst)->x += hsnap - modX;
else if (modX <= (hsnap / 2))
((enigma::object_graphics*)enigma::instance_event_iterator->inst)->x -= modX;

if (modY > (vsnap / 2))
((enigma::object_graphics*)enigma::instance_event_iterator->inst)->y += vsnap - modY;
else if (modY <= (vsnap / 2))
((enigma::object_graphics*)enigma::instance_event_iterator->inst)->y -= modY;
}



void move_towards_point ( double point_x, double point_y, double speed );

#define move_towards_point(point_x,point_y,newspeed) direction = point_direction ( x,y, (point_x), (point_y) ); speed = (newspeed);

I didn't commit this code to svn as I haven't completely tested it yet, I wrote them a few weeks ago but can't remember how well they work, think they work ok tho.
Title: Re: move_towards_point + move_snap
Post by: Josh @ Dreamland on October 25, 2010, 08:01:42 AM
Ouch, TGMG.

Never do this:
#define motion_set(newdirection,newspeed) direction=(newdirection); speed=newspeed;

Use this:
#define motion_set(newdirection,newspeed) direction=(newdirection), speed=newspeed;
or this:
#define motion_set(newdirection,newspeed) { direction=(newdirection); speed=newspeed; }

Otherwise...
with (all) motion_set(...)...
Title: Re: move_towards_point + move_snap
Post by: Josh @ Dreamland on October 25, 2010, 11:44:41 AM
In fact, I must be smoking something.
#define motion_set(newdirection,newspeed) (direction=(newdirection), speed=(newspeed))
Title: Re: move_towards_point + move_snap
Post by: RetroX on October 25, 2010, 06:21:11 PM
Why not use an inline function? :/
Title: Re: move_towards_point + move_snap
Post by: Josh @ Dreamland on October 25, 2010, 06:22:45 PM
Because with macros, you can seamlessly manipulate locals such as direction and speed.
...An inline function would be more efficient, though, as hspeed and vspeed would only need to be edited once.
Title: Re: move_towards_point + move_snap
Post by: RetroX on October 25, 2010, 07:33:36 PM
You also have to realise how macros are not functions and that they result in terribly awkward syntax errors when not done correctly.
Title: Re: move_towards_point + move_snap
Post by: TGMG on October 25, 2010, 07:43:28 PM
oops! yup totally forgot about that :$

It was originally an inline function but it was written when enigma was segfaulting when accessing the variables from the create event.
Title: Re: move_towards_point + move_snap
Post by: Josh @ Dreamland on October 25, 2010, 08:40:20 PM
#define motion_set(newdirection,newspeed) (direction=(newdirection), speed=(newspeed))
Is the STRICT EQUIVALENT to inline double motion_set(double newdirection,double newspeed) { return (direction=(newdirection), speed=(newspeed)); }. There is NO context under which the inline would work, and the macro I specified would not.

Furthermore, if ENIGMA's source is full of more complicated inline functions than this one, compile time will be a disaster.

Again, the reason to write a function for this instead of a macro is to save some trig in assigning hspeed and vspeed.
Title: Re: move_towards_point + move_snap
Post by: Mith on December 14, 2010, 08:17:55 AM
Randomly found a function that was needed.

Here you go.

Code: [Select]
void move_towards_point(double x, double y, double spd)
...

Haven't tested it, but I'm sure that it can easily be modified to work.

EDIT: And I tested it and it didn't work.  Josh, make it work.

Fixed and tested:

Code: [Select]
void move_towards_point(const double x, const double y, const double spd)
{
  enigma::object_planar * const current_instance = ((enigma::object_planar*)(enigma::instance_event_iterator->inst));

  //Move the current instance towards the point.
  const double angle = atan2(y - current_instance->y,
                       x - current_instance->x);
  current_instance->x += cos(angle) * spd;
  current_instance->y += sin(angle) * spd;
}

void move_snap(const double grid_width, const double grid_height)
{
  enigma::object_planar * const current_instance = ((enigma::object_planar*)(enigma::instance_event_iterator->inst));

  //Snap the current instance to the indicated grid.
  current_instance->x = round(current_instance->x / grid_width) * grid_width;
  current_instance->y = round(current_instance->y / grid_height) * grid_height;
}
Title: Re: move_towards_point + move_snap
Post by: Josh @ Dreamland on December 15, 2010, 06:11:55 PM
Hello, Mith. I didn't realize you were still around. I think what you implemented there as move_towards_point is actually mp_linear_step. I don't see a problem with the code at all, though. Nicely done.
Title: Re: move_towards_point + move_snap
Post by: Mith on December 16, 2010, 08:09:43 AM
Ah, thanks :). I still visit the forum once in a while, mostly just looking around. It is really nice to see the project moving forward. You are right regarding move_towards_point, I will try to see if I can implement that and mp_linear_step correctly.

EDIT:

The functions have been fixed:
Code: [Select]
void mp_linear_step(const double x, const double y, const double spd, const bool checkall)
{
  enigma::object_planar * const current_instance = ((enigma::object_planar*)(enigma::instance_event_iterator->inst));

  //Find the new position.
  const double angle = atan2(y - current_instance->y, x - current_instance->x);
  const double diff_x = current_instance->x - x;
  const double diff_y = current_instance->y - y;
  double new_x, new_y;
  //If we are near the destination, stop at the destination (using Pythagoras).
  if (spd * spd >= diff_x * diff_x + diff_y * diff_y) {
    new_x = x;
    new_y = y;
  }
  else {
    new_x = current_instance->x + cos(angle) * spd;
    new_y = current_instance->y + sin(angle) * spd;
  }

  //Check collision.
  //If checking all, non-solid must be taken into account too.
  if ( (checkall && !place_empty(new_x, new_y)) || (!checkall && !place_free(new_x, new_y))) {
    return;
  }

  //Move.
  current_instance->x = new_x;
  current_instance->y = new_y;
}

void move_towards_point(const double x, const double y, const double spd)
{
  enigma::object_planar * const current_instance = ((enigma::object_planar*)(enigma::instance_event_iterator->inst));

  //Calculate the direction.
  const double angle = atan2(y - current_instance->y, x - current_instance->x);
  //Set the values directly, to avoid recomputations.
  current_instance->direction.rval.d = -angle * 180 / M_PI;
  current_instance->hspeed.rval.d = cos(angle) * spd;
  current_instance->vspeed.rval.d = sin(angle) * spd;
  current_instance->speed.rval.d = spd;
}

I used the BBox collision system to debug mp_linear_step, and it seems to work well. There were some minor issues, however. I added checks in both place_free and place_empty for avoiding checking the current instance, and fumbled a little with solid. I also out-commented an implementation of place_free in collisions.h.
Based on the earlier comments regarding recalculation, I tried to set the velocity parameters directly. It seemed to work when I finished debugging it.
Title: Re: move_towards_point + move_snap
Post by: IsmAvatar on December 16, 2010, 04:06:49 PM
Please share your new place_Free and place_empty and is_solid code.
Title: Re: move_towards_point + move_snap
Post by: Mith on December 16, 2010, 06:37:28 PM
Ah, right. The patch for coll_funcs.cpp is below:

Code: [Select]
29c29,30
<  return true;
---
>   const double solidness = obj->solid;
>   return solidness > 0.5;
39a41
>   if (inst2->id == inst1->id) continue;
56a59
>   if (inst2->id == inst1->id) continue;
74d76
<

The is_solid change is somewhat hacky, but worked for the test. I had trouble testing the solid var, so I ended up assigning 1 to solid where it was solid and 0 to solid when it wasn't in each objects creation code, and then use the above "> 0.5" check to see if it was solid. Oh, and solid complained about multiple options for overloading >, so I assigned it to a double first.
Title: Re: move_towards_point + move_snap
Post by: IsmAvatar on December 16, 2010, 07:18:18 PM
1) Couldn't you just do:
Code: (C) [Select]
bool is_solid(const enigma::object_collisions *obj) {
  return obj->solid;
}

2) That said, since obj->solid isn't populated yet, I've been using true instead. I'll document it.

Edit: I've now documented (r569) that obj->solid isn't populated yet. The temporary solution is basically what you said - to put checks inside is_solid for each object you know to be solid. Otherwise, just returning true will treat all instances as solid.
Title: Re: move_towards_point + move_snap
Post by: IsmAvatar on December 17, 2010, 12:24:39 AM
r570 implements solid, and r571 links in the new collision system functions.

place_free now works wonderfully.