ENIGMA Forums
Contributing to ENIGMA => Function Peer Review => Topic started by: RetroX on October 24, 2010, 08:23:45 pm
-
Randomly found a function that was needed.
Here you go.
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.
-
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.
-
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(...)...
-
In fact, I must be smoking something.
#define motion_set(newdirection,newspeed) (direction=(newdirection), speed=(newspeed))
-
Why not use an inline function? :/
-
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.
-
You also have to realise how macros are not functions and that they result in terribly awkward syntax errors when not done correctly.
-
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.
-
#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.
-
Randomly found a function that was needed.
Here you go.
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:
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;
}
-
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.
-
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:
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.
-
Please share your new place_Free and place_empty and is_solid code.
-
Ah, right. The patch for coll_funcs.cpp is below:
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.
-
1) Couldn't you just do:
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.
-
r570 implements solid, and r571 links in the new collision system functions.
place_free now works wonderfully.