Show Posts

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.


Messages - Josh @ Dreamland

376
General ENIGMA / Re: Unicode Fonts
« on: April 12, 2014, 07:01:41 PM »
For the same reason we currently offer two overloads of string_length: one accepts const char*, the other accepts std::string. If all you have is const char*, then length is O(N), but does not necessarily entail a copy. If we only accept std::string, a copy becomes necessary, so now we're N in complexity and memory.

In order to have a utf8_string whose complexity is the same as std::string (which is completely possible), I must keep TWO strings. The first is a string of at most 4N characters, where N is the length in characters of the string; this translates to N bytes. The second string is of size_ts and denotes the byte of each character. So it'll usually look like ⟨0, 1, 2, 3, ...⟩ or ⟨0, 2, 4, 6, ...⟩ but will often be much uglier. Primarily where other languages use English (ASCII) punctuation.

For your interest, I'll write the class. But I am disclaiming liability for slowdown from you two constructing one or more strings in addition to the simple ASCII strings you are usually asked to operate on.

377
Announcements / Re: Heartbleed
« on: April 12, 2014, 06:50:08 PM »
I'm a software engineer. I'll be working under a division of Channel Intelligence called gTech; some info about those is available online. I'm not sure how much of the specifics I'm allowed to mention, because I work on a lot of gutsy things rather than a specific product. You'll probably never personally interact with anything I write, unless you start your own business and want to share information with Google. You still might not come into contact with my code, but you'll at least invoke it. :P

378
General ENIGMA / Re: Unicode Fonts
« on: April 12, 2014, 05:08:12 PM »
"Supports" is a strong word. UTF-8 is eight bits, so an std::string is all we need to store it. You still need special methods to get a character from a position.

I would offer to write a utf8 string implementation, but I'm afraid you two would start using it exclusively for everything.

379
Programming Help / Re: Find the Memory Leak
« on: April 12, 2014, 07:53:25 AM »
Narrow as small a test case as you can. That's always the rule. I can't just hope the leak occurs on my machine and trace out a likely cause throughout a whole game.

And no one cares about reachable blocks, cheesedip. Someone should probably fix the leak in the sprite loader, but that only runs once. You're better off finding an actual, repeated leak.

380
Announcements / Re: Heartbleed
« on: April 11, 2014, 10:02:36 PM »
I tend to simplify when (A) speaking to the public or (B) not giving a shit/not reading up. This happened to be a case of both.

So yeah, sucks about other sites, but we dodged this one (it seems).

381
General ENIGMA / Re: Unicode Fonts
« on: April 11, 2014, 09:18:54 PM »
Once again, let me forward the method I would use. Assuming there is an enigma::glyph class representing a font glyph:

Code: (C++) [Select]
/** Copyright 2014 Josh Ventura
***
*** This file is a part of the ENIGMA Development Environment.
***
*** ENIGMA is free software: you can redistribute it and/or modify it under the
*** terms of the GNU General Public License as published by the Free Software
*** Foundation, version 3 of the license or any later version.
***
*** This application and its source code is distributed AS-IS, WITHOUT ANY
*** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
*** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
*** details.
***
*** You should have received a copy of the GNU General Public License along
*** with this code. If not, see <http://www.gnu.org/licenses/>
**/


class glyph_set {
  struct glyph_range: private vector<glyph*> {
    size_t firstindex;
    using vector<glyph*>::operator[];
    void swap(vector<glyph*>& x, size_t first) {
      firstindex = first;
      vector<glyph*>::swap(x);
    }
    glyph_range(size_t first, size_t count): vector<glyph*>(count), firstindex(first) {}
    glyph_range(): firstindex(0) {}
  };
 
  typedef map<size_t, glyph_range> gmap;
  gmap glyphs;
 
  public:
  glyph *operator[](size_t x) {
    gmap::iterator it = glyphs.lower_bound(x);
    if (it == glyphs.end() or x < it->second.firstindex)
      return NULL;
    return it->second[x - it->second.firstindex];
  }

  void store_range(size_t first, vector<glyph*> &inglyphs) {
    size_t last = first + inglyphs.size() - 1;
   
    #ifdef DEBUG_MODE
    bool overlap = (*this)[last];
    if (overlap)
      show_error("Glyph ranges overlap", 0);
    #endif
   
    glyphs[last].swap(inglyphs, first);
   
    #ifdef DEBUG_MODE
    if (!overlap && inglyphs.size())
      show_error("Something wicked has happened to the glyph map", 0);
    #endif
  }
};

Make sure that compiles in debug mode, too. It should compile in release mode. I haven't tested it in ENIGMA, obviously, but I see no reason it wouldn't work. You populate a vector of glyphs, then use store_range to add that vector from a given glyph index. You can then look up the glyph in the map as you would in a normal map.

The bonus is that it allows you to have dense ranges of glyphs which are themselves distributed sparsely. So you can have, eg, ASCII, Cyrillic, and cat smilies.

382
Announcements / Heartbleed
« on: April 11, 2014, 06:23:25 PM »
tl;dr: we run CentOS 5; our software is so out-of-date, we are not affected by Heartbleed. Of course, you probably don't connect to us via SSL, anyway.

Heartbleed is an OpenSSL exploit that enables hackers to listen in on what should be secured connections. It's a terrible vulnerability that can lead to the leak of all sorts of sensitive information; in our case, passwords. Since most users connect over HTTP and are probably therefore not using a very secure password, this isn't an issue for most of our users. For those who do connect to us over HTTPS, you're safe, anyway, because the vulnerability is with a newer OpenSSL than we'll ever have. This has a number of downsides, but the upside is, we didn't even have to patch for this exploit. So your HTTPS passwords have been safe, and our SSH connections have been safe.

And to clarify, yes, I am still alive; I haven't lived for ten consecutive days in the same state for almost the last month, now, but I am finishing getting moved into my current apartment where I am now holding a job at Google. That said, afternoons and weekends are mine unless I break something.

383
Announcements / Re: Project Mario
« on: April 05, 2014, 10:32:53 AM »
Missed your post due to pagination mishaps, Harri.

Look at your examples. Everything that took you only X lines of code in GM/ENIGMA/whatever was a built-in feature of the two. Largely because of your code, I'll add and acknowledge, but that doesn't change the point. ENIGMA is conducive to audio manipulation and path plotting. It has bottled code for them with which you are intimately familiar as the author.

Your circuit example is the only thing there that doesn't relate to ENIGMA's central purpose, so of course it took you thousands of lines. It involves recursion and keeping track of what kinds of elements you are rendering. Look at the JDI code that renders ASTs as SVGs—a somewhat similar operation. It's a few hundred lines. Of C++. And its only dependency is the generic SVG elements code: another hundred lines. And that's with me rounding up to the next hundred and including the license. Without that, we're at 335 lines to render an AST to an SVG, all-inclusive. I'll grant that including the headers that lay out the structure of "what is an AST node" brings the line count up significantly, but we still don't reach a single thousand lines.

I wouldn't even attempt that in a classless language.

384
Announcements / Re: Project Mario
« on: April 05, 2014, 10:23:18 AM »
One of my talking points from a long time ago was a plan for the ability to specify additional parameters in objects that can be edited visually through the room editor. These would come in four basic types:
  • Point: A coordinate, (x), (x,y), or (x,y,z), visualized with a marker in the room editor.
  • Angle: A single angle scalar, visualized by a vector pointing away from the instance.
  • Instance: A single instance, which is selected from other instances in the editor, visualized with an arrow leading to that instance.
  • Resource: A resource integer, for any resource of a particular kind. Displayed and set in the status dialog on hover.
  • Number: A numeric literal given at the user's discretion. Displayed in the status dialog on hover.
    • Selection: An integer chosen from options in a combo-box. Presented in status dialog.
  • String: A string literal. Displayed and set in the status dialog or visually on hover.

This allows you to set a number of options in the room editor that you'd otherwise typically do through the instance creation code, in an ugly fashion. The combination of which of those settings you want would be read from some markup file read from each object, which would be used to populate default values and combobox entries. My choice of format would be either YAML or JSON (if contention was high for whatever reason, we could dynamically convert between these at the user's preference).

An example of each category:
  • Point: A start and end coordinate for elevators, enemy AIs, etc, etc. Perhaps a "path of zero or more points" option would be in order.
  • Angle: A firing angle for turrets or other static AI.
  • Instance: A target character or destination teleporter. This is more useful than a point where the target point is on an instance that the developer may move.
  • Resource: A path to follow. A sprite to use. An object to fire as ammunition. A timeline to start. I mean, really, the list goes on and on.
  • Number: Speed? Difficulty level? Max mana? Exp points? Amount of gold in the chest? Yes.
    • Selection: What kind of enemy is this? What does this entity do when you approach? What... canned effect does it display upon explosion? :P
  • String: Sign text. Finally, you can set sign text without hassle.

The beauty is that the majority of these can be given a toggleable visual representation in the room editor, which could be configured as needed from the markup. Such as a green arrow or a really transparent arrow or whatever. Coupled with my other proposal for an overworld resource, you could lay out all of Super Mario Land trivially. And Metroid II would be simple, too. Their major downfall in simplicity is that an artist actually painstakingly laid out all those tiles by hand, back in the day.

Couple that with the improved build mode and the compile time reflection we've discussed exhaustively, and you can edit your level live with automatic tile generation. The setup time obviously continues to grow for this shit, but the beauty is that you no longer have this effort barrier that makes you not want to work on other levels.

385
Issues Help Desk / Re: Compile Errors on WinXP
« on: April 04, 2014, 08:32:17 PM »
Wow, that's a new one. Normally my response would be "Blame Sun Microsystems," but due to circumstances beyond our control, that isn't presently an option. I'm going to blame Oracle instead. In all seriousness, I'm thinking this is a JNA problem. Could you make sure you have the latest JNA binaries? We may need to create a test program so users can make sure their JNA can perform simple tasks.

386
Announcements / Re: Project Mario
« on: April 04, 2014, 07:49:20 PM »
Build mode, as in the context of the original ENIGMA build mode?

Behavior components are simple enough to add. But be careful how you refer to them. In EDL, we're dealing with two types of objects. The more obvious type is the "Objects" we inherit from GML, which all inherit from a base object that has eleventy godzillion locals, and is entirely event-driven.

For these, I was originally going to do so through multiple inheritance, but since everyone seems to like that ridiculous event_inherited() nonsense, doing so isn't straightforward. We can't really maintain a complete dichotomy between behaviors and object inheritance, because if two behaviors require an object to have mana, we want them to be able to pool mana, while if two behaviors require ammo, we want them to safely utilize separate ammo. If these behaviors were separate, an object would still need to have multiple parents in order to inherit these shared fields from multiple parents, anyway.

This does, of course, assume you would want to use behaviors for available weapons, which is fine by me as I am a fan of the concept of interfaces. It makes sense to do this, anyway, as you will want with (obj_some_type) to affect all objects inheriting behavior from obj_some_type, which makes much more sense of they're actually objects.


The second kind of object we work with is exclusive to EDL, and in fact, exclusive to the flavor of EDL for which I wrote the first half of a parser before my final year of college picked up. The new parser supports structures, which will support functions (I hadn't finished ENIGMA's function syntax before I got involved in the whole "Graduating" thing). These will support inheritance and virtual functions. While I had not considered it, ENIGMA already supports using C++ classes as Object components: It's how extensions currently work. It wouldn't be hard to allow doing the same with ENIGMA structures, if there'd be any point to it. For instance, if one of these were intimate with obj_mage, or whatever, it could be used as a magic weapon interface, and its children could be stored in an array of current weapons or assigned to different attack buttons. This would allow the child Object to have more control over how its behaviors are used, as well (the object has a weapon and assigns it to 'X' instead of inheriting a weapon that is fired with 'X'). As usual, it comes down to the "has a" vs "is a" problem, so offering both options would certainly help with that.


Now that I'm done ranting on that for the umpteenth time, I fail to see how that is a "high level" design concept, except by virtue of being higher than C. GM already has some high-level functionality. If you want a dumb-ass, dumpy, "high-level" approach to shit, use my_object.behaviors += script_get_text(scr_my_behavior);; then in the step event, execute_string(behaviors);. Done.

387
Announcements / Re: Project Mario
« on: April 04, 2014, 05:05:06 PM »
I find Unity has too much emphasis on certain game features, too; the most obvious being that everything's 3D. In a game design class I took as an elective, other teams used Unity (my team was the only one that did not). We were the only team with a 2D menu, not because we did less work, but because making a 2D menu in Unity was more work for the other teams. Multiple groups mentioned this specifically. They might have just been dumb—one of those teams was trying to draw a targeting reticle as a 3D sprite and doing (lots of poor-quality) math to figure out how to make it appear the right size on screen.

But anyway, if you have a specific example that doesn't over-constrain the sort of games ENIGMA can make, I'm interested in hearing it.

388
Announcements / Re: Project Mario
« on: April 04, 2014, 04:19:34 PM »
The things you are suggesting should be high-level would remove the "programming a game" aspect of programming a game. We could go the stencyl route and include be_a_green_koopa(), be_a_red_koopa(), be_a_block(), be_mario(), be_link(), and fly_around_in_circles(), and then, of course, include a UI to pick which of those you want to call as tiles. But I have this crawling feeling you'd quickly notice a shift in the sorts of games made in ENIGMA. Yes, they'd all behave well; yes, it'd be easy to develop games; and yes, we could easily predict all behavior for purposes of, eg, rewinding time. But somehow, I think interest in the project as a development platform would actually dwindle.

389
Developing ENIGMA / Re: Changes in the new compiler
« on: April 04, 2014, 04:13:05 PM »
I was hoping to use GitHub to generate a basic zip file for release building. I want to eventually automate package generation on this server or another. I can, of course, have git check out all that stuff locally, then zip it manually, but then I have to delete the .git directories. Please tell me there's only one of those.

390
Announcements / Re: Project Mario
« on: April 04, 2014, 04:07:04 PM »
Data structures are important, but Game Maker does offer a C-Like interface to them. Yes, it uglies up the code, but what HaRRi is arguing is that it isn't a limitation in the strictest sense.

I consider the missing structures to be GML's greatest downfall. With those, a user could work around GM's other major flaws, including my personal pet peeves:
1) The inability to name script parameters. This encourages documentation in the ugliest way possible, but otherwise damages code readability.
2) The unavailability of virtual methods in classes. Game Maker offers user events, but these also cannot be named, and there is a strict limit of 16. Emphasis: limit.
3) The lack of proper encapsulation. This only really aggravates me when creating a data structure gives you a sequential integer that must be freed when you are done. We can't do anything to make your life easier; we have all the same problems as C for new users. Close your files, or you'll run out of file handles. Delete your data structures, or you'll run out of memory. If we had data structures as objects, they'd be freed when they left scope.
4) The lack of a well-defined passing convention. Want to pass an array? Create a list structure, pass the ID. See problem list in (3).
5) The inability to hold non-integer objects, thereby constraining the number of object types you can offer–creating them is a pain in the ass.

If you don't miss structs, Harri, then my guess is that A* is the most complicated algorithm you've ever written in GML. Because if you had to store more than three values for any given node or grid cell, you'd quickly go insane. Three values in a grid requires three grids. N values in a grid requires N grids. Each value requires a call to ds_grid_*, which is bulky and ugly. Enter map. Now it's also slow.

If we wanted an iterator for them, we could have ds_map_iterator_*, so that you could construct iterators and work with them by integer. But now we need an array of iterators. What a joke. This puts burden on developers, so it doesn't happen, which puts burden on users, because now their code is slow because it's doing N log M operations for N variables in M objects. This is on top of the already obnoxious overhead for accessing a variable.

This also further exacerbates problem (3). Your iterators wouldn't have an owner, and so you'd need to explicitly denote you are finished with an iterator so the system can destruct it. Now your code is illegibly hideous; ISO C++ is officially prettier than your "high-level" GML.


The rate at which your code blows up is a good metric for whether there are limitations. A rope ladder leading to the moon does not, in itself, remove a limitation. Yes, you could climb to the moon, but the resources required would be insurmountable. Yes, you COULD write a compiler in GML. But I'd advise you to instead do something more fun and productive, like cutting off your limbs in one-inch increments. Even if you managed, it'd run like shit. Even if you compiled it with ENIGMA. Why? Because your code is bad. Even if you can't see it. Being low-level in nature (ie, being a pain in the ass to use), does not imply you will have faster code. Allocating and freeing iterators yourself through those functions would make the code slower, anyway, because now we need to dereference more than just the current frame to figure out where your iterator is to dereference it and figure out where your data is.


And that concludes my rant, for now.