GDR Forum Index
Podcast Podcast
Dev Dev Logs
Search Search
RSS RSS
Register Register
Log in Log in
Reply to topic GDR Forum Index -> Game Developer's Refuge -> Development Log - Glue Gun Glen Page Previous  1, 2, 3, 4, 5, 6  Next
View previous topic :: View next topic  
Author Message
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Wed Sep 13, 2017 7:07 am    Post subject: Reply with quote

So, I figured out why my level editor hadn't been exporting data quite how I expected lately - I thought the carts were just being exported without a property attribute, but well...

Code:
        blocks: this.blocks.filter(function(o) {
            return o instanceof Crate || o instanceof ColoredBlock || o instanceof Gem || o instanceof Icecube); // oh, you're a Cart, huh?  guess i won't be saving your data, ha ha ha!
        }).map(function(o) {
            return o.export();
        }),


...they simply weren't being exported at all. I don't remember exactly why I coded the export like this initially...was my plan to have 20 different OR options in there, one for every object? Meh. I do keep the player objects in a separate list, although that's completely unnecessary - pretty sure I only did that because I was editing the levels by hand originally, and it made it easier to isolate them from crates/gems/etc. if I wanted to move one of them around.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Wed Sep 13, 2017 8:03 pm    Post subject: Reply with quote

I feel a little bit dirty, which is a thing that can happen when you start mucking about with ui coding. In this case I was working on adding ui to the level editor for laser movement behaviors - I knew what I wanted, and also knew it was gonna be ... a process. Or ten, I don't know. Check out a little video strollthrough of how i tlooks - it's pretty slick.



It's actually pretty decent code, I shouldn't feel too dirty, but I did end up duplicating the logic for laser movement. See... I wanted each behavior (e.g. laser move left, laser rotate, etc.) to display a calculation in the ui that indicates how far the laser's endpoints have moved from the spawn location. So, if you create a laser and tell it "move 2 squares left, then up 1, then 2 squares right and 1 square down" then the laser's movement loop starts and ends in the same spot. So, you can let it run forever, no problem. But - what if you defined the same laser, then added an extra movement to the right? Every loop, the laser would move farther and farther to the right, until it ran off the screen. Thus, the ui calculations should confirm that after the last behavior is applied, the delta of each endpoint is [0, 0].

Anyway, the hack is that I did the math all over again in the ui calculation logic - not that there's more than 4 lines per behavior, so it's like 25 lines of redundant code. If I found a reason to modify the laser code then it'd suck to have to change (and remember to change!) them both I guess, but... is it really that likely that start.x += dx; start.y += dy; is going to need maintenance? I'm not very sure about that.

Level export fix, check. Laser ui... partial check - still have to actually serialize it on save, but that part's pretty easy. Oh yeah, and check close in the video, I even have wheel events on the dropdowns to save myself some clicking, and also it highlights any modified values - this way if I accidentally change one, it'll be pretty damned obvious. Finally I also added a proper mask layer to the game, so that I can have rail support beams sink right into the lava. So, a lot of my grunt work tasks are now in the hopper, which is great. I'm sure I can find bunches more just like them.. which is also... great. In its own way. Look no farther than the lasers, though... the ui is nice, but I might want some way of previewing the current loop, or stepping from frame to frame so I can eyeball where it goes on the level, make sure it lines up with my vision. Stuff like that. Just need to start listing them out.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Thu Sep 14, 2017 2:16 pm    Post subject: Reply with quote

It's official: gluegunglen.com Game is obviously not even close to done, but I had a domain to renew for snakes without brakes and decided I'd keep them renewing at same time of year.

This game is like a piņata - it's full of fun and cool things, and I am always trying to break it. Today, after doing some more grunt tasks like setting up 4-directional mine cart rail tiles (i'll need these eventually), 4 sides of lava, etc., I decided to make a move on building levels in components. This means that you can have a "level" that is comprised of 2 or more levels, and each of them will rotate separately. It's going to be like a piņata too, except without the ņa and the a, get it?

So far I'm just rigging together basic framework - the world object is ready to go, and I've rolled a few methods into it tthat do things to all of the levels, e.g. applyGravity - the easy stuff. Once I get very basic rendering in order, I'll start contemplating the much taller order - interdimensional travel. See you in a week...
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Thu Sep 14, 2017 9:24 pm    Post subject: Reply with quote

Anyone want to tell me why the one level doesn't render properly here? A bit perfuzzled, it renderred fine as a 5x8 level, but now that it's 6x8 it's unhappy.



Almost typed mockupgames.com, and then tried to do a /color tag on the image. I'd better not keep trying much longer - I'll just make it worse tonight. The current gotcha is that levels have to either have odd dimensions on both sides, or even dimensions on each side... so 5x5 good, 8x8 good, 5x8 bad - this is because levels always pivot about the center, and if the "width" of the level changes from even to odd, it staggers the collision calculations and generally makes things a major hassle. Currently plan to take the coward's way out and make it a hard rule for the game - if I didn't mention it, you would really never have any idea. This is why the bad-rendering level is 6x8 now, I just added an empty column to the left of the level. And in the process discovered the latest rendering bug.

I really want it to render right. It's gotta be something simple. I've got in code to generate collision map for the world object now, it's a composite of all levels - and it will respect rotation of levels, i.e. will rebuild collision map any time a level rotates. All objects are going to become members of the world object. Thus, with a single collision map and all objects part of the world, interdimension travel will be a lot more straightforward than I previously speculated. But, right now I haven't even re-enabled input checking for the game. Soon - the collision stuff is a good step forward - but, now this damned rendering thing.

Hmmmm, lasers. I might have to constrict them to always being in the same level - would be somewhere in the neighborhood of impossible to keep up with rotation of one end of the laser got into a level that needed to rotate, but not the other end. No, that's be no good at all. Mark it down, lasers will never travel between levels. Adding it to the notes now.

edit - ok it was because the entirely blank left column (just for padding here) meant the outline's minimum x was a full cell width, and the prerender's size was computed as width = maxX - minX, which unfortunately in this case was not enough width. for now will just force top and left to 0, which in most cases is what they would have been anyway
View user's profile Send private message Visit poster's website
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9441
Location: Not Finland
PostPosted: Fri Sep 15, 2017 4:59 am    Post subject: Reply with quote

See, this is the thing people just don't grok about game creation. There's a lot of dirty hacks just to get past a fundamental issue that would normally be resolved "correctly" if time weren't an issue. Commercial games are full of 'em. Modders are usually the ones digging them up... heh.

Then there's also the situation of the tired indie developer who just wants the problem to go away ;)
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
sonrisu
Moderator

Joined: 31 Aug 2005
Posts: 4988
Location: Silicon Valley!
PostPosted: Fri Sep 15, 2017 6:31 am    Post subject: Reply with quote

User doesn't care if the game "works" and remains fun, right? So keep the hacks coming. :]
_________________
loomsoft :]
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Fri Sep 15, 2017 6:09 pm    Post subject: Reply with quote

Hello, friends. Would you believe me if I said that shifting from a one level world to a multi level world has been a significant refactoring? I am not one to tell great lies. Some of it has been on the simpler side - taking Level.applyGravity and shifting it to World.applyGravity, a pretty mean feat. Other parts of it have been a little more complicated. For example, having the world itself render the objects is great - but how to solve the rendering problem when one of the levels is rotating, and all of the objects within that level should rotate with it? That's a longer story, for another tomorrow.

For today, take a look at the first concept level. This is still fresh off the grill, so things like the hard borders between levels? That's just line 829 on the todo list right now. But enough of the core logic is in working order, enough to generate this:



Last quick note, for the inquisitve - you might ask, if a player is on the corner of a level and rotates, he's going to clip through part of the other levels on the way. Is that intended? yes Will there ever be dynamic rotational clipping between levels? NO
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Sat Sep 16, 2017 6:28 am    Post subject: Reply with quote

I haec 1000 things to do still on this levels-as-components task alone, so instead of doing any of them I'm going to talk about them, and how I've gotten to this point. It's a more productive distraction technique than playing xbox, I'm sure.

One of the big changes was taking the objects out of the Level class and moving them into the World class. This made sense, because if the objects are going to move between levels, then they don't really belong to any one of them. (I had originally speculated that I might remove objects from one level and add them to the next, but can you imagine the ridiculous mess of code that'd be involved in checking "but is there a crate in the way on that level?" and the other hundred such scenarios - what a terrible "solution"). It is true though, that within the actual level files, the objects do retain an association with each level - so in the editor I will place a gem within a level at coords (1, 1), and then I will place that level at word coords (5, 0). Then when the "level" (world, sorry this might get confusing) is loaded, the world builds its lists of objects and positions that gem at level coords + local object coords, and it ends up at (6, 1) where it belongs. Or... does it?

Think about this - you create a level that's 4 wide, 8 tall. But then you rotated it, and it's 8x4. Because the levels rotate at their center, the rectangle that bounds the level at any possible rotation is now 8x8. This ties in with the new collision map approach, which was another major change. Previously, I never repositioned the objects within the world upon rotation - instead, once you rotated the level 90degrees, I simply changed gravity from (x=0, y=1) to (x=1, y=0) and pressing ArrowRight would change from (x+=1, y +=0) to (x+=0, y +=1). Completely impossible (I guess?) to retain this logic with levels as components, though. So, the first step was to build a collision map that (1) contained all levels in the world, and (2) included the necessary padding to fit each level even when it rotated, if necessary.

When a level of the world is rotated, the gems and crates and players that are currently within that level should rotate with it. But now that the objects are part of the world, how can this be done? I solved this by implementing an "object sharing" list - each level has a list of shared objects. When you hit shift key to spin a level, I check all objects and calculate which of them are within the level that's rotating. That subset of objects is then sent to the level-in-rotation as shared objects, which indicates to the game that the world should no longer control their rendering - instead the individual level is going to control that, for the duration of the rotation. When rotation is done, the world tells the level that it's done sharing, and then the world repositions the fixed coordinates of the objects in that level to align with the new rotation. So if the player was at top left corner of a level component and then it rotated to the right, then the world will teleport that player object to the upper right corner of the level when ti's done moving. After all of that, the world's collision layer is refreshed to reflect the changes from level rotation, and business continues as usual.

Certain elements will remain a part of the levels themselves. For example tile animations like lava, I will keep them in the levels - they never move. The lasers are another example, as I've stated they're not going to cross between levels because if the math is even possible to rotate one endpoint and not the other and avoid breaking the movement pattern circuit (I'm skeptical that it is!), even if an alien beamed down to earth and gave me the ancient sea scrolls with the equation to make it work, it'd surely be far more of a hassle than it'd ever be worth. I'd kindly tell him to take his parchment and go to hell.

It's not really fair to say that what I've completed so far is the "easy" part because it's definitely been a bit complicated for me, the situation though is that now that I've reached "milestone 1" for the levels as components concept, it's going to be back to grunt work - I can't rely on the drive to make the raw concept work, which was really a pretty great motivator. Now I'm faced with problems like these: if you glue a box to the wall, but that wall is on the level next door, and then you rotate either of the levels and now the crate is glued to "thin air" then what happens? Well, I already thought about that one and figured the crate obviously has to fall back down to the ground, and the glue assocation has to be removed because there's nothing to be glued to. It's logical, but unfortunately it's also going to be somewhat chorious. In other news, the level editor has absolutely no support for the levels as components, I'm pretty sure it would just throw a series of errors at the moment. (To build the test world I used an older build of the game/editor to build each level component one at a time, then pasted the export data into the levle's text file.) There will also come a day when I need to set up game camera logic to support the world concept, and that day just can't come fast enough I had so much fun doing that for just one level area (and it was still a touch buggy at last visit). Lasers and glue markings need to be repositioned like the objects after a level change, and for the lasers their movement history may need some adjustment too in order to keep the circuit on track. Then there's the job of removing the hard borders around levels in the areas which you can cross between. You know what, that might be all of it, or pretty close to it for now. One at a time, that's the only way to do it!
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Sat Sep 16, 2017 5:26 pm    Post subject: Reply with quote

Today brought a simple but very useful idea pertaining to the controls for switching between players. At one point pressing TAB brought up a quickselect id for every character, with an arrow pointing at them - and I'd like to bring that back (never ported it from DOM implementation), but for right now the TAB key is just cycling through them sequentially, or you can press the number keys also. Functional, but not ideal - you're not gonna memorize the id of each character (especially once you've moved them around and rotated some levels), the TAB to cycle sequentially is viable but tedious, and even if I bring back the visible numbers for easier quick select, it's still got some overhead.

Enter the idea idea: press one key to toggle to the nearest character! Well, it seems like an obvious thing now, which explains why it took me this long to think of it. Currently I'm mapping it to the ALT key, as in you are generally ALTernating between 2 characters. What if your current character is equally distant from more than one character, huh? The game keeps a running log of the most recent players controlled, and it will automatically choose the one you most recently used. (Sure, if you've never controlled any other character, at that point it's essentially random - whichever order the objects are loaded in.) I also added a feature where if you jump off of a ledge and land on another character's head, the game automatically switches control to the player you landed on - this is valuable because once a character is being carried, he can no longer move and you're gonna have to switch anyway.

Fixed a nagging bug where a character could land on another character's head, get set as "carriedLeft/Right" but then illegally execute an extra move in the same direction, then be stuck on the ground in "carried" mode and unable to move. The bug: game applied gravity, game applied movement (in this case, player takes final steps and is ready to be carried), then after that the game checked keyboard input. "Oh, look,you want to move left? (Next gravity cycle has not been applied, so character has not been set ito carried mode) Sure! her'es your ticket - one step to the left, have a nice trip!" The resolution here, check input right after applying gravity. (I figured this out just as I was typing in some comments in another function like, "well there's this special case for carried players, so we have to hack into player object and reset target position to null" ... whew!)

Also fixed some incorrect animation rendering, lava was not following level rotation (lava and other static tile animations are still controlled within individual level object). In a similar job, I added finer control over objects' rotation value, so that I can optionally instruct objects to rotate "against" the level as it itself is rotating. So if your player rotatesa level to the right, the player rotates 90 degrees to the left at the same time as level is rotating 90 to the right, thus remaining "on his feet" for the whole time. Gems do the same. Other objects though, such as crates and the colored blocks, instead go along with the level as it rotates, and then accept an accumulatedRotation value, so that as the object returns to the world's rendering control, its rotation can properly reflect the transform it received when the level rotated.

Now focus moves onto the level editor, to support levels as components. It is going reasonably well so far - I can once again make tile edits, and have context menus and their various actions back online for objects and animations (with minor bug action). I think I'll wrap on it pretty soon (to the extent that it has parity with its feature set prior to latest refactors), which will probably queue more work on the glue mask logic, namely those consequences of rotating levels and vacating glue affix wall locations.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Sun Sep 17, 2017 5:18 pm    Post subject: Reply with quote

This is one of those days where I spent a reasonable amount of time doing "stuff" but it feels as if I really didn't do much, whether that's true or not. The first thing I worked on was export of all world data, and finally getting around to saving the export data to a file instead of just dumping all of the json into a textarea and copypasting it into a text file. I even added file exists logic, etc. If the editor is made public it'll probably save to a database so I'll have to rewrite that, but changing write_file to save_row will be a 10 minute job, essentially. This actually is a nice addition for the developer, as I can make a change to a world, then just hit save/overwrite and reload the page - no alt-tabbing to the text edtior, seeking the level file, pasting, saving, switching back - annoying overhead.

Most other work was on editor as well, aside from some fixes to animation spawning (still fixing bad level vs. world references). Lasers are now fully integrated into the editor, from placement to editing to behaviors to saving, it's all finally doable without level file hacking. The lasers were also getting buggy in the game - once again an issue of level vs world coordinates, whether the bug was incorrectly offsetting the lasers on world load (not desired, as lasers are level-as-component objects and their coords should be relative), or not properly translating them to world coords when doing laser occlusion checks. And, I think I still have to add in endpoint adjustment for when rotation happens - and ugh, I'll have to counter-rotate level before rendering them when within levels. Not that it's hard, but just another line to add onto the todo list.

I thought I might get to the glue before/after rotation scenario today, but not so fast. I may step back over to the music for a little bit soon - I've got another track melody done from a few days back, but it's missing the drum track. it'd be good to get a bit of a breather from all of the slogging tasks (I like level editors as much as the next guy, but...) in front of me lately.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Mon Sep 18, 2017 7:14 am    Post subject: Reply with quote

Well, this wasn't too bad to code in the end. I thought it'd be worse. Or maybe I'll find out in a few days that I didn't cover all the scenarios, and it will end up being more work. Hope not!



I'm not sure there's any way around it - the error message is gonna be a mouthful. What should counteract this a bit is the new sidebar I'm working on - it's going to list all the objectives, available characters, and then your rotation options. So if you're in a level section that can't be rotated, it's going to basically say "rotate right - blocked!" so whenever you want, you can check over there and say "oh, it says I can't rotate level right now" and then if you want to try it anyway, or you aren't paying attention, the level gives you the in-yur-face, you can't do that message.

And yes, that's right. After saying I needed to take a little break from menial coding tasks, I made the top call to start working on a sidebar.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Mon Sep 18, 2017 5:18 pm    Post subject: Reply with quote

This glue on the wall staying loyal to individual level component rotation is pretty hard for me it seems. I do think I have a correct implementation of "dissolve floating-in-air glue spots" i.e. you glued a crate to a border, then spun the level and suddenly there's open air, and it's got a little particle effect as it disappears to make it obvious. Where I'm hitting a wall though, it's keeping things rendering at the right orientation and then applying glue at also the correct orientation. It's tough because if you have a crate with glue on the left of it, then you rotate the level to the right 90 degrees, then the crate "accumulates" that rotation and is rendered sideways (this is what you would expect from a visual fidelity standpoint) - but the block is still in standard gravity within the entire world, and the glue mask now is on the top of the block because of the rotation. What's more is that the blocks themselves render their own glue masks, so I have to counter rotate against any accumulated rotation before rendering the glue mask - and that mask's position (top, left, both, neither, whatever) must be adjusted internally after the rotation. And most of that appears to be functioning correctly - far as I can tell, but when the level rotation finishes, the glue is not being applied to the level itself correctly. Instead of pasting the glue above the crate (because glue is now on top, and that's what gets rendered too), the glue is still being pasted one tile to the left of the crate. What a bunch of damnation. Damned glue. And now I have now damned choice but to make it work, because that's in the url. (Okay, not that I was going to give it up otherwise, but grrrrrr)
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Mon Sep 18, 2017 8:51 pm    Post subject: Reply with quote

Made some ok progress on the glue front - sides now apply to the correct wall after rotation, and I fixed a bug where the glue application wasn't undergoing animation properly as well. Overall there's still a few lame bugs, glue getting stuck on walls on the other side of the level for no obvious reason. Unsure of whether it's a purely rendering issue, or if I'm really putting glue there and rendering it "correctly." Better run that debugger some more and inspect the objects. Oh yeah, and in case anyone has a pool going on "how many days until the color matching logic is bugged again and stops working" well I don't know, I made it quite a few days - but now I'm managed to make it not work once again.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Tue Sep 19, 2017 7:02 am    Post subject: Reply with quote

Interesting. After a few run throughs with the debugger, I found the main culprit for the level-specific glue bugs, and it was this:

Code:
var existingGlue = level.findGlueAt(x, y); // ideally we can reuse an existing glue mask
if (existingGlue === null)
    existingGlue = new Glue(x, y, TOP);
else
    existingGlue.applyGlue(TOP);

level.glues.push(existingGlue); // oops!  here i'm adding to the array every time, even if it already existed and we didn't create a new one!  oops!


What a shame. Would it be surprising to you to hear that this project is essentially the first time I have had a serious relationship with a debugger? I'm sure there's some kind of debuggers for python, but I've never used one, and never used one in any kind of C based game I might have made in previous incarnations. (I do have a love for doing things like this: print("why isn't this code working? x = ", x, "y = ", y) and so on.. and I'm still doing that too!) Anyway, it's good to have figured out what was going on in this case. There's still a bug pertaining to object-on-object glues being added to the wrong side, and the color match thing - once I fix those I'll be almost back to square 1... finally.

edit - object-on-object fixed, needed to internally track both accumulated rotation (via level rotate) and also push rotation (turns end over and eacht ime pushed), and then normalize the side to adjust for both of those rotations. color matching fixed too - not sure why, but it was checking almost every frame and this somehow made it not work at all - it's supposed to only check if block lands on ground with fall distance > 0. i vaugely recall taking a conditional check out of an if statement (which i have now entirely disabled) that probably made this possible - typical
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Tue Sep 19, 2017 9:09 am    Post subject: Reply with quote

Doesn't look like much - maybe cause it isn't, but here's the successful result of updating the lasers to render and process properly when its parent level is rotated.



Laser movement behaviors are defined in "upright" coordinates, so I say "move down 3 tiles and then back up 3 tiles." If you rotated level to the right though, then what used to be "down 3 tiles" should now be "left 3 tiles" - and if the laser is 1.5 tiles into the movement animation, then it needs to understand "well I moved down 1.5, but now I've gotta move left 1.5." Keep all of that updated might have been a bit of a job, so I took a safer route - behind the scenes, it's doing all of its positioning calcs in upright coordinates, and only when it's time to either render (or check for occlusion), that's when I ask the parent level to tell me, "if the laser starts at (50, 50) but you have been rotated twice to the right, what would that coordinates be on the screen right now?" And apparently that's all it's going to take, which is nice.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Wed Sep 20, 2017 8:11 pm    Post subject: Reply with quote

Still keeping busy with the new sidebar. Here's a look at the new design in screenshot form



I've some a little bit of education in the realm of css animations and transforms, which started last night. Never used em before, they're pretty easy but I started down the wrong road -- for my needs -- by starting off with animations. The problem I ran into is that I want to be able to interrupt a transition at any time, like if you press ESC to slide in a menu from the side, but maybe you realize "oops didn't mean to do that" and so you hit ESC again to get rid of it. Couldn't find a way to tell an animation to stop at some arbitrary location and then undo itself, and I did waste a small measure of time trying to hack in a queued animation system into my jquery knockoff functions. The transitions are actually even easier to "code" - you just say "element x should run a transition when you change widht" and then if you say widget.width += 100, then it'll automatically animate it (for whatever length you indicated). So, this works great for me cancel-in-progress scenario.

Screenshot also reveals the other thing I"ve been working on, a challenges system. I kept thinking about it along the way, and I couldn't stop any longer from getting it off the ground. After a couple of days of tuning, it's working pretty nice. I'm trying to keep it a little bit on the simple side - each challenge has a set of victory conditions that must all be met, so there's not (planned) gonna be anything like "do this -or- that to complete" and then there are failure conditions, any one of which will fail the entire challenge. Each condition is a simple a vs b compare, where each value is either a constant value or a key that gets translated at runtime. For example, a condition might look like this:

Code:
{
  left: {
    type:  "lookup",
    value:  "countGemsRemaining"
  },
  comparison: "===",
  right: {
    type:  "literal",
    value:  0
  }
}


Certain world events such as collecting gems, dying, etc. will throw in an order to the challenge tracker object, telling it that "something" happened and that it should evaluate each of the world challenges. Then, this example challenge condition would translate the "countGemsRemaining" to whatever real-time value that is, and compare it against 0. If evaulated to true, this challenge would be set as complete. Overall, the system in simple enough to stay pretty manageable in code, but it will have enough flexibility to create a suitably diverse number of challenges.

Still a decent bit of work to do to keep the sidebar integrated with game state - I haven't touched player data yet, so the "list of players" is totally mock data, and also tracking ability-to-rotate status which will change as you travel from level to level within a world, whether because the level has hard-set rules (e.g. you can only rotate 3 times) or because of a rotation overlap conflict. But, I'll get these sorted out pretty soon. Oh, restoring them upon a checkpoint reload is also part of the program - it's working for the challenges, I still have to replicate (ok, copy paste and hopefully not introduce bugs by missing a search replace) for some sections. Oh yeah, and tooltips probably. Move mouse over a challenge to get full description, and nothing weak like setting it in the browser-level mouseover tooltip (like I'm doing now...)

After my todo file got to like 500 lines or something, I created an alternate file called priorities.txt. It's closing in on 400 lines itself. I look forward to veryimportant.txt.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Thu Sep 21, 2017 10:46 am    Post subject: Reply with quote

Just found a pretty dirty lingering bug in the save state logic. Previously mentioned I'm saving game objects by reference - first time I see an object, I say "oh, you're new!" then serialize it, and add it to a list of distinct objects - then any time that object shows up, I add it to the state as object[n]. Or something like that, but the bug related to lists that contained world objects - this is an uncommon scenario, but array serailzations were not forwarding the running list of distinct objects, and thus if an array had game objects in it, boom, infinite recursion. (Well, stack size exceeded error - same thing.) So, that took a bit of time to diagnose and then fix up. (By the way, the list in this case pertains to the glue groups - a glue group does keep a list of object refs in an array, and I never noticed it to this point because I haven't been glueing blocks together on purpose.)

Sidebar has taken a couple steps forward. It's got a really nice css tooltip that hslides into place now - very pleased with it. I also added in realtime updating of the left/right rotation options, which means if you control a player in level section 1 where rotation is allowed then the sidebar says "ready" for left/right rotation, but as soon as you move into another level component where rotation in one or both directions is not allowed or not possible, the sidebar updates with a disabled icon and the tooltip updates to say "oh, sorry, [reason]". It's not quite done (currnetly lacking some statistical updates, e.g. "only 3 rotations remaining") but it's a strong start.

Added serialization of the new chalelnges to the world export method, and fixed a couple nagging issues that would throw exceptions on save (annoying to try to save and have the app hang, even when it's just test levels).

The last main objective for the moment is the player roster on the sidebar. Won't be too different from the other dynamic sections, but wooooof, I'm dragging my feet - let the ui work be done for a bit! I also have a very clever idea for the checkpoints ui, but I'm going to sit quiet on that one for a little bit. Small thing, but it'll be great.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Thu Sep 21, 2017 4:38 pm    Post subject: Reply with quote

Today, I sinned.

Code:
// "collecting" a Gem shall prepare it for expiration
Gem.prototype.collect = function(level) {

    // only collect once
    if (!this.isCollected) {
        this.isCollected = true;

        /* ... */

        // well .. this is kind of sad, but this is where
        // we finally hack into the global App object to
        // create a checkpoint
        app.createCheckpoint();

        /* ... */
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Fri Sep 22, 2017 8:54 am    Post subject: Reply with quote

I don't know exactly how "crazy" I will get with the lasers when I start making "real" levels. No doubt the first laser you ever see will just be a non-moving laser, we'll start easy, then some will move a little bit, rotate a couple of times - but at some point I'm going to take off the training wheels and really start screwing with the player. Will it be this crazy?



Maybe not. But, if there's any hope of me establishing advanced laser routes like these, there's essentially no chance of doing that "in my head." I tried on this one, and I got lost after a few steps when it had adjusted size and spun a couple of times. So, I finally got around to adding "preview at this step" support ot the eidtor - I click a button on the row (say the 8th row of laser steps), and it starts drawing the laser at the location it will occupy after the 8 steps to that point have completed. I can basically follow along frame by frame. It works very well - I took a hopelessly non-circuit-completing laser and had it back on track in about 2 minutes. After the 200 minutes I spent getting the damned preview code to work. (Moderate exaggeration.)

Got a series of other scattered fixes into the hopper. I think I fixed the rolling crates glue side bug fixed - I wasn't accumulating the rotation upon grab or end-over-end push, so that would obviously cause side application bugs since internal rotation wasn't kept up-to-date. Nervous as I type this, because I wonder about the glue mask object iself needing the same fix, but looking at the code I think I am already handling that - the glue mask is a child of the object it's applied to, and I think the system is "smart" in that regard. It certainly seems to work correctly now during gameplay testing.

Also finally fixed some gem collection errors, such as not collecting gem during a jump animation. That was because the jump animation is render-based, where I never change the physical coordinates of the player until jump completes, at whcih point I just x += 1, y -= 1 type of thing. So if there were a gem above the playe'rs head (that he jumps through in the process), it wasn't getting detected - that's fixed now. I also have the gem checkpoint system pretty much completely online, including a very cool system where it generates a thumbnail of each checkpoint that you can bring up in a side panel.

I'm not quite sure what's next at the moment. Oh, probably the application of glued objects to walls during gravity. Right now if object is pushed over edge, it falls to the bottom pretty much guaranteed, but I think if it has glue on one of its sides and it passes by a wall it should glue to that wall. I think I have to add new cell threshold testing, where if y += gravity takes the block into a new cell (but y % tileHeight === 0.225) then I clamp gravity back to y / tileHeight if doing so would allow a glue application. There's another hundred things I could probably pick from too...
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Fri Sep 22, 2017 12:50 pm    Post subject: Reply with quote

Alright! New concept level. Here I demonstrate the throw-and-glue addition, where a falling block will glue to the wall on the way down, letting you create your own bridge. Then watch as I try and fail 2 or 3 times in a row to get one of the gems, blatantly abusing my save state cheat keys before finally realizing it's not going to happen during a live performance and abandoning it. (Just need to edit that laser a little bit to make it less pixel-perfect.)

I also added a little "grace area" for the lasers, so that even if one is hitting you, it won't completely kill you until it makes solid body contact.

View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Sat Sep 23, 2017 3:21 pm    Post subject: Reply with quote

Is this feature creep? Maybe, but I think it's happening. Sometime.



Here's the thing. I was thinking about adding teleporters to the game, I'd thought about it from early on in the notes but wasn't sure about it. And well, the pipes are the same thing as teleporters, but they'll be way cooler. To hell with the stupid teleporters that magically transport you from point to point. And to back up the point even more, the pipes make it way more obvious where you are coming from and going to. It's better in every way.

Of course, have I programmed anything for it yet? ha a ha! No, of course not because I've been coding waaaaay more exciting stuff. Number one winner today, the logging of uncaught javascript errors to a database! Even if you don't count the 30 minutes I wasted trying to figure out why my 10 line php script worked locally but threw 500s on my host (damned permissions, how could it have taken so long?), even without that it was still a lot of fun! Oh yes! Now, on the plus side of that pool of damnation, it will probably be useful. I went a step further than just logging the error - I also log the gamestate (could be useful), and I log the keypress history - so in theory I could run an exact replay of the series of events that led to the error. Very interesting, right? (Oh, but of course, do feel free to ask me if I've actually coded the "replay" system......)

During some real world testing, I spotted and (occasionally reproduced) a sticky key error. And I'm not talking about those damned windows sticky keys, but rather the scenario where game tricks itself into thinking you're still holding down ArrowRight even though you're not, so you just keep running to the right. Man, I have no idea if I've solved it because I just can't reproduce it in lniux to date - may have to boot windows sometime and try it there - but I added a disqualifer in the keydown code, where if the keydown event is a repeating keydown event, it gets ignored. I have zero use for repeating keydowns, because I'm already tracking "is key down" in a custom object. At best, the extra keydowns are console spam, and at worst they could have triggered the sticky key scenario on some setups. Just not sure.

I guess there were a couple other bug fixes, like not being able to push a block if it's just been pushed over ledge, no longer able to grab blocks that are glued to wall / other blocks, the like. The stuff no one ever wants to programs, like once you get the base concept working, it's cool and you make a video about it, then it's more fun to just ignore the little bugs that do really have to be fixed. I should outsource them.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Sun Sep 24, 2017 5:22 pm    Post subject: Reply with quote

Played around with the pipes just a little bit today. I did add an animation for "dive down into pipe." At first I thought it might be cool to have the character do a "card flip" upside down and then enter the pipe, but in execution it didn't really look right. (The effect itself was about right, it either didn't fit what I was going for or something.)

Another thing I noticed, when running the current build on live site (as opposed to running it locally), sometimes got some console errors about "surface doesn't exist" which figured to result from images-not-yet-loaded. I had a resource controller object that loads in a list, and one of the "bad" images was certainly on the list, after some deliberation I decided perhaps I wasn't including the file size for the image, and thus the resource controller would say "ready" prematurely. Unsure about the total accuracy of that conclusion, but it was true that I had omitted file size from a large number of files. (A lot of others I had just hacked in "100 bytes!" as placeholder data.) So, I got off my lazy chair and wrote the 10 line script that loops my resource file, checks size on disk, and then updates resource file in place. Then added the progress bars and wired them up to respect the file. Well, the gfx resource progress bar isn't updating properly - unsure of why, but the other two are good, so it's something specific to my gfx loading code / reporting. Not considered an urgent priority just yet.

I am pretty sure I want to make the pipes full tile size, so that I don't have to scale objects down when they're traveling through pipes. Going to make a bit more work - lot more? - when I'm designing levels, because the "lip" of the pipe is now going to be wider than a tile, so there'll be much more time spent adding those effects. Very possible that I could write some kind of smart algorithm for it, though... we'll see. For starters I'll wirng it, just like I spent x weeks hacking json files in a text editor to control level files and stuff. (Still doing the challenges this way - probably will last a good while, too.)

And of course, as far as traveling through the pipes, that's still a.... .... .... ....... .... pipe dream. Ha ha ha ha ha ha! Wait... come back... don't close me... please......
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Mon Sep 25, 2017 3:55 pm    Post subject: Reply with quote

Progress on pipes has been agonisingly slow. There are a few reasons for it. first, I spent a lot of mana working on the new sidebar and realtime updates to it. ui work is just a grind somettimes. Second, grahpics. Now, I'm much satisfied with the puzzle pipes theme I downloaded, however the size of the tiles is off. I want/need the pipes themselves to cover a whole tile, so the characters and objects can move freely* through them. (Still going to have to consider some on-the-fly scaling because I want everything to tumble end-over-end all through the pipes, and 45 degree turn of tileWidth is > tileWidth - maybe I'll just clip instead, I don't know. Clipping could be fun.) So, there's been various starts at stops at resizing, and also I want intersections and trisections which weren't included with the pack. Third, it's just kind of hard, for me at least. Didn't have a strong plan for how to map the travel from end to end.

What I have now is the pipe graphics resized and ready-ish to go - odds are good I revisit them at some point, or want some change, but I'm ok with moving forward with what I have. Also, I coded "smart" application of the pipe edges, the corners that require being placed on adjacent tiles. It will save me a lot of time and tedious grind of applying 2 edges to every length of pipe (or every other, as my current trend) in any level where I use them, and it also saves me from dedicating 16 separate tiles or whatever on my tilesheet to all of the rotations, permutations, etc. And, it'll let me preserve any existin gmask layer, so I can put a little sprout of grass on mask layer right next to pipe, and the edge/corner of that pipe endcap will just render on top of the mask, preserving grass and pipe component alike.

I also now have a plan forward for the travel. It's pretty straightforward, basically I'll set up an "itinerary" when first entering a pipe, a list of target coords - move down 2, right 5, up 3, etc. During this time, no gravity applied, no coliision (assumed within the pipe, not within the level now). Inter-object collisions that are going opposite ways in the same pipe, that's kind of accounted for. The primary asterisk right now is how to handle collision between object coming out of the pipe, and object sitting "in the way" of the exit. If just one object, I want traveling through pipe object to knock it out of the way, but two objects, too much to overcome. But that requires collision detection between in-pipe object and out-of-pipe object, which in every other scenario I intend to disable. Hmmmm. Maybe the final item in the interary list - assuming an exit to the pipe is indeed found - can include a flag to check collision "outside of pipe" during the final movement. Maybe. Well, that's an advanced case - I'll start simple and work forward.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Tue Sep 26, 2017 5:44 pm    Post subject: Reply with quote

Fitting for a dev log, here's a rough cut of a concept level featuring the pipes. I went a little bit overboard on the pipes - the levle is actually not solvable (green blocks), and what can be done is difficult, but a handful of the basic concepts are well demonstrated here.



If you look closely you can see a number of issues. The core logic for rendering objects in pipes is good - if object is traveling in pipe, then redraw base layer, draw object, and then redraw mask layer on top of object, with a clipping region to prevent outside-of-pipe rendering as object rotates. The velocity is also good - it ramps up to a top speed, then slows down at the end. The not-quite-theres: rotation is off. I don't make any attempt to rotate such that the object ends up at the same rotation as it started. I'm very sketchy on the math for doing that, because it's not even going to be a flat rotation rate - it'll rotate more slowly at first, then spin fastest when it's at top speed. So, good luck with that, right? More problems: when redrawing base, object and then mask layer during travel, I don't properly compensate for level rotation, so there's black squares rendered on the left level (which is rotating) at times, during pipe travel. That I know I can fix. The harder one: rendering level outlines as object passes through pipe between levels. For this, I guess it'd be more like draw base, object, mask, and then (any level border) - I suppose I can get the calculations for that. It'll probably be fun. (On the plus side, unlike with the rotation calcs, I am sure I can do it - given the inclination.)

It's buggy as hell in a lot of ways still, but this is a start, something to build on.
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 324
Location: Tristram
PostPosted: Wed Sep 27, 2017 4:06 pm    Post subject: Reply with quote

After posting that last video, I got to being a bit depressed about the state of things. Part of this was the bugginess of things. Sure the concepts in principle worked, but the guy tried to jump on crates pushed into pipes, things rendered wrong going through them, and so on. Another part was the level itself, which I think had some fine concepts in it, but it didn't please me at all. (Maybe without the bugs...) I skipped the evening coding session and everything, I was out.

I was skeptical today staring down my neverending list of bugs, so I just started with a basic square with some pipes on it so I could easier test the rendering issues. Lo and behold, this simple box level turned into a very nice level, and I was able to revive my spirits quite some amount. This level is 10x improved from the last, and I am quite certain it will be seen in the final game.

spoiler note - i'm going to push this live right now, if you'd like to try to solve it on yoru own don't watch! gluegunglen.com/wip


The big winner: accurately* calculated rotation so that objects enter and exit at the same orientation. I was most skeptical about doing this of all things, but I put some thought into it and crafted a good solution. (Asterisk means that I've noticed occasional errors in the 5 - 10 degree range - will investigate more, but at present more than satisfied. Unsure of what might be introducing the occasional off-ness, as in general it works within what looks like a degree of exact accuracy.)

More wins: pushing crate into pipe now works seamlessly. I had an issue where the player movement attempt was reporting as false after taking a couple pixels' worth of steps in the push attempt, because at that point the crate said "hey I'm busy here, I'm going somewhere, so you can't push me." Solved that by continuing to reject the "push crate" request but then returning true for the move request all the same. Good enough, it seems. Also, rendering is almost correct now . There's still a bit of a wrongness with the borders, but it's subtle and at this point is not objectionable enough for me to focus on. (Another truth here is that the borders are quietly being rendered a couple of pixels off target, covering too much of 2 edges and not enough of the others....)

So the bottom line here - still a fair amount to do (example: want to make it so player can ledge jump into pipe entrance, doesn't work yet; considering not having objects fall down into pipe unless explicitly thrown by player), but this cleanup effort was super valuable.
View user's profile Send private message Visit poster's website
Reply to topic GDR Forum Index -> Game Developer's Refuge -> Development Log - Glue Gun Glen Page Previous  1, 2, 3, 4, 5, 6  Next

Use this link to get a Sign-On Bonus when you get started!

All trademarks and copyrights on this page are owned by their respective owners. All comments owned by their respective posters.
phpBB code © 2001, 2005 phpBB Group. Other message board code © Kevin Reems.