I'll pay $300, maybe more, for Construct 3

Discussion and feedback on Construct 2

Post » Wed Dec 16, 2015 1:56 pm

newt wrote:family(index).x
Mind blown.


+1 + 1 +1... :!: :!:
B
13
S
4
Posts: 280
Reputation: 1,573

Post » Wed Dec 16, 2015 2:02 pm

That already works.
Image ImageImage
B
166
S
49
G
154
Posts: 8,102
Reputation: 100,225

Post » Wed Dec 16, 2015 2:03 pm

newt wrote:That already works.

With an Object, but not a Family. And not with UID.
B
13
S
4
Posts: 280
Reputation: 1,573

Post » Wed Dec 16, 2015 2:08 pm

Yes, () is for the instance index, or iid, including families.
[] would be for uid, if it was implemented.
Image ImageImage
B
166
S
49
G
154
Posts: 8,102
Reputation: 100,225

Post » Wed Dec 16, 2015 2:22 pm

newt wrote:Yes, () is for the instance index, or iid, including families.
[] would be for uid, if it was implemented.

Hmmm, I wasn't able to make this work with Family(IID), Only Object(IID). It's supposed to work?
B
13
S
4
Posts: 280
Reputation: 1,573

Post » Wed Dec 16, 2015 2:29 pm

It's the same as it would be for an instance.
Family(1).x would allow you to reference the x in the "second" instance in the family, Family.

I think to use the iid expression you have to use family(family.iid).x
Which is almost pointless since in order to get anything useful it already has to be picked.
It would work nice for a function parameter though.
Image ImageImage
B
166
S
49
G
154
Posts: 8,102
Reputation: 100,225

Post » Wed Dec 16, 2015 4:01 pm

Ashley wrote:Yeah, that worked out pretty badly for multiplayer. If the vote counts had been representative, most users would be using multiplayer. From what I can tell, it's just a small minority. So I think that shows that large numbers of users - even a majority of those participating in the vote - will vote up features that sound cool even without actually ever using it.
I don't have sales or engagement data for Scirra, but having multiplayer does "check a box", and therefore I'd expect people to be more satisfied with the product once they see it is multiplayer-capable.
I used to be frustrated with multiplayer via websockets (which was the old way of doing it), and was a big supporter (formatting is broken in that thread) of it when it was in development.

Overall I was pretty happy with the end result, and I'd guess that scirra was losing sales because of lack of multiplayer support before, but again I don't have any data to support that claim. Still I'm not sure I'd say multiplayer was a disaster even if people end up rarely using it.

Ashley wrote:... the top requests will probably be "make Construct 3D" (probably with people saying things like "it's only one extra dimension, how hard can it be?!?!")

I say we are definitely lacking at least some support for 3D. I mean at least some textured primitives should be supported, right? I'd love to be able to do something like this in-game.

Ashley wrote:Then if that's the highest voted feature and we quite reasonably decide not to act on it, now it's fodder for the trolls: "look, Scirra ignore their users, they don't care what we think".

I can think of a few ways of doing it, but one way would be to return to the forum pools, where you suggest "what's next for construct" and people pick what they want most, this way you are still in control and people still get to vote.

I don't mind that we don't have the page, since you're pretty active in the forums especially with regards to replying to posts when you're called - that's more than enough for me - but I remember that voting and discussing the proposed ideas was a lot of fun.

Ashley wrote:
Fimbul wrote:Call the expression players[0].character.turret.fireRate directly

It's a nice idea and it does look useful. But if you think it through it becomes a lot more complicated with further-reaching implications than you appear to have considered. This makes it far from a straightforward suggestion.


I get that there are edge cases that are hard to work around, but other parts of construct have similar things anyways. There are plugins that throw warnings in the debugger when you do something unexpected, for instance. Overall this stems from the idea that user code should never generate errors, which IMHO is naïve, but I get the rationale of catering to beginners - in the end it's as if we ran code with error warning turned off and an exception catcher that does nothing. I mean, even excel has #N/A and Err:000 placeholders, but that's outside the scope.

Imagine the following is already implemented in Construct:
  1. Arrays and dictionaries can be referenced directly in the expression editor via the syntax Array[0] and Dictionary["index"] - This isn't hard to imagine and is probably overdue anyways
  2. Objects can have arrays and dictionaries as properties - again, as requested above
  3. There is an expression returnValueByUID(objectUID,property) that, given an object's UID and a property, returns the value stored in that property for the object with that UID
  4. Other similar expressions exist: returnStringByUID(objectUID,property), returnArrayByUID(objectUID,property) and returnDictionaryByUID(objectUID,property)
The expressions listed in 3 and 4 can already be implemented via the SDK. That way, my players[0].character.turret.fireRate expression would become:
returnValueByUID(returnValueByUID(returnValueByUID(players[0],"character"),"turret"),"fireRate"). Again, this can already be acheived by the SDK, but the resulting expression is messy. It's still better than nothing, though.

Ashley wrote:- fail the expression evaluation, cancel the action/condition, cancel the event, and log some kind of diagnostic error somewhere. However this can leave events in a half-run state which can leave the game in an unexpected state. This is also different to how the vast majority of events work: you never need to look up diagnostics to see why something isn't working.

This is already what happens if you do it the current way, by picking objects sequentially using the "object UID exists" and "pick by unique ID" conditions. If the UID doesn't exist, your event sheet is left in an unexpected state. If you're a power user, you should be aware of the possible states. This is not a beginner feature.
Ashley wrote:return a dummy value like 0. Even this is surprisingly complicated.

I know you thought about those things and are perfectly aware of the problems with such a solution: what if 0 is the correct value? How do you distinguish a valid-returned zero from an error-returned zero? Again, an excel-like #NA or #ERR:XXX, or even a debugger warning (like already happens in some cases) would mitigate the issue, but how exactly it should be implemented is up to you. Again, all I want is a reduction in code bloat, which is generated too quickly by the current workflow.

Ashley wrote:There's also the problem of validating expressions. Right now a strong point of the event system is it is near enough impossible to enter invalid events. However if you type in "players[0].character.", what should autocomplete show and what should the expression validator consider valid tokens to follow it?

Which is why I suggested that there should be a "pointer" property type, so that it could "point" to a specific type of object (this is the same as saying "static typing", which I personally don't like, but whatever, better than not having it). If we could "point" to objects, then we could "point" to arrays/dictionaries, and this solves that other issue of having arrays/dictionaries as object properties.
With pointers, the expression editor knows what to expect, and can keep working fine. It also allows more flexible families and object grouping, so the entire family feature can be simplified.
Ashley wrote: At edit-time, the editor does not necessarily know what type of object the reference could be pointing to. So should it just dump a list of every behavior and instance variable name in the entire project after it? Is that useful to the user? What if you pick a behavior that does exist in the project, but at runtime the object instance you get does not have that particular behavior?

Make the "pointer" static-typed: you have to specify what type of object the pointer can point to. Issue solved. I mean, you already have to specify that a property should hold an integer/string/bool, why not a pointer to a specific object?
Ashley wrote: Perhaps a similar feature that picks by UID and *ignores picking* (so you can always get any instance) would be better, e.g.:

Sprite[1].X

would pick the Sprite instance with UID 1 and then get its X position. This is a lot easier to implement and avoids many difficult cases above, but still has some gotchas.
Going by your proposed syntax, your example would become turret[character[players[0]].turret].fireRate. Same situation as above. I mean, sure, I'd rather have that than nothing :lol: but I still prefer players[0].character.turret.fireRate
B
36
S
8
G
8
Posts: 532
Reputation: 6,903

Post » Wed Dec 16, 2015 4:32 pm

Fimbul wrote:
Ashley wrote:- fail the expression evaluation, cancel the action/condition, cancel the event, and log some kind of diagnostic error somewhere. However this can leave events in a half-run state which can leave the game in an unexpected state. This is also different to how the vast majority of events work: you never need to look up diagnostics to see why something isn't working.

This is already what happens if you do it the current way, by picking objects sequentially using the "object UID exists" and "pick by unique ID" conditions.

I don't think it's the same: it's obvious looking at a condition that it might not run if the condition is not met. It's a lot less obvious that an event could bail out half-way through evaluation of an expression, which is more of a "gotcha" type surprise. It's also easy to add an "else" to the "pick by UID" condition to handle the error case.

Make the "pointer" static-typed: you have to specify what type of object the pointer can point to. Issue solved.

It's not quite that simple. People often want to refactor projects later on, and as soon as there is a single expression reference depending on some aspect of the pointed-to type, it now can't easily be changed to anything else. It's the same reason you can't take a number instance variable and change it to be a string when there are already events referencing it. Once you have "object.pointer.turret.fireRate", the "pointer" variable of "object" can no longer be changed to anything apart from other objects with a "turret" behavior, otherwise the expression would become invalid. Various extra tools can help with this, but it could end up a bit of a straitjacket for event refactoring, and the extra tools to help replace things become very complicated in order to ensure the integrity of the project is maintained regardless of which changes are made. For example it's not enough that "otherobject.turret" is a valid expression, since "turret" could be the name of an instance variable, so even though the "turret" name exists on "otherobject" the expression "otherobject.turret.fireRate" is a syntax error.

I'm not saying it's a bad idea - it's probably actually quite a good idea. My main point is it's easy to throw out a suggestion like "let me type object.variable.turret.fireRate", but if you follow all the implications of that, it also ends up with non-obvious complicated consequences like writing special refactoring tools which can inspect the existing set of expression references to a pointer-variable across a project and only let you choose compatible choices when swapping the type of pointer, which maintains the validity of events but is itself restricting of the flexibility in the ability to easily refactor a project. That kind of thing turns otherwise simple suggestions in to a major project which will consume considerable development time and probably have a range of nasty bugs involved (I dread to think of the cases that come up when you start to copy-paste pointer-variable references to a different project). UIDs on the other hand are pretty straightforward, and although they may not be as concise, they work nicely within the existing event system. So I think it's worth trying to think of alternative suggestions still based around UIDs, so we can try and get basically the same usability result, but without having such major consequences.

That's also a microcosm of all feature suggestions in general. This is another factor in having users vote on suggestions: it's easy to vote up cool and easy sounding suggestions, but few users appreciate the true scope of the consequences for the code base, development time, future maintainability etc. If I sound like I'm fighting back, I'm only trying to find the path of least resistance to get the end result you want, which can sometimes look quite different to the original suggestion.
Scirra Founder
B
383
S
224
G
86
Posts: 24,109
Reputation: 190,416

Post » Wed Dec 16, 2015 4:47 pm

Ashley wrote:Various extra tools can help with this, but it could end up a bit of a straitjacket for event refactoring, and the extra tools to help replace things become very complicated in order to ensure the integrity of the project is maintained regardless of which changes are made. For example it's not enough that "otherobject.turret" is a valid expression, since "turret" could be the name of an instance variable, so even though the "turret" name exists on "otherobject" the expression "otherobject.turret.fireRate" is a syntax error.

I sometimes "refactor" construct projects by editing the XML, which is probably why it hadn't occurred to me. Yeah I admit that that can be a problem.

Ashley wrote:I'm not saying it's a bad idea - it's probably actually quite a good idea. (...) That kind of thing turns otherwise simple suggestions in to a major project which will consume considerable development time and probably have a range of nasty bugs involved (...) UIDs on the other hand are pretty straightforward, and although they may not be as concise, they work nicely within the existing event system. So I think it's worth trying to think of alternative suggestions still based around UIDs, so we can try and get basically the same usability result, but without having such major consequences.


Well if you can come up with something simple, I'd rather work with a beta/experimental feature full of gotchas than having to code bloat into a game... I'd love to adapt your Sprite[1].X idea in order to be able to type turret[character[players[0]].turret].fireRate in the expression editor and deal with bugs on my own, and that seems quite a simple solution to code, even if it's not as clean as my example.

Ashley wrote:That's also a microcosm of all feature suggestions in general. This is another factor in having users vote on suggestions: it's easy to vote up cool and easy sounding suggestions, but few users appreciate the true scope of the consequences for the code base, development time, future maintainability etc. If I sound like I'm fighting back, I'm only trying to find the path of least resistance to get the end result you want, which can sometimes look quite different to the original suggestion.


I understand. I don't want my ideas to pass unchallenged either, I mean if they have flaws, they should be exposed as fast as possible, and if they're too unworkable they should be discarded with the least amount of time wasted.

I agree with you on many things (like the dreaded native exporters), and my suggestions aren't necessarily the best solutions either... I could just describe my difficulties, but I like always having a proposed solution to a problem. As long as the "disease" is treated (in this case code bloat and repetition), I'm happy, even if my "treatments" are all discarded.

Besides that, the only complaint I have is that we don't have enough news about construct 3 ;)
B
36
S
8
G
8
Posts: 532
Reputation: 6,903

Post » Wed Dec 16, 2015 4:57 pm

I wonder what the outcome of a poll to drop the dom, and canvas would be.
Image ImageImage
B
166
S
49
G
154
Posts: 8,102
Reputation: 100,225

PreviousNext

Return to Construct 2 General

Who is online

Users browsing this forum: Yahoo [Bot] and 6 guests