ENIGMA Forums

General fluff => General ENIGMA => Topic started by: polygone on December 21, 2010, 02:44:15 pm

Title: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 21, 2010, 02:44:15 pm
These are some common big issue I find with GML, I am wondering how/if they can be dealt with in Enigma.

1. Referencing multiple instances

Often you want to be reference or loop through a set of multiple instances, such as when using instance_nearest or instance_position. Is there functionality in Enigma which allows you to easily do this?


2. Referencing resources as strings

People often find themselves wanting to reference a resource index from it's corresponding string, being lazy they don't wish to map all the object indexes to strings manually, so is there a way this can be done easily in Enigma?

3. Exiting Code

Certain functions like game_end and some others do not exit code instantly but only when the current event has finished executing, I presume this behaviour is mimicked in Enigma. A problem however arises when you wish to exit in a script for example because in GM you can only exit the current script and not the entire event being executed. Is there a way for Enigma to deal with this?

4. get_real

A get_real() function asking the user to enter a real value is a very commonly wanted feature.

5. Pausing The Game

Very common feature which considering how commonly it's wanted isn't really as easy as it should be to implement in GML. Maybe a nicer system could be worked out for Enigma?

6. Multiple collisions issue

This is rather common, a user adds some code to a collision event like increasing the score or something but undesirably GM winds up increasing their score every step that the collision is occurring. A way for users to handle this nicely would be useful, I think a collision enter event and a collision exit event will suffice.

7. Timers

Another very common problem. Someone for example wants to draw some text for 4 second when they press a key. This isn't really nice to do in GML it involves creating an alarm and such then drawing from a variable in the draw event. You cannot simply do it from key press event of whatever. Now I don't know exactly how you could achieve such a functionality in Enigma but if you could work a out some nice mechanism for it, it would be rather useful for beginners.
Title: Re: Some common GML issues, will/how can they be dealt with in Enigma?
Post by: TheExDeus on December 21, 2010, 03:03:32 pm
Quote
1. Referencing multiple instances
And how exactly the return value would look like? If you just thought something like instance_nearest_nth (which would return n'th nearest instance) then that needs just a separate function.

Quote
2. Referencing resources as strings
As string? Like "sprite_player" would return a sprite index? But then how would you write "sprite_player"? If you thought something like sprite_return("sprite_player"), then I think that could be possible, but in the same way as variable_set or execute_code.

Quote
3. Exiting Code
What do you mean with "entire code"? Do you mean the event? If so, then I guess it could be cool if you could stop the rest of the event to be executed. But to exit from code in any place you can just type "exit;".
Title: Re: Some common GML issues, will/how can they be dealt with in Enigma?
Post by: polygone on December 21, 2010, 03:56:33 pm
Quote
And how exactly the return value would look like? If you just thought something like instance_nearest_nth (which would return n'th nearest instance) then that needs just a separate function.
I don't know, I don't have all the answers, I was wondering if Josh had thought about it. The problem with nth type functions is that they will be a lot slower to cycle through instances. The way I see to do it is by return a list of some sort then you could then cycle through the list somehow or use the with() command perhaps

Quote
As string? Like "sprite_player" would return a sprite index? But then how would you write "sprite_player"? If you thought something like sprite_return("sprite_player"), then I think that could be possible, but in the same way as variable_set or execute_code.
Yes like that, again I don't have all the answers. Although thinking about it some more maybe this naturally wont be such an issue in enigma since it will I presume have better resource cycling functions then GM I imagine you could write a function easily to loop through a resource and map it yourself. This is a common thing that 'newbies' wish to do though so maybe Enigma could automatically map resource indexes to string values then Enigma could actually call reference resources from string values. As horrible as this sounds it might be worth considering...

Quote
What do you mean with "entire code"? Do you mean the event? If so, then I guess it could be cool if you could stop the rest of the event to be executed. But to exit from code in any place you can just type "exit;".
Yes I meant event, edited the post to include that.
Title: Re: Some common GML issues, will/how can they be dealt with in Enigma?
Post by: TheExDeus on December 21, 2010, 04:22:21 pm
Quote
The problem with nth type functions is that they will be a lot slower to cycle through instances.
Well you will always need to cycle trough all the instances. Its the only way to actually get the distance of thous instances (unless the room is divided in some regions and only instances in specific regions are checked etc.).

Quote
2. The function is able to cycle through instances itself
Well C++ is possible to return multiple values, and automatically populating an array or some ds could also be possible.

Quote
Yes like that, again I don't have all the answers.
No I just wanted to understand what you actually meant. For example:
Code: (C++) [Select]
sprite_index="spr_player"; //this would not be good, because you can't actually return "spr_player" in this case. So context sensitive parsing could do this while compiling, but not real time.
sprite_index=sprite_get_string("spr_player"); //this on the other hand could be cool. Especially when some simple loops are necessary
Title: Re: Some common GML issues, will/how can they be dealt with in Enigma?
Post by: polygone on December 21, 2010, 04:42:09 pm
Quote
Well you will always need to cycle trough all the instances. Its the only way to actually get the distance of thous instances (unless the room is divided in some regions and only instances in specific regions are checked etc.).
But with using nth you will need to cycle through the instance multiple times, every time it is called which is much slower. Unlike if you return a list of instance which only requires cycling through once, which is why I think the first method is probably a better choice.

Quote
No I just wanted to understand what you actually meant.
I wasn't fixed on a method, I think they are both could actually be done. The first:

Code: (EDL) [Select]
sprite_index = "spr_player";
instance_create(x, y, "obj_player");
Is much easier to use and more naturally to beginners to use, but is a lot less 'coder' friendly. I believe this could be implemented if Enigma automatically maps resource indexes to corresponding string indexes. Then for all instance functionality it could check if a real is given, if so just return the index as normal or if a string is given then lookup from a map and return the corresponding index. From a coder perspective I do not particularly like this myself but it would make life easier for beginners who do not understand the difference between strings and indexes, many beginners try to do this in Game Maker.

Code: (EDL) [Select]
sprite_index = sprite_get_index("spr_player");
instance_create(x, y, object_get_index("obj_player"));
These _get_index functions returning the index from a string name could be added to compliment the object_get_name() and hopefully _get_name() functions for all the resources. This is much more coder friendly but would still require Enigma mapping all the resource indexes to corresponding string names.

Or maybe both could be implemented? I personally would never use either method because I think it's bad programming but I'm just thinking what might entice beginners to the program.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: Josh @ Dreamland on December 21, 2010, 08:03:22 pm
Trying to sort through you two's bickering is frustrating, so I'll just reply to everything I see without linking the posts together.

First, Poly's original post:


1. Referencing multiple instances

In Game Maker, the only way to do this is multiple inheritance. Most worthwhile scripting languages today offer multiple inheritance, but this isn't compatible with GM's system at face value due to ambiguity in event inheritance. I am still abstracting ideas on how to resolve this, but some of them depend on Ism. I've actually been thinking about this myself for my own purposes, and this is what I have so far:
2. Referencing resources as strings

I've never thought of this. It could be implemented but is not in any plan thus far. As you may be aware, maps are much easier to use in ENIGMA, but if you feel this is beneficial, file a suggestion in the tracker and I'll see about implementing it.

3. Exiting Code

I've been chewing on this issue for tears. Presently, scripts and DND are homogeneous; one exit means all exit. And, game_end() is instantaneous at the moment because I've not standardized an exit method. I've been waiting for someone to complain about this behavior before I modified it; suggestions are always welcome. I may define "exit" as goto <label generated at end of this script> and leave "return" as an omnipotent breaker. I Intended to do this about the time I index the code for quick position lookup on C++ compile error.

4. get_real

Already implemented in GTK interface; will be implemented in WinAPI when the widget APIs are finished and made available.

5. Pausing The Game

In the beginning, when the earth was young, young me wanted a pause feature that would put that kind of functionality in the hands of the user. Back then, it was intended that ENIGMA would have its own interface, and I would have a special resource to implement draw code for the pause screen. I haven't even presented the idea to Ism, because I have enough things on my wish list for her. Do you suppose it will require more than a single script executed each paused step? And should it paused immediately, or just after the frame? (You mentioned this point in another issue on this list).

6. Multiple collisions issue

Good suggestion! When I was new to Game Maker, I had this problem. I wanted to play a sound when crashing into an instance. An abs(hspeed)>0 check wouldn't work, because I just set the hspeed every time you pressed an arrow. So I ended up just checking that the sound wasn't playing. Your example's an even better one, though. The problem hasn't occurred to me in a while, and I never thought up a solution in ENIGMA. I'm a bit tired to think one up now, but I'll put some thought into it over the next while and tell you if I come up with something. My first impulse is a flag called "collision_fresh" which is set to TRUE or FALSE according to whether or not a key exists in a 2D map with the IDs of both instances. I have no idea the implications of the efficiency or simplicity of use, so I'll have to think about it further.

7. Timers
Rusky got me thinking about this problem not long ago. His solution didn't strike me as practical because I didn't see how to implement it (especially in ENIGMA), but the idea is an instantiable event (his proposal involved closures). Presumably this could be resolved by having easily forged first-class functions, but with the current state of both C++ and GML this just doesn't seem practical in full scale. They're illegal inline in C++, and var doesn't allow storing anything but real and string. What I may end up doing is allowing in-place declaration of alarms, which would mean no less bloat, but an easier interface. Again when the earth was young, I was thinking it'd be neat to have a when() {} statement, but I hadn't the foggeiest how to implement it. I may as well use the same mechanism to do so.
Or I can simply implement when() to mimic for(), and it could be used like this:
Code: (EDL) [Select]
when (i=0; i==10; i++) {
  //Alarm code
}
But that's kind of ugly. What do you think? My original idea was just when(condition), but I'm not sure the typical user is smart enough to say timer_explode = 0; when (timer_explode++ == 10) explode();



Upon reading the rest of the replies, they seem to have resolved themselves or have already been answered above. I don't have an API to iterate instances other than rooms, which you can do in GML like so:
Code: (EDL) [Select]
for(r = room_first; r != -1; r=room_next(r)) map[room_get_name(r)] = r; I could add such an API for all resources, if you like.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 22, 2010, 07:27:29 am
Quote
Upon reading the rest of the replies, they seem to have resolved themselves or have already been answered above. I don't have an API to iterate instances other than rooms, which you can do in GML like so:
Code: (EDL) [Select]
for(r = room_first; r != -1; r=room_next(r)) map[room_get_name(r)] = r; I could add such an API for all resources, if you like.
I think it would be obviously useful to add an API for all resources, I've seen this wanted many of times in GM. It's just nice to have the consistency anyway. I presumed this would be something you would naturally add.

Quote
1. Referencing multiple instances
I've actually been thinking about this myself for my own purposes, and this is what I have so far:
... <snip>
Interesting ideas, maybe you could start a new topic to discuss some of these concepts further. As they could lead to some changes I think they are perhaps best discussed earlier rather than later.

Quote
2. Referencing resources as strings

I've never thought of this. It could be implemented but is not in any plan thus far. As you may be aware, maps are much easier to use in ENIGMA, but if you feel this is beneficial, file a suggestion in the tracker and I'll see about implementing it.
Like I said I'm not personally a fan of the process but I think it's little things like this which really add up in appealing to beginners. I'll put it in the tracker if that's the best place for it.

Quote
3. Exiting Code

I've been chewing on this issue for tears. Presently, scripts and DND are homogeneous; one exit means all exit. And, game_end() is instantaneous at the moment because I've not standardized an exit method. I've been waiting for someone to complain about this behavior before I modified it; suggestions are always welcome. I may define "exit" as goto <label generated at end of this script> and leave "return" as an omnipotent breaker. I Intended to do this about the time I index the code for quick position lookup on C++ compile error.
So the current behaviour doesn't actually match GM's but I presume you plan on changing it to do so. A little idea I thought of, which isn't exactly 'nice' but rather convenient for usage would be to have an optional argument for those functions. For example:

Code: (EDL) [Select]
game_end(inst)If it was plain called with no argument as game_end() it would execute as inst being false so would behaviour exactly like GM's but if wanted you could could call game_end(true) to end the game instantaneously. I'm not sure how this idea fits in with how Enigma currently works but I think the same concept could also be used for other functions, like instance_destroy(). It's a lot more naturally for beginners to be able to specify and argument to that function to destroy a specific object, I see this all the time. So I was thinking it could possibly be done in the same way as previously suggested:

Code: (EDL) [Select]
instance_destroy(obj)When called plain with no argument as instance_destroy() it would destroy the current instant exactly like GM's but if wanted you could call game_end(obj) to specify a particular instance to destroy.

Quote
5. Pausing The Game

In the beginning, when the earth was young, young me wanted a pause feature that would put that kind of functionality in the hands of the user. Back then, it was intended that ENIGMA would have its own interface, and I would have a special resource to implement draw code for the pause screen. I haven't even presented the idea to Ism, because I have enough things on my wish list for her. Do you suppose it will require more than a single script executed each paused step? And should it paused immediately, or just after the frame? (You mentioned this point in another issue on this list).
I'm not actually sure it would work very well having it's own interface, it sounds like a lot of work to implement as well which is never good for Ism.

I was thinking before of perhaps a separate set of functions for pausing, like something similar to that of the high-score functions. So it's functionality is not fully in the hands of the user but more generalised. This would be easy for most people if they want plain pause menus but then some pause menus also need to interact with the game itself which would be more difficult to do (maybe script_execute could be utilised by the user for this?).

I don't know really. It's not a particularly nice thing to implement but then it's also currently not very nice for the user to implement either which is why it would be rather useful if something could be worked out. Surely some other game creation programs use a pause system. It might be worth looking around to see how some of them have implemented it.

Quote
7. Timers
... <snip>
I'm going to think about this some more and get back to you. Again it's one of those things that isn't exactly very nice to implement but I'm sure something neat could be worked out.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: TheExDeus on December 22, 2010, 08:02:56 am
Quote
5. Pausing The Game
I usually just use room_persistent and move to another room. Very easy to implement, cool effects possible (like drawing the frame to a global surface and then blur it in the background in the pause room) and works great.

Quote
I've been chewing on this issue for tears.
Don't cry. Everything will be o..... *died*
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: MrGriggs on December 22, 2010, 08:29:07 am
Code: [Select]
when(i,==10,mytimer) {
if Done = true;{
Dostuff();
}
{

Script When
Code: [Select]
if argument2.firstran == false {
timer = string(argument3)
firstran = true;
//First ran code
argument2.Done = false;
argument0 = 0;
}


if (argument0 !argument1) {
argument0 +=1;
}
if (argument0 argument1) {
argument2.Done = true;
}







Would something like this not work for a timer?
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 22, 2010, 10:57:33 am
OK I have thought about things some more and I think come up with a good setup. Adding these features would be hugely beneficial, allowing things to be done much more simply and I believe actually more efficiently than is currently possible. The reason I see it could be more efficient is I presume once executed these checks could be completely removed internally, whereas a user cannot do this themselves with a standard alarm or step check, the alarm or check will always remain even if it's not being used any more.

Timer Event

I think you should add a separate event for timers, which is executed every step until the count hits 0. Just like alarms, eg:

Code: (EDL) [Select]
timer[0] = 4*room_speed;
Timer 0 Event:
Code: (EDL) [Select]
draw_text(x, y, "some text");That would be the way of solving my original problem. (Except you wouldn't be able to draw in the event but you get the idea...).

Do Step Statement

The when statement suggestion I think should definitely be added also, it really is a more powerful system. I don't think it's best suited like a for statement though, more like a do, until statement and I think it should be renamed from when to something else I'm just using do_step for now but it will obviously need to be changed from that also. I'm seeing something like this:

Code: (EDL) [Select]
i = 0;
do_step
{
  draw_text(x, y, "some text");  //will draw some text every step
  i++;
}
until (i == 4*room_speed)  //until i is equal to 4*room_speed
When the until statement has been met the code will be removed from the game.

Alarm Statement

You could maybe also do a similar statement with alarms, I think the keyword when is more suited to this actually:

Code: (EDL) [Select]
i = false;
when (i == true)
{
  show_message("hello");  //will show the message when i is set true
}
Basically it would set a dynamic alarm, when it has been executed once the code can again be removed from the game I presume.

You could then do standard alarm functionality by combining the two. ie:

Code: (EDL) [Select]
i = 4*room_speed;
do_step
{
  i--;
}
until (i == 0)

when (i == 0)
{
  show_message("hi");  //will show the message in 4 seconds.
}
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: Rusky on December 22, 2010, 11:03:26 am
GM already has a way to iterate over all instances:
Code: (gml) [Select]
for (i = 0; i < instance_count; i += 1) {
    if (instance_id[i].object_index == bomb_obj && distance_to_object(instance_id[i]) < 100)
        instance_destroy()
}
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 22, 2010, 11:12:57 am
That code is also a lot slower than if it was done internally. And it's long winded to write. Looping through instance_position like that is even slower.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: freezway on December 22, 2010, 04:22:59 pm
Are we gunna duplicate the create event happening before game start event bug?
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: IsmAvatar on December 22, 2010, 06:48:48 pm
freezway: This behavior is defined in events.res, I believe, which is a text file that you may freely modify. It seems like ENIGMA currently has game start occur first, then room start, and then create. This could be simply reordered as you desire.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: Josh @ Dreamland on December 22, 2010, 07:00:19 pm
Polygone:
game_end(bool now = false): Good idea.
instance_destroy(obj): Already done. Since R3, and made public in R4.

Quote
I'm not actually sure it would work very well having it's own interface, it sounds like a lot of work to implement as well which is never good for Ism.

I was thinking before of perhaps a separate set of functions for pausing, similar to the high-score functions maybe. So it's functionality is not fully in the hands of the user but more generalised. This would be easier for plain pause menus and for most people to use but then a lot of pause menus also need to interact with the game itself which would be more difficult to do (maybe script_execute could be utilised though?).
Actually, it'd be as simple as another setting script like the four she offers now under "ENIGMA Settings." Each of those is supposed to be game-specific, and Definitions scripts are supposed to be instantiable. ENIGMA will, at that point, let you set code to be executed before game start, after game end, and (with my proposed addition) during game pause.

I think you should add a separate event for timers, which is executed every step until the count hits 0. Just like alarms really...
I see no distinction between your proposal and additional alarms. We could easily make alarms unlimited.

The when statement suggestion I think should definitely be added also, it really is a more powerful system. I don't think it's best suited like a for statement though, more like a do, until statement and I think it should be renamed from when to something else
when(){} and do_step{}  are two entirely different mechanisms, as I'm sure you realize. They are the step-based equivalents to if() and while(), respectively: if() and when() are performed only once (when the condition is finally met), where do_step() and while() are performed throughout the duration of a condition (or its negation). In ENIGMA, no distinction is made between while !() and until()... that may work to our advantage. How do you feel about when(){} and step(){}[until()]?
Code: (EDL) [Select]
// Destroy the next gate we come near. It'll probably create effects in its destroy event.
when (distance_to_object(instance_nearest(x,y,gate))<32)
{
  instance_destroy(instance_nearest(x,y,gate));
}

// Implement an alarm using only one local variable
local int do_explode = 0;
when (++do_explode == 30)
{
   // Alarm code
}

// Emit particles until not dizzy
local int dizzy = 100;
step {
   instance_create(x,y,dizzy_spiral);
   dizzy--;
} until not dizzy

Rusky:
...Sometimes I think you don't know what with() does...

Code: (GML) [Select]
for (i = 0; i < instance_count; i += 1) {
    if (instance_id[i].object_index == bomb_obj && distance_to_object(instance_id[i]) < 100)
        instance_destroy()
}

Is apparently the same as, but much, much less efficient than
Code: (GML) [Select]
with (bomb_obj) if (distance_to_object(instance_id[i]) < 100)
        instance_destroy()

Freezway/Ism:
The create event in GML is the equivalent of a constructor in C++. By logical dynamic, the create event must be the first event an instance can perform. Events.res has no control over the create event; it only lists it with an integer mapping to Mark's specification.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 22, 2010, 07:11:58 pm
Quote
Actually, it'd be as simple as another setting script like the four she offers now under "ENIGMA Settings." Each of those is supposed to be game-specific, and Definitions scripts are supposed to be instantiable. ENIGMA will, at that point, let you set code to be executed before game start, after game end, and (with my proposed addition) during game pause.
Ah I see, that's a good idea yeah. I didn't realise you could do something like that so easily. If you could get that to work it would be a very good way of implementing pausing.

Quote
I see no distinction between your proposal and additional alarms. We could easily make alarms unlimited.
The timer suggestion I made is different to alarms, the code in alarm events only executes when the alarm timer reaches 0. The code in timer events would execute every step until the timer reaches 0. Timer event probably isn't the best name for it as it's confusing, I couldn't think of a proper name for it though.

Quote
How do you feel about when(){} and step(){}[until()]?
Yes step() is a good name instead of do_step. That all works good. :)

I didn't think of the ++do_explode trick, I see how that makes things even easier. :)

So are you happy with that syntax yourself now? I think it all works well and comes rather naturally to write, I don't think a beginner would struggle with the concept either, it seems pretty easy to follow in my opinion (it's probably easier to understand than a for loop).
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: Josh @ Dreamland on December 22, 2010, 08:05:57 pm
Timers:
Ah, I see. Not a bad idea; I'll implement it when Ism reads events.res after we have our own format.

when/step:
Yes, I'm pretty happy with the syntax we specified (used in my example code). We should probably document the alarm-like behavior of when (with the ++name) so new users know how to do so simply.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 22, 2010, 08:28:38 pm
Oh I have just had some sudden thoughts.

I was thinking could you make it so using until after step was optional, if it wasn't added it would just always execute the code in the step event. While visualising that and due to your changed naming convention I then thought could you not also add beginstep and endstep statements as well? This would then give you control over when the step code is actually executed. And, then I thought surely a draw statement could also be added in the exact same way. So things like this could be done:

Code: (EDL) [Select]
draw
{
  draw_text(x, y, "Yo");  //this would draw the text "Yo" from now on
}
OR

Code: (EDL) [Select]
i = 0;
draw
{
  i++;
  draw_text(x, y, "some text");  //this now actually solves the original problem I stated! :]
}
until (i == 4*room_speed)
This would be great. Not being able to draw in events other than the draw event is actually another one of GML's common problems but this would be a neat way of solving it if it is possible to implement, which I'm thinking it is ...

Quote
Timers:
Ah, I see. Not a bad idea; I'll implement it when Ism reads events.res after we have our own format.
Cool. Maybe think of a better name for them though :)
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 22, 2010, 08:55:12 pm
Another thought, could you add a read-only global variable current_step, which would work just like current_time except with steps. Then alarm codes will become even easier and not need to involve creating a local variable each time:

Code: (EDL) [Select]
var message_end = current_step +  4*room_speed;
draw
{
  draw_text(x, y, "some text");
}
until (current_step == message_end)

Code: (EDL) [Select]
var step_now = current_step;
when (current_step == step_now + 30)
{
   // Alarm code
}
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: Josh @ Dreamland on December 22, 2010, 09:13:02 pm
I like the draw {} idea. I think we'll limit it to that.

As for current_step making lives easier... I suppose so, but I think ENIGMA inherits enough bloat from GM as it is. I... guess I'll consider it since current_time in fact will not take space in ENIGMA's RAM unless used.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 22, 2010, 09:24:06 pm
I like the draw {} idea. I think we'll limit it to that.
OK. I suppose beginstep and endstep aren't exactly 'pretty' as statements. Draw and step will be nice enough :)

Quote
As for current_step making lives easier... I suppose so, but I think ENIGMA inherits enough bloat from GM as it is. I... guess I'll consider it since current_time in fact will not take space in ENIGMA's RAM unless used.
Hmm, I'll try to think of some other uses for it to try and justify it's inclusion. Perhaps you should not add any unnecessary extra bloat though like you said, it is a variable you kind of expect to exist though.

EDIT: It could be useful with timelines maybe? In fact wouldn't you actually need an internal variable like this if timelines were used in a game (that's if you even bother to actually implement them of course :p).
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: IsmAvatar on December 22, 2010, 09:36:45 pm
Careful with how you name them. 'draw' is a common variable name that people use to determine whether something will draw or not. 'step' is usually an incremental variable, sometimes used to indicate how many 'steps' a character has walked. I wouldn't expect people to use them as script names, though, so draw() and step() would be safe, as long as they are distinguished from their non-parenthesized namesake.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: luiscubal on December 23, 2010, 11:43:18 am
There are edge cases that need to be solved.
For instance, is draw{} drawn BEFORE or AFTER the draw event contents?

Also, in
Code: (EDL) [Select]
var step_now = current_step;
draw
{
  draw_text(x, y, "some text");
}
until (current_step == step_now + 4*room_speed)

If current_step != step_now + 4*room_speed for a bit, and then equal once again, would some text be rendered in the screen or not?

Also, regarding WHEN, couldn't it significantly harm performance?
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 23, 2010, 12:11:47 pm
Quote
For instance, is draw{} drawn BEFORE or AFTER the draw event contents?
After would make more sense to me.

Quote
If current_step != step_now + 4*room_speed for a bit, and then equal once again, would some text be rendered in the screen or not?
Text would be drawn while (current_step != step_now + 4*room_speed) and then when (current_step == step_now + 4*room_speed) the code piece would be removed so it would not be drawn again.

Quote
Also, regarding WHEN, couldn't it significantly harm performance?
Why?
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: luiscubal on December 23, 2010, 01:28:39 pm
If you have multiple draw{}until(); statements, in which order are they executed.

Also, regarding performance, I think I misread the way "when" works.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 23, 2010, 01:46:54 pm
If you have multiple draw{}until(); statements, in which order are they executed.
I presume in the order they were called. I see it as just adding them in a list to the end of the draw code, then if their until statement is met they are removed from the list.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: TheExDeus on December 23, 2010, 05:10:43 pm
There is reason why GM can draw only in draw event you know... For example, if object1 has depth=0, and another object2 has depth=2. So the first object1 draw event is executed before the second one and thus draws on top of the other. Now what happens when object1 draws in step event? It will draw below the object2 even thou it should draw on top. This can be fixed with some kind of queue, but that seems just like another way to lose memory and speed. Thou Josh can prove me wrong and get this done for the next rev, so I can snuff my coke in amazement.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 23, 2010, 05:15:02 pm
Quote
This can be fixed with some kind of queue, but that seems just like another way to lose memory and speed.
Why would it lose memory and speed?
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: TheExDeus on December 23, 2010, 05:43:46 pm
Well queues need memory (in best case a vector that can autoresizes) and speed, well, because it just needs all this. Maybe the impact wouldn't be that big, but who knows.

I agree about the timer thing, and it would kick ass. But the draw{} thing just seems very problematic. Maybe Josh came up with some biblical idea that will blow our minds, but will see.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 23, 2010, 05:53:51 pm
Isn't the whole event system already on a queue?
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: Josh @ Dreamland on December 23, 2010, 09:39:45 pm
Yes, all of these will be queued in each event if used. Pay attention to that last clause. If no one uses the when(), step{}, or draw{} statement, they will not be added to any of the objects. As polygone mentioned, most of the events are entirely queue-based anyway, so the performance cut from when() will be roughly negligible. Those who are concerned about the negligible (such as myself) can opt to program the checks in manually so they are not stacked anywhere and iterated.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: r9k on December 24, 2010, 06:49:42 am
I approve.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 24, 2010, 06:51:21 am
As I said previously I think these statements will actually improve efficiency. Let's look at an example. Say you are making a platform game and you want to the game to save once automatically when the player's x reaches 300. Now this is the method I would normally use in GM:

Creation Event:
Code: (EDL) [Select]
saved = false;
save_dist = 300;

Step Event:
Code: (EDL) [Select]
if !(saved)
{
  if (x >= save_dis)
  {
    game_save();
    saved = true;
  }
}

And this is the method I would use with a when() statement:

Creation Event:
Code: (EDL) [Select]
var save_dist = 300;
when (x >= save_dist)
{
  game_save();
}

Using the when() statement there is no need for a saved variable check because once the when statement has been met it will be removed and not checked again. Thus the code will be more efficient both before and after the player reaches 300 because that extra 'saved' check is not needed. Note also the decrease in memory and the opportunity to use no extra local variables.

You can then go even further, imagine you want to add a save point from a key press instead of just the creation event. Easy to do with the when() statement but try doing it in GML, you have to add another variable and it's even messier.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: r9k on December 24, 2010, 06:57:53 am
I would expect when() to run more than once.

Code: (EDL) [Select]
onceWhen(x >= 300)
game_save();
}
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 24, 2010, 07:10:54 am
I would expect it to only run once. I would expect something like whenever for running multiple times:

Code: (EDL) [Select]
whenever (x >= 300 && xprevious < 300)
{
  show_message("You crossed the 300 line!");
}
This would be just the same as adding an if check in the step statement though so is pretty pointless:

Code: (EDL) [Select]
step
{
  if (x >= 300 && xprevious < 300)
  {
    show_message("You crossed the 300 line!");
  }
}
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: Josh @ Dreamland on December 24, 2010, 07:38:45 am
You seemed to expect when() to fire for each call when you called it in that script. Each when would have only one id, but there's an issue with that, anyway; neither x nor argument0 is a constant. We haven't specified any way of denoting that one of the parameters passed to when() is constant. So when that when() was called, the condition x > argument0 would be superimposed on the step event, and that check would be done each step verbatim.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: polygone on December 24, 2010, 07:43:53 am
You seemed to expect when() to fire for each call when you called it in that script. Each when would have only one id, but there's an issue with that, anyway; neither x nor argument0 is a constant. We haven't specified any way of denoting that one of the parameters passed to when() is constant. So when that when() was called, the condition x > argument0 would be superimposed on the step event, and that check would be done each step verbatim.
Hmm I had not thought of that, I have edited it out of the examples so it is not an issue.

What syntax could be used be used to specify constants? You can define a variable local to a script for it to be constant, for example:

Code: (EDL) [Select]
var arg0 = argument0;
when (x >= arg0)
{
  game_save();
}
But it would be useful to have a way of defining constants.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: Josh @ Dreamland on December 24, 2010, 09:21:39 am
Not sure. We could just abuse the const keyword, like so:
Code: (EDL) [Select]
when (x >= const(argument0))
  game_save();
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: TheExDeus on December 25, 2010, 11:17:19 am
Quote
Yes, all of these will be queued in each event if used. Pay attention to that last clause. If no one uses the when(), step{}, or draw{} statement, they will not be added to any of the objects. As polygone mentioned, most of the events are entirely queue-based anyway, so the performance cut from when() will be roughly negligible. Those who are concerned about the negligible (such as myself) can opt to program the checks in manually so they are not stacked anywhere and iterated.
I just meant drawing. As far as I know drawing is not queued, and thus using draw{} inside step event would cause problems with depth. That was all I was saying. Maybe I misunderstood something thou.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: Josh @ Dreamland on December 25, 2010, 11:35:05 am
I don't see how. A function is a function....
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: TheExDeus on December 25, 2010, 01:53:15 pm
Quote
I don't see how. A function is a function....
Well but isn't step before draw? And so if there is draw{} inside step, then wouldn't it draw in the wrong depth (below everything)? Well, but if its queued then ok. I just don't see where that queuing is happening, as I have only made some draw functions themselves and haven't checked any event code. I guess I will have to study the code some more. :) And how font loading from LGM is going?
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: IsmAvatar on December 25, 2010, 04:58:29 pm
LGM passed font information to ENIGMA, and passes each glyph separately. Josh asked for a compression callback, so I provided one. Everyone was using font_load_from_sprite, which required each subimage be a separate glyph, so to alleviate the processs I added in sprite strip loading into LGM. At this point, LGM+Plugin does everything ever asked of it to make the font support easier, short of drawing the glyphs itself each draw event... the rest is Josh being too lazy to do anything about it, or to even bother finding out/reporting any problems with the stuff I provided him.

Edit: guy32123 was nice enough to report that populating the font glyphs sometimes somehow populates more than 255 glyphs, causing an ArrayIndexOutOfBoundsException. I'm investigating it right now and trying to reproduce it.

Edit2: I think I fixed that. Should be in for the next revision (r583).
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: RetroX on December 30, 2010, 11:46:55 pm
2. Referencing resources as strings

People often find themselves wanting to reference a resource index from it's corresponding string, being lazy they don't wish to map all the object indexes to strings manually, so is there a way this can be done easily in Enigma?
Haven't read the topic, but:

This will be nice, as it removes 90% of the use of execute_string().

Oftentimes, people do things like:
status = 'standing';
color = 'blue';
execute_string('sprite_index = player_' + color + '_' + status);
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: TheExDeus on December 31, 2010, 05:15:52 am
Quote
This will be nice, as it removes 90% of the use of execute_string().
I agree. That's actually the only reason why I use execute_string. Even thou GM can set variables using strings too, it doesn't allow creating them. It wouldn't change anything sprite_index case, but it would be nice if things like variable_create("int variable"), would create a variable. This is the reason why I still needed to use execute_string in one GM project, as it allows creating variables too. I had an alternative, but it would be harder to use, so...

edit: Though I don't know how this (even if this) would work in C++.
Title: Re: Some common GML issues, and dealing with them in Enigma?
Post by: RetroX on December 31, 2010, 11:49:19 am
The only way that it would work in C++ is by creating a map of variables to strings.

map<var*, string> var_map;
var_map.find(variable_name);

Of course, I think that ENIGMA should have a separate resource and variable map, and have each disablable.  This also probably is how execute_string would pull variable/resource names.