This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
Pages: « 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 »
331
Programming Help / Re: Instance Creation Codes
« on: May 17, 2014, 09:09:03 am »
So, Robert recently edited the draw_string function. It wouldn't surprise me if it crashes your game when passed an empty string or an uninitialized variable. Could you verify this by drawing string(string_length(text))? That will at least tell us what's going on.
Another item to consider is the fact that your string contains a "²" character. Did you modify your font to contain this glyph? Does it crash in debug mode? What happens if you remove this glyph?
Another item to consider is the fact that your string contains a "²" character. Did you modify your font to contain this glyph? Does it crash in debug mode? What happens if you remove this glyph?
332
General ENIGMA / Re: Variable performance
« on: May 17, 2014, 08:41:27 am »
I'm glad we actually have a benchmarking tool. This can be fixed with a little reflection, and depending on the user's mood, a little memory. Throughout ENIGMA's past, I've hemmed and hawed about how to treat variables referenced in with blocks. The current behavior is to look them up in the same manner as ID-referenced variables. The other behavior was to scope them into everything, so they exist and are located in the same place in every object, and therefore are trivial to access.
A third behavior I have not attempted is using virtual tables to store the variable access methods. This would make arbitraryId.myvariable into getter(arbitraryId)->get_myvariable(). This moves the burden from a switch statement based on object index to a simple virtual call. We're probably already incurring a by-pointer function call, so this could only mean savings.
The simplest way to take care of the whole "var" fiasco is with some static analysis of the code. This cannot be done with the current compiler.
Note: the behavior you are seeing, ie, GM being faster at setting a single var index, is due to the fact that GM's variables are always a map. So nothing special is constructed when you need to assign to a var. It's not that assigning to a var is expensive—constructing one is. There might be a way to improve that by enforcing a single var implementation, and moving the contents of var4_lua.cpp into var4.cpp. This would remove the need to do the allocation tricks I've done, and expose all code to the optimizer. Another quick trick might be replacing std::map with a faster map type; you could try hash_map.
Please do a benchmark with variant instead of var.
A third behavior I have not attempted is using virtual tables to store the variable access methods. This would make arbitraryId.myvariable into getter(arbitraryId)->get_myvariable(). This moves the burden from a switch statement based on object index to a simple virtual call. We're probably already incurring a by-pointer function call, so this could only mean savings.
The simplest way to take care of the whole "var" fiasco is with some static analysis of the code. This cannot be done with the current compiler.
Note: the behavior you are seeing, ie, GM being faster at setting a single var index, is due to the fact that GM's variables are always a map. So nothing special is constructed when you need to assign to a var. It's not that assigning to a var is expensive—constructing one is. There might be a way to improve that by enforcing a single var implementation, and moving the contents of var4_lua.cpp into var4.cpp. This would remove the need to do the allocation tricks I've done, and expose all code to the optimizer. Another quick trick might be replacing std::map with a faster map type; you could try hash_map.
Please do a benchmark with variant instead of var.
333
General ENIGMA / Re: EDC Partially Fixed
« on: May 12, 2014, 09:47:06 pm »
We weren't hacked; someone just decided that a good item to display on failure is "ಠ_ಠ". This was RackSpace side, which was funny. That's the only reason it was worth remarking on.
The only issue with the EDC was in how we retrieve our API URLs from the Service Catalog we are given along with our auth token. The problem was that we were just taking the first service in the catalog. That *used* to be the only service listed, but now we're given a catalog of some 25 other services, and we wanted the 14th in the list, called "CloudFiles". So now I just filter for that string. RackSpace actually recommends just hard-coding the URLs, though, so we'll probably switch to that in the near future (or next time this breaks).
The only issue with the EDC was in how we retrieve our API URLs from the Service Catalog we are given along with our auth token. The problem was that we were just taking the first service in the catalog. That *used* to be the only service listed, but now we're given a catalog of some 25 other services, and we wanted the 14th in the list, called "CloudFiles". So now I just filter for that string. RackSpace actually recommends just hard-coding the URLs, though, so we'll probably switch to that in the near future (or next time this breaks).
334
Programming Help / Re: function error
« on: May 11, 2014, 04:43:05 pm »
If that works for any reason, it's because it's getting parsed into something entirely different. But it shouldn't even compile...
335
Programming Help / Re: Question on variables and arrays (important)
« on: May 11, 2014, 09:34:59 am »
The local and global keywords in ENIGMA, when followed by a type, begin a C++-style declaration at the instance-local or global scope, respectively.
I am still deliberating on the sanity of this behavior when it comes to arrays. Presently, [snip=EDL]local int my_int[100];[/snip] declares in the instance a C++-style array of 100 integers. This means that indices [0] - [99] are valid, while indices outside that range will cause an immediate, unrelenting, undetectable segmentation fault, in the best case. In the worst case, you'll silently break your whole game by assigning out of bounds.
What should be done about this is modifying the way arrays are treated in debug mode. That is, use a hidden, fixed-size array class behind the scenes while in debug mode. This class would report undefined behavior through the show_error mechanism.
Now that I think about it, an elegant way of dealing with it might be to create a distinction between [snip=EDL]int a[100][/snip] and [snip=EDL]int[] a;[/snip], regardless of whether we allow (unlike most languages) specifying the size in the prefix [].
As for data structures, be aware that var is a sparse matrix. This means that you can use it efficiently as an array, or a 2D map. Assigning to myvar[100000, 200000] will not significantly increase your memory usage. That said, you probably don't want [snip=EDL]local var a[100];[/snip], as this creates an array of 100 sparse matrices. You could then say [snip=EDL]a[10][10000, 15000] = 20;[snip], but the first bound would have the same limitations and dangers as previously discussed with integer arrays. Plus, it just looks weird.
I am still deliberating on the sanity of this behavior when it comes to arrays. Presently, [snip=EDL]local int my_int[100];[/snip] declares in the instance a C++-style array of 100 integers. This means that indices [0] - [99] are valid, while indices outside that range will cause an immediate, unrelenting, undetectable segmentation fault, in the best case. In the worst case, you'll silently break your whole game by assigning out of bounds.
What should be done about this is modifying the way arrays are treated in debug mode. That is, use a hidden, fixed-size array class behind the scenes while in debug mode. This class would report undefined behavior through the show_error mechanism.
Now that I think about it, an elegant way of dealing with it might be to create a distinction between [snip=EDL]int a[100][/snip] and [snip=EDL]int[] a;[/snip], regardless of whether we allow (unlike most languages) specifying the size in the prefix [].
As for data structures, be aware that var is a sparse matrix. This means that you can use it efficiently as an array, or a 2D map. Assigning to myvar[100000, 200000] will not significantly increase your memory usage. That said, you probably don't want [snip=EDL]local var a[100];[/snip], as this creates an array of 100 sparse matrices. You could then say [snip=EDL]a[10][10000, 15000] = 20;[snip], but the first bound would have the same limitations and dangers as previously discussed with integer arrays. Plus, it just looks weird.
336
Programming Help / Re: Using C++ and GML in same project. Why?
« on: April 27, 2014, 10:36:21 pm »
There are a lot of benefits to a more authentic object-oriented paradigm. I'll write up some clear and useful documentation for them after they are actually implemented. Right now, our C++ feature set is pretty limited.
337
Programming Help / Re: function error
« on: April 27, 2014, 10:33:28 pm »
What I mean is that the memory allocated for the variable exists. It's true that these values can be uninitialized, at least for var/variant. In fact, we attempt to do so now, at the user's option. We could technically allow something like this:
This would offer the same functionality, provided the option "treat uninitialized variables as value 0" was not set.I believe we disable that functionality in release mode, presently, but that's not to say we can't undo that. In general, though, I'm opposed to this; I prefer to be able to seamlessly convert var and variant to primitive types. Before that can happen, of course, I will still need to add checking for function calls that only take the var/variant reference. So theoretically, implementing those functions wouldn't harm too much, at that stage. But I still don't encourage the practice.
But to answer your original question, yes, if you are using the local variable a, it still exists, even if you never use it outside the step event. You are able to access it in other objects using object0.a, or whatever.
The use case you give is archaic at best. If you want other entities to assign that for you, which is arguably way too intimiate (but standard, poor practice in GM), then the solution is to set it to -1 in the create event and check that in the script or whatever. In other words, [snip=edl]if (button_grid == -1) button_grid = ds_grid_create(0,0);[/snip]. This is always safe, because the create event is always performed first. So you'll never accidentally overwrite something by setting it to -1 in create.
Code: (cpp) [Select]
bool variable_initialized(const variant& x) {
return x.type != -1;
}
This would offer the same functionality, provided the option "treat uninitialized variables as value 0" was not set.I believe we disable that functionality in release mode, presently, but that's not to say we can't undo that. In general, though, I'm opposed to this; I prefer to be able to seamlessly convert var and variant to primitive types. Before that can happen, of course, I will still need to add checking for function calls that only take the var/variant reference. So theoretically, implementing those functions wouldn't harm too much, at that stage. But I still don't encourage the practice.
But to answer your original question, yes, if you are using the local variable a, it still exists, even if you never use it outside the step event. You are able to access it in other objects using object0.a, or whatever.
The use case you give is archaic at best. If you want other entities to assign that for you, which is arguably way too intimiate (but standard, poor practice in GM), then the solution is to set it to -1 in the create event and check that in the script or whatever. In other words, [snip=edl]if (button_grid == -1) button_grid = ds_grid_create(0,0);[/snip]. This is always safe, because the create event is always performed first. So you'll never accidentally overwrite something by setting it to -1 in create.
338
Programming Help / Re: Does ENIGMA support command-line args ?
« on: April 27, 2014, 10:22:10 pm »
That doesn't sound right. If it's compliant, parameter_count() should give 3, with parameter_string giving "GAME.EXE", "/cheat", and "/secrets" for 0, 1, and 2, respectively.
339
Programming Help / Re: Not able to set or get userdefined variables with unique values for instances.
« on: April 27, 2014, 08:20:18 pm »
I see. I had GM's find_value and the typical meaning of "find value" confused. I never use Game Maker's data structures; they're kind of terrible.
340
Programming Help / Re: Not able to set or get userdefined variables with unique values for instances.
« on: April 27, 2014, 07:48:41 am »
Q1:
By object_name.instance_id.variable, I assume you mean object_name.id.variable. That's the same, though, as saying object_name.variable. Once you have forced . to find you an instance, it has a definite result whose id will only point to itself. So you could just as well say object_name.id.id.id.id.id.id.id.id.variable, but why would you.
When you say obj_unit.x, your call is theoretically ambiguous, because there are probably multiple instances of obj_unit. ENIGMA deals with this by returning the first instance of that object, which won't always be what you want. This is where an ID comes in, which is why you stash the return value of instance_create: an ID of a specific instance of obj_unit. Note that obj_unit.id is the unambiguous ID of the current first instance of obj_unit. Which still isn't that helpful, because it'll remain the first instance (thus being accessible through only the object name) until it's destroyed, and then you don't want to be accessing it.
Q2:
Correct, on both counts. Those IDs won't change (but may be destroyed), and all lists are global.
Q3:
I did my best to explain this in Q1, but I'll clarify here. If you don't have the ID of a specific instance, then there's no way to access the exact instance you want, unless by chance there is only one instance of that particular object or you are always interested in the first. So if all you know is that you want some obj_unit, you don't really know a lot. However, there are methods to access *all* of the instances, as well as to narrow down some particular instance.
You seem to already be aware of the with statement. It lets you iterate over all instances of a given object, one at a time, changing the scope of the statement to each of their scopes as you go. This is the easiest way of accessing all instances.
What you want to access a specific instance with only an object index, normally you want something like the nearest instance or the instance that intersects some point. For those, you'd use instance_nearest and collision_point, respectively. These functions accept an object index and return an ID of some instance of that object.
You can keep lists of instances, as you are doing. But if you already have the ID of some instance, then looking that ID up in the list is probably not what you want to do. Instead of [snip=EDL]un = ds_list_find_value(t0_list,up); un.image_index = 1;[/snip], try just using [snip=EDL]up.image_index = 1;[/snip]. In your code, un is the index of the instance in your list, which is local to your list, while up is how ENIGMA refers to the instance.
That said, you really only need the list of units if there are many lists of units that you want to iterate over. Otherwise, you can iterate over all of them using with, as you are already doing once to zero the image_index values, and you can just use up to access the current instance of interest.
By object_name.instance_id.variable, I assume you mean object_name.id.variable. That's the same, though, as saying object_name.variable. Once you have forced . to find you an instance, it has a definite result whose id will only point to itself. So you could just as well say object_name.id.id.id.id.id.id.id.id.variable, but why would you.
When you say obj_unit.x, your call is theoretically ambiguous, because there are probably multiple instances of obj_unit. ENIGMA deals with this by returning the first instance of that object, which won't always be what you want. This is where an ID comes in, which is why you stash the return value of instance_create: an ID of a specific instance of obj_unit. Note that obj_unit.id is the unambiguous ID of the current first instance of obj_unit. Which still isn't that helpful, because it'll remain the first instance (thus being accessible through only the object name) until it's destroyed, and then you don't want to be accessing it.
Q2:
Correct, on both counts. Those IDs won't change (but may be destroyed), and all lists are global.
Q3:
I did my best to explain this in Q1, but I'll clarify here. If you don't have the ID of a specific instance, then there's no way to access the exact instance you want, unless by chance there is only one instance of that particular object or you are always interested in the first. So if all you know is that you want some obj_unit, you don't really know a lot. However, there are methods to access *all* of the instances, as well as to narrow down some particular instance.
You seem to already be aware of the with statement. It lets you iterate over all instances of a given object, one at a time, changing the scope of the statement to each of their scopes as you go. This is the easiest way of accessing all instances.
What you want to access a specific instance with only an object index, normally you want something like the nearest instance or the instance that intersects some point. For those, you'd use instance_nearest and collision_point, respectively. These functions accept an object index and return an ID of some instance of that object.
You can keep lists of instances, as you are doing. But if you already have the ID of some instance, then looking that ID up in the list is probably not what you want to do. Instead of [snip=EDL]un = ds_list_find_value(t0_list,up); un.image_index = 1;[/snip], try just using [snip=EDL]up.image_index = 1;[/snip]. In your code, un is the index of the instance in your list, which is local to your list, while up is how ENIGMA refers to the instance.
That said, you really only need the list of units if there are many lists of units that you want to iterate over. Otherwise, you can iterate over all of them using with, as you are already doing once to zero the image_index values, and you can just use up to access the current instance of interest.
341
General ENIGMA / Re: Please vote for ENIGMA's new license
« on: April 26, 2014, 06:44:04 pm »
I'm talking about this:
And I am not aware of a place to submit a license for review. If there is a process for that, I'm interested in seeing it. It's likely that your proposal is a great place to start (at least better than the typical LGPL exemption). But I still need to read that over.
And I am not aware of a place to submit a license for review. If there is a process for that, I'm interested in seeing it. It's likely that your proposal is a great place to start (at least better than the typical LGPL exemption). But I still need to read that over.
342
Off-Topic / Re: Environment Variables are Windows Only
« on: April 26, 2014, 05:35:11 pm »
I don't see a problem with using an otherwise cross-platform toolkit to do platform-dependent coding. With preprocessor expressions, equivalents or alternatives can be given on platforms which do not support that feature.
It's a little unfair that Linux users have to pick between dconf, gconf, xfconf, kconf, and just writing the keys to a file in ~. But that's the downside of customizability, something that Linux distributions have always had, and Windows has generally not. At this point, the obvious choice is dconf or just writing the file.
It's a little unfair that Linux users have to pick between dconf, gconf, xfconf, kconf, and just writing the keys to a file in ~. But that's the downside of customizability, something that Linux distributions have always had, and Windows has generally not. At this point, the obvious choice is dconf or just writing the file.
343
General ENIGMA / Re: Please vote for ENIGMA's new license
« on: April 26, 2014, 05:11:31 pm »
That puts us back in legal muddy-water, because now our license isn't Open-Source approved, and may or may not actually hold water, legally. What constitutes similar/competing software, for example? It's possible we could pull from an existing legal definition of "competing," but only a lawyer would know that.
344
General ENIGMA / Re: Please vote for ENIGMA's new license
« on: April 26, 2014, 03:48:41 pm »
I will have to read over the wx license, but I suspect it suffers the same problem. The problem is that if you can release an arbitrary binary linked against ours, without source code, you can lock us out and sell an improved ENIGMA binary. While this does not encumber the use of our software directly, it gives this party direct and perpetual competitive advantage, leaving this team with little incentive to continue development, and locking everyone in on a proprietary version of ENIGMA due to addiction to the improvements.
This isn't a problem for wx due to its active developer base. Outdoing the wx devs with their own source code is a lot harder than outdoing us with ours.
This isn't a problem for wx due to its active developer base. Outdoing the wx devs with their own source code is a lot harder than outdoing us with ours.
345
Programming Help / Re: Not able to set or get userdefined variables with unique values for instances.
« on: April 25, 2014, 08:20:50 pm »
That's what the local keyword does. It moves your declaration into the class scope. From the behavior you describe with the keyword in place, I'd say the code is working as intended, and the problem is more likely to lie in the code that works with those variables locally.
Pages: « 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 »