ENIGMA Forums
Contributing to ENIGMA => Function Peer Review => Topic started by: IsmAvatar on January 07, 2011, 04:05:11 pm
-
void motion_set(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->direction.rval.d = newdir;
inst->speed.rval.d = newspd;
inst->hspeed.rval.d = newspd * cos(newdir);
inst->vspeed.rval.d = newspd * sin(newdir);
}
inline void move_towards_point(double x, double y, double spd) {
motion_set(point_direction(
((enigma::object_planar*)enigma::instance_event_iterator->inst)->x,
((enigma::object_planar*)enigma::instance_event_iterator->inst)->y,
x,y),spd);
}
motion_set was borrowed from action_move (http://enigma-dev.org/forums/index.php?topic=667.0). It's just used as a convenience method to set both speed and direction efficiently. There have been some concerns over radians vs. degrees, and I haven't looked into them fully, but oddly enough action_move seemed to work...
-
In addition, motion_add:
void motion_add(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->hspeed.rval.d += newspd * cos(newdir);
inst->vspeed.rval.d += newspd * sin(newdir);
inst->direction.rval.d = point_direction(0, 0, inst->hspeed.rval.d, inst->vspeed.rval.d);
inst->speed.rval.d = abs(hypot(inst->hspeed.rval.d, inst->vspeed.rval.d));
}
Untested, but it's mathematically sound.
-
Also, random thing to mention, but:
void motion_set(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->direction.rval.d = newdir;
inst->speed.rval.d = newspd;
inst->hspeed.rval.d = newspd * cos(newdir);
inst->vspeed.rval.d = newspd * sin(newdir);
}
inline void move_towards_point(double x, double y, double spd) {
motion_set(point_direction(
((enigma::object_planar*)enigma::instance_event_iterator->inst)->x,
((enigma::object_planar*)enigma::instance_event_iterator->inst)->y,
x,y),spd);
}
void motion_add(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->hspeed.rval.d += newspd * cos(newdir);
inst->vspeed.rval.d += newspd * sin(newdir);
inst->direction.rval.d = point_direction(0, 0, inst->hspeed.rval.d, inst->vspeed.rval.d);
inst->speed.rval.d = abs(hypot(inst->hspeed.rval.d, inst->vspeed.rval.d));
}
-
No, they shouldn't
-
move_towards_point should be inline, at least. :V
-
I think also did this one (move_towards_point). Is anyone actually reading this?
-
I think also did this one (move_towards_point). Is anyone actually reading this?
In GML, not C++.
-
EDL :eng101:
-
Also, random thing to mention, but:
Code: (C++) [Select]
void motion_set(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->direction.rval.d = newdir;
inst->speed.rval.d = newspd;
inst->hspeed.rval.d = newspd * cos(newdir);
inst->vspeed.rval.d = newspd * sin(newdir);
}
inline void move_towards_point(double x, double y, double spd) {
motion_set(point_direction(
((enigma::object_planar*)enigma::instance_event_iterator->inst)->x,
((enigma::object_planar*)enigma::instance_event_iterator->inst)->y,
x,y),spd);
}
void motion_add(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->hspeed.rval.d += newspd * cos(newdir);
inst->vspeed.rval.d += newspd * sin(newdir);
inst->direction.rval.d = point_direction(0, 0, inst->hspeed.rval.d, inst->vspeed.rval.d);
inst->speed.rval.d = abs(hypot(inst->hspeed.rval.d, inst->vspeed.rval.d));
}
Tried to use move towards point from this, and my word it's CRAAAAAAAZZZZZZYYYY, have you tested it?
-
Probably because hes giving a non radian angle to sin and cos.
-
Yeah, it is. Updated:
void motion_set(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->direction.rval.d = newdir;
inst->speed.rval.d = newspd;
inst->hspeed.rval.d = newspd * cos(degtorad(newdir));
inst->vspeed.rval.d = newspd * sin(degtorad(newdir));
}
inline void move_towards_point(double x, double y, double spd) {
motion_set(point_direction(
((enigma::object_planar*)enigma::instance_event_iterator->inst)->x,
((enigma::object_planar*)enigma::instance_event_iterator->inst)->y,
x,y),spd);
}
void motion_add(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->hspeed.rval.d += newspd * cos(degtorad(newdir));
inst->vspeed.rval.d += newspd * sin(degtorad(newdir));
inst->direction.rval.d = point_direction(0, 0, inst->hspeed.rval.d, inst->vspeed.rval.d);
inst->speed.rval.d = abs(hypot(inst->hspeed.rval.d, inst->vspeed.rval.d));
}
Suggestion: point_direction_radians
-
Quoting Ism:
There have been some concerns over radians vs. degrees, and I haven't looked into them fully, but oddly enough action_move seemed to work...
Because of the way rval.d works, the code is correct without degtorad. This got me too.
-
oh, well, ignore what I posted, then
-
Actually, I have no idea why the fuck Ism's implementation works. direction.rval.d is in degrees. Or at least it's supposed to be. There is the possibility that it is only in degrees when it is the last variable set.
-
Have any of these been tested and found to function as desired?
-
Nope. :P
-
Actually, I have no idea why the fuck Ism's implementation works. direction.rval.d is in degrees. Or at least it's supposed to be. There is the possibility that it is only in degrees when it is the last variable set.
Funny you said that to me when I mentioned it. But then Ism quite rightly pointed out that you were actually the one who used that code first:
I'm actually too tired and lazy right now to do the trivial amount of text insertion required to put that to code. >.<
-sigh-
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.
She doesn't know why the fuck it works either
-
All of these make it run away from the position rather than move towards as it's supposed to.
Here's a corrected version.
void motion_set(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->direction.rval.d = newdir;
inst->speed.rval.d = newspd;
inst->hspeed.rval.d = newspd * cos(degtorad(newdir));
inst->vspeed.rval.d = -newspd * sin(degtorad(newdir));
}
inline void move_towards_point(double x, double y, double spd) {
motion_set(point_direction(
((enigma::object_planar*)enigma::instance_event_iterator->inst)->x,
((enigma::object_planar*)enigma::instance_event_iterator->inst)->y,
x,y),spd);
}
void motion_add(double newdir, double newspd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
inst->hspeed.rval.d += newspd * cos(degtorad(newdir));
inst->vspeed.rval.d += newspd * sin(degtorad(newdir));
inst->direction.rval.d = point_direction(0, 0, inst->hspeed.rval.d, inst->vspeed.rval.d);
inst->speed.rval.d = abs(hypot(inst->hspeed.rval.d, inst->vspeed.rval.d));
}
"inst->vspeed.rval.d = -newspd * sin(degtorad(newdir));"
making it negative corrects the issue. :)
-
inline void move_point_stop(double x, double y, double spd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
if (inst->x==x && inst->y==y)
return void;
else
{
motion_set(point_direction(
((enigma::object_planar*)enigma::instance_event_iterator->inst)->x,
((enigma::object_planar*)enigma::instance_event_iterator->inst)->y,
x,y),spd);
}
}
How do you like these apples? Or are they dysfunctional apples?
-
When you introduce the inst variable, you shouldn't keep it inline anymore I don't think, and it's redundant to return void to a void returning function. Also, indentation. This would be more likely:
void move_point_stop(double x, double y, double spd) {
enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
if (inst->x!=x || inst->y!=y)
motion_set(point_direction(inst->x,inst->y,x,y),spd);
}
Or this:
inline void move_point_stop(double x, double y, double spd) {
if (((enigma::object_planar*)enigma::instance_event_iterator->inst)->x!=x
|| ((enigma::object_planar*)enigma::instance_event_iterator->inst)->y!=y)
motion_set(point_direction(
((enigma::object_planar*)enigma::instance_event_iterator->inst)->x,
((enigma::object_planar*)enigma::instance_event_iterator->inst)->y,
x,y),spd);
}
In addition, this doesn't stop when it has reached the point. It only ceases to set the motion. Recall that an object in motion continues to stay in motion until acted upon.
Append this prior to the last closing curly brace:
else ((enigma::object_planar*)enigma::instance_event_iterator->inst)->speed = 0;
Or if you already have inst defined:
else inst->speed = 0;
-
Ah yeah, I forgot hspeed and vspeed doesn't cease until instructed to.
-
Ugh.
-
Ugh.
You've done this in EDL, already?
It needs to be done in C++ so that it can be compiled directly into ENIGMA though, doesn't it? :v:
-
Another thought, isn't it best if the functions don't use other function to complete their tasks, as when the time comes to allow the user to remove particular functions from instances and checks, removing something such as motion_set but not move_towards_point then using the latter, will cause issues for the user, and they probably will have no idea what the issue is...
-
GML scripts allowed?
If they work when added as a function in Whitespace, or are really worth porting, I don't see why not.
I already sent it to Josh but I'm not even sure he still has it.
-
Oh ok, that's good then. Shouldn't your version have been implemented already then?
Also, about my other post, you have any answers for that? ???
-
I don't see a reason to disable motion_set while keeping move_towards_point. It seems to me that if you want to disable one, you'll want to disable the other as well (e.g. bulk removal of motion-related functions). That said, if you still wanted to disable motion_set but keep move_towards_point, you might be able to set motion_set to be private access, so that it's not visible to outside files (this might just be Java rubbing off on me)... but there's not much use in that, because the function is still there, it's just not visible anymore - in which case you might as well just keep the function and not use it. Point is, move_towards_point needs motion_set one way or the other, whether it's in a function called motion_set, or unrolled. The benefit of using motion_set is that it eliminates duplicate code.
-
IsmAvatar - C++ doesn't allow setting access to globals. All globals are public. Only members of structs and classes can be set with access specifiers.
What could be done is merely not including the code for that header in the game, or just not linking the object. If the header provides a declaration and no implementation is provided, it will still compile as long as the function isn't being used. Alternatively, you can add these flags to the GCC:
-fdata-sections -ffunction-sections
which compiles everything into separate sections in the actual object, and:
-Wl,-gc-sections
which will remove unused sections from the program upon linking.
On that matter, for debugging purposes, it would be nice to be able to add -g -O0, which will provide C++ debugging symbols, which GDB can use. It's extraordinarily useful.
-
Oh ok, that's good then. Shouldn't your version have been implemented already then?
Yes, it should. Damn Josh >: |. But I guess you guys could do it better either way. I can program in ActionScript 3.0 and C# but I dunno if that's of any use.
-
C# is pretty similar in many ways, but in many ways it also is not. Action Script is compleeeetely different in my opinion, i HATE the syntax of it, it's so backward (my opinion).
Maybe there's justification for the backward syntax, but i haven't looked into it, if you use it, i'm sure it has it's uses.
-
A motion_set that's five lines in GML isn't really worth porting. Those kinds of functions are more like blueprints or suggestions than code. It doesn't help me if you just take advantage of ENIGMA's scoping system to do things that are a pain in the ass in plain, general C++.
Though, with the new instance system, they're now much easier to produce.
-
I would've thought writing code in GML for functions would add to the compile time, though. Or does it only need to be coverted once?
-
GML functions are slower in nature because they use var. But compared to the speed of GM, it's already loads faster anyways.
Besides, if you code something in GML, post it here, and someone will likely be able to convert it to C++ for you.
-
Slow how? Takes more processing during run time? I thought the code was parsed straight to C++ at compile anyways? Or do you mean because of GML not being definitive in its types that it takes more memory?
So my initial thought was right anyways, that it's best to write the functions within C++ with the instance interator for Josh so that it doesn't have to be parsed during compile?
-
Well, basic integers are handled quickly by the processor. var has to check, at every calculation, what variable type is being used and how to handle it. It's not a huge notice, but if you take an entire project and convert it from var to primitive types, you'll see a relatively decent increase in speed.
-
Besides, if you code something in GML, post it here, and someone will likely be able to convert it to C++ for you.
I did!
-
with (obj) direction=dir, speed=spd; isn't worth porting, considering the corresponding C++ is completely different.
-
Well, basic integers are handled quickly by the processor. var has to check, at every calculation, what variable type is being used and how to handle it. It's not a huge notice, but if you take an entire project and convert it from var to primitive types, you'll see a relatively decent increase in speed.
Will defining our types before using them increase the speed at all, for example
int varname
string strname
so on and so forth.
To get the boost will we also have to include the variable type in the if statements and other such checks when referncing the varname
?
-
Will defining our types before using them increase the speed at all, for example
Of course. The biggest speed increase is in for cycles like for (int i=0; i<10000000; i++){}
will work A LOT faster thanfor (i=0; i<10000000; i++){}
To get the boost will we also have to include the variable type in the if statements and other such checks when referncing the varname
?
No, in c++ you have to set the type only when declaring them. When used in if checks and so on the type doesn't need to be set again. Unless you want to cast them as another type, like:double d=1.23;
int i=1;
if ((int)d == i){}
Dunno if ENIGMA allows this right now, but I also never really saw the reason to do that (unless in coding in c++ where functions can take only certain types of varaibles).
-
Yeah, I know how C++ works, I just didn't know if the way ENIGMA compiled it would cause me to have to do this, thanks for clearing that up :)
-
Indeed. I've managed to make variant work as fast as double, but double is still slower than int. Granted, they are hundreds (int thousands) of times faster than Game Maker, but best practice is to declare them. local int varname; will take care of all your woes.
You can stick a cast anywhere in an expression you like in ENIGMA. Just like ++, or !. Casts are just another unary operator.
-
But the .gmk that declares the data types won't work with GM as well wil it? As GM does not allow type casting...
-
Correct. Game Maker will complain, hence, ENIGMA is backwards-compatible.
-
LOL, ahhhhhhh. Great!