Jump to content


Photo

Game Maker Suggestions


  • This topic is locked This topic is locked
1162 replies to this topic

#961 Rusky

Rusky

    GMC Member

  • GMC Member
  • 2492 posts

Posted 20 January 2012 - 04:26 AM

A lot of languages have a ternary operator for that- "expr ? trueResult : falseResult". Another lot of languages just allow if in expressions- "if expr then trueResult else falseResult"
  • 0

#962 Dark Matter

Dark Matter

    RPG Expert

  • GMC Member
  • 3196 posts
  • Version:GM:Studio

Posted 20 January 2012 - 06:52 AM

A lot of languages have a ternary operator for that- "expr ? trueResult : falseResult". Another lot of languages just allow if in expressions- "if expr then trueResult else falseResult"

Yeah, that'd be better to have.
  • 0

#963 Yal

Yal

    デーモン猫ガール

  • Global Moderators
  • 9468 posts
  • Version:GM:Studio

Posted 20 January 2012 - 09:14 AM

I think it would be nice if there was some mechanism for placing many of the same tile in a room more quickly. If you're doing a floor for an RPG or something, it would be nice to be able to make a shape (like a rectangle) with those tiles filling the shape like pixels, except with a grid size. Get what I mean?

You can select multiple tiles from a tile set by holding CTRL and dragging in the image of the background you pick tiles from. It doesn't work properly when the tile set has separation/offset though.
  • 0

#964 paul23

paul23

    GMC Member

  • Global Moderators
  • 3935 posts
  • Version:GM:Studio

Posted 20 January 2012 - 07:54 PM


A lot of languages have a ternary operator for that- "expr ? trueResult : falseResult". Another lot of languages just allow if in expressions- "if expr then trueResult else falseResult"

Yeah, that'd be better to have.


Also notice that in (most) ternary operators the "false result" is only executed if "expr" returns "false", this allows for writing statements like:
a =  ( b != 0  ? 8 / b : 0);
Using scripts will fail as when b is "0" 8 / b is infinite.
  • 0

#965 Gamer3D

Gamer3D

    Human* me = this;

  • GMC Member
  • 1819 posts
  • Version:GM:Studio

Posted 23 January 2012 - 07:47 PM

Also notice that in (most) ternary operators the "false result" is only executed if "expr" returns "false", this allows for writing statements like:

a =  ( b != 0  ? 8 / b : 0);
Using scripts will fail as when b is "0" 8 / b is infinite.


Since you brought that up, YoYo should probably add short-circuit evaluation. This would increase speed (while keeping code easily readable), but might break old code (some of which might depend on GM checking EVERY expression)
  • 0

#966 faissialoo

faissialoo

    I get high on orange

  • GMC Member
  • 1250 posts
  • Version:GM8.1

Posted 23 January 2012 - 08:08 PM

stop dlls and exts messing with what the exe returns when the exe ends.
  • 0

#967 IceMetalPunk

IceMetalPunk

    InfiniteIMPerfection

  • GMC Elder
  • 9603 posts
  • Version:GM:Studio

Posted 24 January 2012 - 04:10 AM


Also notice that in (most) ternary operators the "false result" is only executed if "expr" returns "false", this allows for writing statements like:

a =  ( b != 0  ? 8 / b : 0);
Using scripts will fail as when b is "0" 8 / b is infinite.


Since you brought that up, YoYo should probably add short-circuit evaluation. This would increase speed (while keeping code easily readable), but might break old code (some of which might depend on GM checking EVERY expression)

Yeah, I've wanted this for a while. It's at the very least useful to replace nested if's with single lines:

if (b!=0) {
  if (variable/b > 10) {
    somevar = variable/b;
  }
}

Becomes

if (b!=0 && variable/b > 10) {
  somevar = variable/b;
}

Not the best example, but there are more compounded cases that would illustrate the point better, which I just can't think of now.

It would also be nice if ds_lists were implemented as doubly linked lists internally instead of normal arrays (i.e. vectors). Index-based functionality would still be supported, for the new programmers, but it could also support iterators which are much more efficient.

I created my own version of doubly-linked lists not too long ago, using constant-sized ds_lists to represent list nodes. They were much more efficient than ds_lists in everything except adding to the end, which I eventually realized is because if GM's arrays are vectors, they double in size whenever they reach the end, whereas my methods require new allocation for each new node. Still, everything else was orders better, so...I think it should be implemented "correctly" (i.e. in a more standard, generally more efficient way).

-IMP
  • 0

#968 rwkay

rwkay

    YoYo Games CTO

  • YoYo Games Staff
  • 2632 posts
  • Version:Unknown

Posted 24 January 2012 - 11:06 AM

Short circuit evaluation is coming in GM9, I have wanted to add it for a while now but compatibility reasons stop me from doing it - I may add it as an option in GM:Studio (depends if I have enough time).

Russell
  • 4

#969 Rusky

Rusky

    GMC Member

  • GMC Member
  • 2492 posts

Posted 24 January 2012 - 02:01 PM

Can I make a request for short-circuiting behavior? Scripting languages often allow logical operators to evaluate not to true/false, but to whichever object decided their truth/falsehood, which is then treated equivalently by e.g. if statements. This allows for things like default values with ||, or similar checks to the "b != 0" example in more contexts.

For example, to give argument3 a default value, since 0 (or null, that would be nicer) is treated as false, you could say
arg3 = argument3 || my_default
You could also do something like this, using &&, saving the result of some_call in foo:
foo = some_check && some_call()
This even allows for implementing ?: yourself, although it's not very readable:
a = cond && yes || no

Edited by Rusky, 24 January 2012 - 02:03 PM.

  • 0

#970 rwkay

rwkay

    YoYo Games CTO

  • YoYo Games Staff
  • 2632 posts
  • Version:Unknown

Posted 24 January 2012 - 03:25 PM

Most of the issue with that behaviour is down to how the '=' is interpreted in GML as it is not only the assignment operator but also the equality operator this is the reason that the a = b = c; does not work properly (as the b=c is interpreted as an equality not assignment) due to this the behaviour of short circuiting would not be very good.

Now I know that is a bit woolly but it is buried within the language definition and due to the nature of GML it is problematic - currently the parser enforces that the && || ^^ MUST have boolean arguments (the left and right of the operator) this stops the type propagation which is what you are desiring - in the long term for type safety I think this is a good idea (though I would like to hear the arguments for and against).

Russell
  • 0

#971 Rusky

Rusky

    GMC Member

  • GMC Member
  • 2492 posts

Posted 24 January 2012 - 03:51 PM

It is currently possible to do something like "a = b && c" as a statement, so I'm not entirely sure what the problem is parser-wise.

I do wonder how possible it would be to enforce == without confusing people though (or if it would even be beneficial).
  • 0

#972 rwkay

rwkay

    YoYo Games CTO

  • YoYo Games Staff
  • 2632 posts
  • Version:Unknown

Posted 24 January 2012 - 04:08 PM

In GM9 you will need to use == as it simplifies things so much at the parser

Trust me when I say that the Delphi parser it is complicated to do the propagation - for HTML5 and Studio it is a bit easier and I will investigate how to propagate the type correctly from left and right arguments of || && and ^^ - the problem is when you have 2 types that are not the same (say <int> && <boolean>) then the propagation rules have to make sense and be easily understood - some of C's more basic problems originally stemmed from arbitrary and ill understood edge case rules for things like this...

I will need to sit down and think about them when finalising GM9's GML

Russell
  • 0

#973 IceMetalPunk

IceMetalPunk

    InfiniteIMPerfection

  • GMC Elder
  • 9603 posts
  • Version:GM:Studio

Posted 24 January 2012 - 05:57 PM

Can I make a request for short-circuiting behavior? Scripting languages often allow logical operators to evaluate not to true/false, but to whichever object decided their truth/falsehood, which is then treated equivalently by e.g. if statements. This allows for things like default values with ||, or similar checks to the "b != 0" example in more contexts.

For example, to give argument3 a default value, since 0 (or null, that would be nicer) is treated as false, you could say

arg3 = argument3 || my_default
You could also do something like this, using &&, saving the result of some_call in foo:
foo = some_check && some_call()
This even allows for implementing ?: yourself, although it's not very readable:
a = cond && yes || no

I don't understand that second one at all...why would some_call() necessarily be stored in foo? With an && operator, both must be true to evaluate to true, so why is some_call() stored instead of some_check?

-IMP
  • 0

#974 Rusky

Rusky

    GMC Member

  • GMC Member
  • 2492 posts

Posted 24 January 2012 - 11:26 PM

If some_check evaluates to false, foo gets some_check. If some_check evaluates to true, foo gets some_call(). It doesn't matter what some_call() evaluates to at that point because if it evaluates to true, it will evaluate to true again; if it evaluates to false, it will evaluate to false again.

@rkway: I was thinking it would be pretty simple for && and || just to evaluate to the operand that decided their result, the way e.g. Lua, Python, JavaScript, Ruby, Lisp... do. There's no need to bring in C-like type coercion, and since GML is dynamically typed the result doesn't need to be coerced either.

Edited by Rusky, 24 January 2012 - 11:29 PM.

  • 0

#975 paul23

paul23

    GMC Member

  • Global Moderators
  • 3935 posts
  • Version:GM:Studio

Posted 25 January 2012 - 12:06 PM

If some_check evaluates to false, foo gets some_check. If some_check evaluates to true, foo gets some_call(). It doesn't matter what some_call() evaluates to at that point because if it evaluates to true, it will evaluate to true again; if it evaluates to false, it will evaluate to false again.

@rkway: I was thinking it would be pretty simple for && and || just to evaluate to the operand that decided their result, the way e.g. Lua, Python, JavaScript, Ruby, Lisp... do. There's no need to bring in C-like type coercion, and since GML is dynamically typed the result doesn't need to be coerced either.

So.. the TYPE of returned value may differ depending on the first operand? :yucky: That's even more places where you have to watch runtime behaviour. Ah well, I suppose it's not clever to feed strings to a place where you expect booleans anyways.
  • 0

#976 Rusky

Rusky

    GMC Member

  • GMC Member
  • 2492 posts

Posted 25 January 2012 - 02:35 PM

I don't see how that's a problem, especially with dynamic typing. The value will behave exactly the same when used in a boolean context with or without this behavior, and instead of throwing out information it just keeps it around to enable some useful idioms.
  • 0

#977 paul23

paul23

    GMC Member

  • Global Moderators
  • 3935 posts
  • Version:GM:Studio

Posted 25 January 2012 - 05:01 PM

I don't see how that's a problem, especially with dynamic typing. The value will behave exactly the same when used in a boolean context with or without this behavior, and instead of throwing out information it just keeps it around to enable some useful idioms.

I've never been a fan of dynamic typing. Weak typing is nice, however when a variable changes it's type of their life I frown upon that heavily. Just a trivial example of a "bug":
var i, s;
i = 10;
s = random(1000) < 1 && "hello world";
s += i;
That's a 1 in 1000 chance the program will crash.
  • 0

#978 Dark Matter

Dark Matter

    RPG Expert

  • GMC Member
  • 3196 posts
  • Version:GM:Studio

Posted 25 January 2012 - 06:56 PM


I don't see how that's a problem, especially with dynamic typing. The value will behave exactly the same when used in a boolean context with or without this behavior, and instead of throwing out information it just keeps it around to enable some useful idioms.

Just a trivial example of a "bug":

Well then, you make sure your code is better written than that, don't you?
  • 0

#979 Rusky

Rusky

    GMC Member

  • GMC Member
  • 2492 posts

Posted 25 January 2012 - 11:37 PM

I've never been a fan of dynamic typing. Weak typing is nice, however when a variable changes it's type of their life I frown upon that heavily. Just a trivial example of a "bug":

var i, s;
i = 10;
s = random(1000) < 1 && "hello world";
s += i;
That's a 1 in 1000 chance the program will crash.

You can crash a program the same way with or without this feature, and this feature can exist with or without dynamic typing. It's a completely separate issue.
  • 0

#980 paul23

paul23

    GMC Member

  • Global Moderators
  • 3935 posts
  • Version:GM:Studio

Posted 26 January 2012 - 12:04 AM

I've never been a fan of dynamic typing. Weak typing is nice, however when a variable changes it's type of their life I frown upon that heavily. Just a trivial example of a "bug":

var i, s;
i = 10;
s = random(1000) < 1 && "hello world";
s += i;
That's a 1 in 1000 chance the program will crash.

You can crash a program the same way with or without this feature, and this feature can exist with or without dynamic typing. It's a completely separate issue.

Well the problem is how the error may be reported.

With such a feature, the crash occurs at the "s += i" - line 4. Yet the actual bug is in the s = random(1000) < 1 && "hello world"; - line 3. Here the lines are directly below each other, but with these features you'll always have subtle cases where things may crash, making it much more difficult to track the bug down to the correct line.
When to operands of the && operator are forced to be "convertable to boolean", the above example would crash at line 3.


Well sure it's not deal breaking, but I'm not really seeing any advantage of such syntax? Especially if a ternary operator is added I don't see any use to this - well only thing would be if the left side operator is an expression with a side effect...
  • 0

#981 Rusky

Rusky

    GMC Member

  • GMC Member
  • 2492 posts

Posted 26 January 2012 - 12:59 AM

Your "bug" and its "problems" with error reporting are 100% independent of both short-circuit evaluation and value propagation:
var i, s;
if (random(1000) < 1) s = true
else s = "hello world"
s += i
There are plenty of much more realistic situations where the cause of the bug is not on the reported line; just because you can write a sample with that problem that just happens to use a feature doesn't mean the feature is in any way to blame. In fact, you can't even really blame it fully on dynamic typing, as the same thing can happen in statically typed languages.

On the other hand, I have already given several examples where value propagation is more concise:
foo = argument0 || default_value // default values when an argument is null
bar = do_something() || handle_error() // also when some operation fails
if (baz != 0 && some_condition(qux / baz)) // checking before performing an operation that can error
There are more that may or may not apply depending on other changes, such as checking if an array index exists before using it, etc.

Edited by Rusky, 26 January 2012 - 01:01 AM.

  • 0

#982 Gamer3D

Gamer3D

    Human* me = this;

  • GMC Member
  • 1819 posts
  • Version:GM:Studio

Posted 26 January 2012 - 06:48 AM

It would also be nice if ds_lists were implemented as doubly linked lists internally instead of normal arrays (i.e. vectors). Index-based functionality would still be supported, for the new programmers, but it could also support iterators which are much more efficient.

I created my own version of doubly-linked lists not too long ago, using constant-sized ds_lists to represent list nodes. They were much more efficient than ds_lists in everything except adding to the end, which I eventually realized is because if GM's arrays are vectors, they double in size whenever they reach the end, whereas my methods require new allocation for each new node. Still, everything else was orders better, so...I think it should be implemented "correctly" (i.e. in a more standard, generally more efficient way).


Many people use lists as pointers to arrays (random access). Perhaps it would be better to change the implementation, but to add a set of ds_vector functions (or a class, if classes are added).

Some of the current data structures should have their current implementation overhauled. For example, I have written GML that replicates the ENTIRE set of ds_priority functions, and runs 10x faster on average than the built-in functions (~31000 elements). The DLL averages 120x faster on the same data set (includes the time required to determine whether input/output is string or real) (Mine: log n) (Built-in: n). If used properly, the DLL is faster than built-in for 32 or more elements.

GM seems to use the most naive method for managing priority queues (An unordered list, with finding/deleting max/min handled using a picking algorithm)
A better solution would be to use a min heap (or max heap, if people check the max more often than the min). The finding of the other one (min or max) can still be done using picking algorithms, but problems arise when changing or deleting random elements.
Best solution: Min-max heap. This is what I did. O(1) for finding min/max, O(log n) for adding/deleting. Care must be taken when editing/deleting a random element, but if its position is known, it can be done in O(log n)
  • 0

#983 Boreal

Boreal

    C++ Wackjob

  • GMC Member
  • 417 posts
  • Version:None

Posted 29 January 2012 - 06:39 AM

I don't know if this has been said yet or not, but we need the option to disable collisions/speed updates/automatic stuff for certain objects. Does a controller really need to be included in collision checks?
  • 0

#984 Big J

Big J

    GMC Member

  • GMC Member
  • 2852 posts
  • Version:GM8.1

Posted 29 January 2012 - 07:02 AM

The overhead for updating all the variables of 1 object is probably negligible compared to everything else that the engine has to do. Aren't controller objects usually made without a sprite? In that case, they would probably be excluded from collision checks. However, since I actually don't know, this post cannot be taken at face value because it is merely speculation. :P

Edited by Big J, 29 January 2012 - 07:03 AM.

  • 0

#985 falconfetus8

falconfetus8

    GMC Member

  • GMC Member
  • 38 posts
  • Version:Unknown

Posted 05 February 2012 - 04:09 PM

For the debugger, we already have the ability to exceute code one step at a time. However, this is useless when trying to solve many bugs. What we need is the ability to execute code one LINE at a time. This will make solving bugs dramatically easier, and cut down much of the trial and error involved.
  • 0

#986 Rusky

Rusky

    GMC Member

  • GMC Member
  • 2492 posts

Posted 05 February 2012 - 04:37 PM

That's already planned, and available in GM:HTML5.

Edited by Rusky, 05 February 2012 - 04:37 PM.

  • 0

#987 falconfetus8

falconfetus8

    GMC Member

  • GMC Member
  • 38 posts
  • Version:Unknown

Posted 08 February 2012 - 10:58 PM

That's already planned, and available in GM:HTML5.

Sorry, but who exactly were you replying to?
  • 0

#988 iam1me

iam1me

    GMC Member

  • GMC Member
  • 380 posts
  • Version:GM8

Posted 12 February 2012 - 08:13 AM

I have a couple suggestions to improve the language: if_with & return_with. As the names suggest, these will allow you to do an if then statement or return a value from a function while setting the scope, temporarily, at the same time.

For example, say I have an Object1 instance that has a script which will return true/false depending upon some condition which must be checked real-time. Right now, in order to do a conditional based upon that value from outside the scope of Object1, I have to take a rather verbose approach:

var temp;
with(Object1) temp = script_name();

if(temp){....}

The need for useless intermediate values and verbose code can be done away with by combining the if & with statements into one:

if_with(Object1,script_name()) {...}

of course, if_with is not exhaustive and could be improved with a return_with statement. For instance, say I needed to do a conditional using values from scripts using variables from different instances? I could make a bunch of temporary variables to store the values or I could have the much nicer return_with approach:

if(local_script() && return_with(instance1,another_script())) {...}


Still better yet, I would love to see a "->" operator, like in c++, which would essentially serve as a quick with statement. It would set the scope to the variable indicated on the left for the variable/script indicated on the right. Like so:

somevariable = someinstance->evaluate_script();

someinstance->do_function();

This would be an incredible improvement to the language for those of us who know how to program outside of GML.
  • 0

#989 Dark Matter

Dark Matter

    RPG Expert

  • GMC Member
  • 3196 posts
  • Version:GM:Studio

Posted 12 February 2012 - 06:08 PM

This would be an incredible improvement to the language for those of us who know how to program outside of GML.

Alternatively, just add an additional argument to any scripts that require taking in local variables...
  • 0

#990 iam1me

iam1me

    GMC Member

  • GMC Member
  • 380 posts
  • Version:GM8

Posted 12 February 2012 - 06:13 PM


This would be an incredible improvement to the language for those of us who know how to program outside of GML.

Alternatively, just add an additional argument to any scripts that require taking in local variables...


I've thought of this of course, and that is how GML does things for lots of its built in functions. But when scripts are written which are meant to be run entirely in the scope of a particular instance, it would be preferable to have a '->' operator. It seems much more natural, personally. This would also prevent the unnecessary problem of having to pass along the instance id as a parameter when the scope is already set correctly.
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users