Chadwyk.com

The ramblings of a developer

Now We’re Talking!

One of the biggest tasks I’ve been putting off is figuring out how to handle conversations. Luckily Ron Gilbert once again comes to the rescue with his open source release of Delores. In it, he has a bunch of .yack scripts which I believe he said are loosely based on Ink (scripting language by Inkle). Well I ended up writing my own lua parser which analyzes these .yack files. There are some more advanced features that Ron used that I am not – or I am handling in code someplace else, but for the most part it works. I can put lua code in curly brackets if needed and I can set tags for each dialog line.

  • [random], where if they all have the same grouping it randomly selects one and removes the others.
  • [once] will only show that item once if you click it.
  • [showonce] only shows once regardless if you clicked it or not.
  • [temponce] will show it once if you click it, but then next time you come back to the NPC to talk to them it will appear again.
  • [YACK(“variable_name”) == 1] is treated like an “if statement”. If variable_name == 1, then select that line.

One additional thing that made this a whole lot easier, is I created a state manager, so that I can easily keep track of variables that will need to be saved to JSON. This is a life saver. I can say setProperty(“name”, “property”, true); and it keeps track of it. I can easily loop through all properties and spit them out to json. This function’s last argument takes bools, strings, ints, and floats so I can basically store any value in it that is needed. In the yack file’s init, where I initialize the variable “mumble_counter” to 0, then the YACK function basically just runs setProperty(“example.yack”, “mumble_counter”, 0); then to run the if statement [YACK(“mumble_counter”) == 1], the YACK function would run getProperty(“example.yack”, “mumble_counter”); and then it would compare it to 1.

OK here is an example of a conversation script, .yack file.

=== init ===
{ YACK("mumble_counter", 0) }
-> exit

=== start ===
{ hideVerbMenu() }
player: SAY(12281,"Hi papers!")
papers: SAY(12282,"Hello player!")
-> main  -- Transition to the 'main' section

=== main ===
1 SAY(12283,"What did you mumble?") -> mumble [once]
1 SAY(12284,"Just then! You did it again!") -> mumble [YACK("mumble_counter") == 1] [showonce]
1 SAY(12285,"Whatever <mumble>") -> mumble [YACK("mumble_counter") == 2] [showonce]
2 SAY(12286,"Not a lot to do here, is there?") -> pools
3 SAY(13288,"Yawn...") -> bored [random] [once]
3 SAY(14288,"Ahhhhh!!") -> bored [random] [once]
3 SAY(15288,"I'm tired...") -> bored [random] [once]
4 SAY(12288,"I was thinking about becoming a professor...") -> detective [once]
5 SAY(12289,"Got to run... bye.") -> done

=== pools ===
papers: SAY(12290,"Not really.") [once]
papers: SAY(12291,"There are some pools over there.")
papers: SAY(12292,"They are kind of deep") [once]
papers: SAY(12293,"But I don't like to get wet.")
-> main

=== bored ===
papers: SAY(12290,"Sorry to bore you")
-> main

=== mumble ===
papers: SAY(12295,"I don't understand-what you're asking?") [YACK("mumble_counter") == 0]
papers: SAY(12296,"Are you on drugs? Just say no.") [YACK("mumble_counter") == 1]
papers: SAY(12297,"Hey, the 'mumble' gag is mine!") [YACK("mumble_counter") == 2]
player: SAY(12298,"Ha! Got ya!") [YACK("mumble_counter") == 2]
{ YACK("mumble_counter")++ }
-> main

=== detective ===
player: SAY(12306,"Ever met one?")
papers: SAY(12307,"Can't say that I ever have.")
player: SAY(12308,"Maybe I'll just make a game that has a detective in it.")
player: SAY(12309,"Sounds easier.")
-> main

=== done ===
{ showVerbMenu() }
-> exit

My parser passes the dialog to my engine which queues the dialog up. If it finds an audio file with the ID number, it will play it and display the text. If not, it will just display the text.

Here is a preview of what the above file looks like:

Back at it again!

It’s been a few years since I worked on any dev work outside of my day job. I lost interest in making my point and click adventure game because the engine cocos2d-x that I had originally been using, removed xbox support because they didn’t want to support it, then eventually the c++ version went out of support, in favor of a GUI version of the engine much more like Unity. I’ve played around with things like Adventure Creator for Unity, and some other engines but I really don’t want to learn to use those types of engines because that is more scripting and I want to get into the gritty of programming. I always feel way over my head with those engines too. I restarted the game framework many times and gave up each time after getting burned out on it.

I later found that cocos2d-x had been branched and renamed to Axmol http://axmol.dev Even better, they added back in UWP apps, so that means Xbox is once again an option with it. In addition I believe with Axmol, if I want to port to Nintendo eventually, it’s possible, with a lot of manual changing of the rendering code. From my understanding, on Nintendo’s developer forums, there is info on how to do so, but it is under NDA.

Recently I decided to start over one last time in C++ and Lua scripting. I decided to go a different approach and found ways to really simplify my old code for creating walk boxes and pathfinding. It works so much better too. I am also using a built in library, imGUI for making windows and text boxes etc which makes things a lot easier. So I am happy to say that after about a month, I am much further along than I had ever been with this project. I am close to having a working prototype that can move between rooms, but character movement, basic inventory control, and verb commands are all working in this prototype. The thing I’m really happy about is that the path finding code now can use far fewer polygons and it is way quicker to create them.

During Thimbleweed Park’s development, I had read and paid very close attention to how Ron Gilbert did things via his devlog. Later when he released the open source project Delores, which used the same game engine, I got even more insider information. I am taking a lot of influence from what he did with his “Wimpy” tool to build out levels. Though for now I am building the editor directly in my game. Once I get the game to a pretty good spot where I won’t need to add much more code to the editor, I’ll branch the project and remove all the editor code so that the finished game won’t have that code. It might not be the best way, but I don’t want to update two code bases until I get much further into the development.

That being said, I have not decided on a game name yet, and the story is still being worked on. For now I’m referring to this project as codename “Ariel”.

Below is video showing a bit how the tool looks, and the prototype in action.

Bleh…

So it’s been a long time without an update.  For a while there I was working a side job at work which sucked up my free time, then I kind of just lost interest. Then next thing I knew I let me website hosting expire, and my Apple account expire.  I just now got my websites back up finally, but at this moment Lumps of Clay on the iOS App Store is still down.  I’m unsure if I’m going to bring it back.  It never saw too many downloads.  In order to get it back on the store, I may need to recompile it since it’s been so long, but the engine it is written in, is no longer supported so I may run into issues.  I’ve thought about porting it to another engine, but then I think “why should I do that unless I port it to other platforms”.  Bringing it to Switch might be cool.  But I also never got very far on my other project, which would have been a point and click adventure.  I’d almost rather see that through than revisit an old game.  I’ve kind of had more interest again to start that up again, so maybe I’ll do that.

Simple Stupid Funnel Algorithm

It has been a long time since I posted anything or really worked on this project.  I finally got some motivation and decided to tackle a couple of the hard issues that I was facing and wasn’t sure the best way how to handle.

First up, clicking outside of walk boxes.  What should happen? Where should the player move? I went through lots of experimentation to find the best results.  Finally I made an algorithm to expand a + out from the click point to see if it hit any walk boxes.  If it does, then that is the spot the player walks to.  If not, then it means it is in a diagonal and I need to find the closest walk box vertices to the click point, and have the player walk to that position.

That was difficult but I was able to handle it with relative ease.  The second issue was that I had the player walking the path to a click point, but he would move to the center point of each walk box as he walked through them. This lead to a very unnatural look.

When I originally made the code for walk box path finding, I remembered that Julian Ceipek wrote about something called the Simple Stupid Funnel Algorithm. http://jceipek.com/Olin-Coding-Tutorials/pathing.html#funnel-algorithm This algorithm finds a more direct route for the player to walk, and it looks a lot better.  I followed this article that he linked to by Digesting Duck which gives a very excellent explanation of how it works. http://digestingduck.blogspot.com/2010/03/simple-stupid-funnel-algorithm.html

However, much of his code was hard to follow and in psuedo code.  Luckily in the comments I found someone used his code in a javascript example and posted it on pastebin.  http://pastebin.com/7jwrmw1i

It actually probably only took me a couple hours to port the code to c++.  The hard part was to figure out all the “portal points” along the walking path.  This means basically finding all the vertices of the edges the player walks through. Also not a horribly difficult task.

What was hard, is that I needed to keep track of the point orientation as the player walked the path.  This was crazy hard for me to figure out the best way to do it.  You could not just say, if the player goes left, the left vertices is the bottom one and the right is the top.  That might work for some shaped walk boxes, but others it wouldn’t, especially if the angle you were walking into it was a diagonal.

The solution I finally came up with was to find the orientation of the segment. If it was mostly vertical, or mostly horizontal. Then I got the direction the player was moving in. Based on that I made the following conclusions which seem to work.

If the segment was vertical and player moving right, then left = upper vertices, right = lower.

If the segment was vertical and player moving left, then left = lower vertices, right = upper.

If the segment was horizontal and player moving up, then left = left vertices, right = right.

If the segment was horizontal and player moving down, then left = right vertices, right = left.

So now after tweaking my code to move the player along the path via the center points of each walk box, the player walks a smooth line to the click point!

The final step in the process is Steering.  I’m unsure if I’m going to do this or not.  I don’t think my walk box paths are going to be that big and it looks pretty good as is.  For example, if a player is walking around a turn, he will make a 0-point turn.  You could use steering to tell the character to generally stay within a range of the path I made with the Simple Stupid Funnel and steer back to it if they get off track. If I implement this, I’ll have to do some more research into the best way to implement it.

Now for a demo!

I was Hacked!!!

&%@# You Hackers!

Ugh… today was a pain… I woke up and found an email that eBay locked my account because someone hacked my password.  Turns out I think I used that same password on lumpsofclay.com… no good….

I also got an email that some random email address got set as an “Owner” for lumpsofclay.com. They hacked the site and since they had access to the server, where all my sites live, they messed up almost all of them. They hijacked them with malicious code and had google re-index my sites, so now crazy links pop up when you search for them.

 

Lame… I spent a good chunk of the day on chat with my hosting company.  Luckily they were able to restore everything from backups.  I then promptly changed all the passwords for website accounts, databases, and other websites that may have used any of those passwords that got hacked.  I also updated WordPress and all plugins incase that was the attack vector, but I think it was an old password that may have been listed on some hacker sites from other websites getting hacked.

 

Bleh… I know I should never of done it, but it was easy to use the same password for multiple sites.  But no more!  No more using the same password for multiple sites! I’m going to start using password manager software!

 

It could have been worse… they could have got banking passwords (which were all different already).