[SUGGESTION] Classes as Object-Oriented Data/Storage

0 favourites
  • 5 posts
From the Asset Store
Data+ is the best Data Management solution for Construct 3. It contains 4 Addons (Plugin & Behavior).
  • Warning: There's a bit of a long read ahead. But try and get through it, I put a ton of thought into this and I think it's worth your time

    Construct 2 plays a very difficult game - a great balancing act of making an engine simple enough for non-programmers to use while maintaining the

    flexibility and complexity required by advanced developers. And it does this brilliantly - mostly.

    One feature, which is commonplace in just about every high level OOP language, seems to be neglected and forgotten about, even though it is

    crucial to almost every modern day application.

    I am talking, of course, about Classes. You know, those customizable objects with their own properties and variables.

    "So you mean Sprites?" I can hear you asking.

    Well, sort of.

    While Sprites do have the ability to store information in themselves through Instance Variables, I feel that they are severly limited. First of all, using a

    Sprite to store data just seems strange. I mean, sure, I can spawn new ones off the layout with their own variable values, but that seems way too

    much like a workaround rather than a feature. And I'm fairly certain that the process of creating a sprite, albeit offscreen, is far more resource

    intensive than manipulating much simpler data.

    Second of all, there are only three (3!!!) data types available for instance variables - Number, Boolean, and Text. While this may work for simple

    things, it is borderline unusable for more complex problems.

    Let's take an example:

    Let's say I'm making a pizzeria simulation game. A customer calls and places an order, and I need to fill out the order properly, through mini games

    and memorization. Stuff like remembering toppings, customer details, slice cutting, seasoning, and the works. Sounds simple, right? But let's look at

    the classes and properites needed:

    Customer - First Name(text), Last Name(text), Phone Number(number), Address(text), Slices Ordered(???)[/code:23trtued]
    
    If I were to use a conventional programming language, this would be very simple. I would simply create a Slice class that looks like this:
    
    [code:23trtued]Slice - Toppings(text array)[/code:23trtued]
    
    And then make the Slices Ordered property be an array of Slice objects.
    
    [code:23trtued]Customer - First Name(text), Last Name(text), Phone Number(number), Address(text), Slices Ordered(Slice array)[/code:23trtued]
    
    While simple through conventional programming, [b]this is ridiculously difficult in Construct 2.[/b]
    
    Sprites cannot have arrays, dictionaries, or other Sprites (or even anything remotely object related) as an Instance Variable. So instead, I'd have to 
    resort to using confusing, sideways solutions like using 3D global arrays (for something so obviously non global!) as subsitutes and just parsing 
    through row, column, and depth for each property, value (which can be an array!), and customer respectivly. And parsing that is hell. And should be 
    entirely unnecessary.
    
    I hope you see my problem by now.
    
    [i]"So, what's your solution?"[/i] I can hear you asking.
    
    Well, it's definitely not going to be easy to implement, but I definitely think it's possible, and necessary. Please note that this is just how I envision 
    this, and is definitely not the only way to do this.
    
    So you double click the screen, and add a "Class" object. It's added to your object bar, but not shown on screen, like an array or dictionary. When 
    selected, it shows the "Object type properties", "Container", and an "Variables" bar (just to avoid confusion with Instance Variables. You'll see why in 
    a second). The only thing that is different here is that the Variables bar (which has an "Add/Edit" option, like we're used to) when clicked, and after 
    pressing the add button, the available types shown are: Number, Boolean, Text, Array, Dictionary, and [i]any other classes that you have created 
    on this layout[/i]. If the Array or Dictionary options are selected, the Initial Value field expands to contain all of an Array's or Dictionary's starting 
    Properties panel (in the case of an array - width, height, and depth), and in the case of a Class, all non-complex variables (number, text, boolean) 
    are shown, and then, in a recursive hierarchical fashion, each complex object shows its information until the lowest, only non-complex variable level is 
    reached. Just visualize it like nested dropdown lists, much like [url]http://orteil.dashnet.org/nested[/url].
    
    So you've created your class! Whoo! But be patient - it's not on the layout yet. You've just built the abstract of it. Let's jump to the event sheet and 
    get this thing in our game.
    
    Let's have a look at it's actions. Click "Add Action", and each Class object that you've created appears there, like any other object does. Each class 
    has the actions "Initialize", "Destroy", and "Set Variable" (there could definetly be more, these are just the essentials). "Initialize" opens up a menu 
    box identical to what is shown when setting the Class's default variable values, except at the top it has a "Tag" or "Name" option, much like audio 
    files. This is what will be used whenever you need to access this specific instance of the class. "Destroy" takes a name and destorys the instance 
    related to it. "Set Variable" allows you to set the value of one of the variables in this instance.
    
    So if I want to compare the value of "Name" inside of the instance "customer1" of the Class "Customer" with the string "Bob", I would access it by 
    typing something along the lines of
    
    [code:23trtued]Customer.getInstance("customer1").getValue("Name")[/code:23trtued]
    
    Or if I wanted to get his street number, which is stored in another class called "Address", I would access it by typing
    
    [code:23trtued]Customer.getInstance("customer1").getClass("Address").getValue("Street Number")[/code:23trtued]
    
    Or if I wanted to access an Array of something stored in the customer
    
    [code:23trtued]Customer.getInstance("customer1").getValue("SomeArray").At(1,1,1)[/code:23trtued]
    
    This may seem a bit too programmer-y, but again, this is just the way that I see things, and is completely up to anyone's interpretation.
    
    Condition-wise, there shouldn't be too much, just maybe a "Is Initialized" option or something along those lines.
    
    And that's basically it. So while this may be difficult to implement, it definitely is possible. Thanks for taking your time to read this, and if you have 
    any questions don't hesitate to respond here or shoot me a tweet @bowiz2. I tried to make this as understandable as possible, but I may have failed 
    miserably - so let me know!
    
    Have a great day!
  • Hey man. I have read the entire post. Don't have time for an in depth reply as I'm mobile. Have you done a search on "oop" as this has been raised quite a few times (including by me). You're right about c2 walking that fine line. I'm an oo guy from way back don't get me wrong. I think just having a simple "data" object (POD) would be great, to aggregate values and combine those objects into compound objects. Arrays of these would be great too. I think I'm agreeing with the spirit of your post, but keeping it simple. I don't think that would be difficult to implement, but who knows. I don't like the accessing of fields by string name though.

  • "Sprites cannot have arrays, dictionaries, or other Sprites (or even anything remotely object related) as an Instance Variable."

    See that part that says container?

    Also you're not limited to one instance of any data object, and you can reference them using the index array(0), array(1) etc.

  • Overall I agree: handling complex data structures and algorithms is difficult within the current event system, and the spirit of this suggestion is to resolve that. I'm not sure I agree with the specifics, but I agree that there is a weakness and that something along the lines of what is suggested would help. However such changes are deep and far-reaching and would require quite some rearchitecting. I don't think we could start addressing this within a C2 time-frame (more like C3, whenever that may be).

    I do however have some random points to add to what you've said which might help you realise the situation as it is right now is perhaps not quite so bad as you think:

    And I'm fairly certain that the process of creating a sprite, albeit offscreen, is far more resource intensive than manipulating much simpler data.

    Not really - sprites are actually very well optimised. If it has no animations, it sits on an invisible layer, and you don't make any collision checks, then IIRC it has no performance overhead from simply existing. This means it's actually a pretty reasonable idea to have some global sprites as a sort of namespaced global variable solution. So you can for example have some variables with names like "Stats.Accuracy", "Inventory.ItemCount", etc.

    [quote:1prxrse4]Sprites cannot have arrays, dictionaries, or other Sprites (or even anything remotely object related) as an Instance Variable.

    No, but an interesting feature of containers is that you can put an array or dictionary in a container with a sprite, and each instance of a sprite gets its own array/dictionary instance. The way picking works with containers also means once you pick one of those sprites with events, all actions/expressions to do with its contained arrays/dictionaries refer to its own objects only. You can add several arrays or dictionaries to a sprite in its container and have all sorts of per-instance advanced data structures for different purposes. While that's not using instance variables, it achieves the same end, and hopefully is a good workaround.

    [quote:1prxrse4]Customer.getInstance("customer1").getValue("Name")

    One of my concerns with expressions like this is performance. If "Customer.getInstance" returns an entire customer record with *all* their data, and then you discard it all and retrieve only the name, and then you do that a lot, then there's a lot of wasted effort going on. It's solvable with by-reference passing and so on, but it gets complicated if you want to start adding expressions that modify the result, such as slicing arrays and such.

    Other options could include:

    • involve this in a new modularity system somehow
    • better ways to integrate JS code (which is quite an extreme way to solve the problem I guess)
  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • It's coo, to chain the output of expressions. And I agree that put an algorithm on event sheet is (very) difficult, I usually put it into plugin/behavior.

    In my point of view, reuse-able (by plugins) is more important than easy to program in event sheet. Encapsulation is also a part of OOP, that's way I LOVE C2. Don't miss the event-plugin system in C3.

    Of course, chaining the output of expressions will be more better.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)