Pages: [1] 2
  Print  
Author Topic: move_towards_point + move_snap  (Read 3644 times)
Offline (Male) RetroX
Posted on: October 24, 2010, 08:23:45 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
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.
« Last Edit: October 24, 2010, 08:34:45 PM by RetroX » Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Unknown gender) TGMG
Reply #1 Posted on: October 25, 2010, 04:39:31 AM

Developer
Joined: Jun 2008
Posts: 107

View Profile WWW Email
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.
Logged
me
GMbed 2.0 :: Embed you gm games in websites.
Offline (Male) Josh @ Dreamland
Reply #2 Posted on: October 25, 2010, 08:01:42 AM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2932

View Profile Email
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(...)...
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Male) Josh @ Dreamland
Reply #3 Posted on: October 25, 2010, 11:44:41 AM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2932

View Profile Email
In fact, I must be smoking something.
#define motion_set(newdirection,newspeed) (direction=(newdirection), speed=(newspeed))
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Male) RetroX
Reply #4 Posted on: October 25, 2010, 06:21:11 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
Why not use an inline function? :/
Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Male) Josh @ Dreamland
Reply #5 Posted on: October 25, 2010, 06:22:45 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2932

View Profile Email
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.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Male) RetroX
Reply #6 Posted on: October 25, 2010, 07:33:36 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
You also have to realise how macros are not functions and that they result in terribly awkward syntax errors when not done correctly.
Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Unknown gender) TGMG
Reply #7 Posted on: October 25, 2010, 07:43:28 PM

Developer
Joined: Jun 2008
Posts: 107

View Profile WWW Email
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.
Logged
me
GMbed 2.0 :: Embed you gm games in websites.
Offline (Male) Josh @ Dreamland
Reply #8 Posted on: October 25, 2010, 08:40:20 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2932

View Profile Email
#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.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) Mith
Reply #9 Posted on: December 14, 2010, 08:17:55 AM
Member
Joined: Apr 2010
Posts: 7

View Profile Email
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;
}
Logged
Offline (Male) Josh @ Dreamland
Reply #10 Posted on: December 15, 2010, 06:11:55 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2932

View Profile Email
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.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) Mith
Reply #11 Posted on: December 16, 2010, 08:09:43 AM
Member
Joined: Apr 2010
Posts: 7

View Profile Email
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.
« Last Edit: December 16, 2010, 04:02:34 PM by Mith » Logged
Offline (Female) IsmAvatar
Reply #12 Posted on: December 16, 2010, 04:06:49 PM

LateralGM Developer
LGM Developer
Location: Pennsylvania/USA
Joined: Apr 2008
Posts: 886

View Profile Email
Please share your new place_Free and place_empty and is_solid code.
Logged
Offline (Unknown gender) Mith
Reply #13 Posted on: December 16, 2010, 06:37:28 PM
Member
Joined: Apr 2010
Posts: 7

View Profile Email
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.
Logged
Offline (Female) IsmAvatar
Reply #14 Posted on: December 16, 2010, 07:18:18 PM

LateralGM Developer
LGM Developer
Location: Pennsylvania/USA
Joined: Apr 2008
Posts: 886

View Profile Email
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.
« Last Edit: December 17, 2010, 01:03:37 AM by IsmAvatar » Logged
Pages: [1] 2
  Print