Smash and Edit

Smash and Edit

Pushing things around
is fun!
(click image to biggify)

This week’s gruedorf challenge is a day late but at least 19.95 over. First up is a prototype of the reason I put in the entity collision event: A block-pushing demonstration! While it’s not quite “there”, I’m amused by the demo. I expected to have to do a little more work to get non-player entities to interact with each other, but the way I coded it up worked right on the first attempt!

Unfortunately the handling acts in peculiar ways, mainly due to the fact that I’m using playerstep = 16; to fake tile-based movement. I initially thought that playerstep would effect all entities, but ha… look at the name again, sucker! I’m tiring of how verge always handles player-entities as a super-special case from regular entities. They should all be one and the same but for where their marching orders are coming from, maaan.

There will be more developments on this front in the near future. Don’t worry, Glambo. Your two cents have not fallen on deaf piggy banks.

Old dog, new code.

I’ve invented maped1!
(click image to embiggen)

Today’s second verge-based miracle is Maped 1. In verge 3. In VC. Well, not quite fully functional seeing as it can’t load or save maps, and not really maped1 since its tiles are 32×32 and based off of pngs in the ./tile/ directory instead of a real vsp, but… SHUT UP OKAY.

This project came about from a long-standing desire for a mapeditor in-code in vc, a desire to find a use for overkill’s widget library, and a need for a map editor for my iPhone games projects. I don’t have much intent to build this past my needs there, but I have been building it fairly generically, so it could be updated for 16×16 tiles easily… so if anyone wants to come along and write v3 loaders and savers in vc, well, hell, we could surely use’m ;)

Download the Block Pushing Demo here.

Download the Map Editing Demo here.

As far as the mapediting goes, select “New Map”, enter a garbage string as the name, and two positive ints between 1 and 100 for the size. When in the map editing mode, ‘A’ and ‘Z’ scroll the left click button’s selected tile up and down, and ‘S’ and ‘X’ scroll the right click button’s selected tile up and down. Clicking left or right on a tile will paint, and holding ‘CTRL’ while left or right clicking will ‘eyedropper’ the tile you click on into the button’s slot you clicked with.

If you should strike me down…

If you should strike me down…

don’t eat the yellow tile.

So, I just added a global entity colission trigger to verge 3. If you set the global string trigger.onEntityCollide equal to a vc function, whenever an entity runs into an obstruction that function will be called.

It sets the following variables:

  • event.tx and event.ty are the tile coodinates hit.
  • event.entity is the entity who did the hitting.
  • is the zone of the tile being struck, as long as it was a tile obstruction being hit. Otherwise, -1.
  • event.entity_hit is entity index of the entity being hit, as long as it was an entity-on-entity collision. Otherwise, -1.

    This facilitates pushing entities around, and zelda-like tool use, and entities reacting to their environment in general. Basically everything that people generally hijack verge’s native movement system for. So, yeah.

    This feature is as of r244 of I haven’t fully announced it yet as I’m sure there are bugs and “bugs” in here (for instance, NPCs don’t collide with the player yet because that was apparently never permitted in the first place?). However, I really would like some feedback since this is a feature that lets everyone stop hijacking control from verge and gives the power back to the people. Or stuff.

    Download the demo here!

  • ah, crap.

    I took monday off from work to sleep. And so I thought tonight was posting night. Ha… whoops. 20 hours late.

    On verge3 I’ve been working on making a verge.cfg variable to specify an optional subdirectory that your maps and map vc can live in, so as not to clutter up the root directory.

    In sully I diagnosed a battle action queue error that sends an action to linger far too long at the bottom of the stack (fix pending). I fixed a problem where the cursor would wildly list to the left and bottom when you entered a battle. I also helped the always awesome Gayo with some stuff he’s doing with the Sully battle system. Yay for doing things!

    On the website side I added some preliminary RSS features to the front page and the forum page. I also fixed the HELL out of registration.

    Also I worked enough in my day job last week to need a day off to sleep this week. So yeah. Anyways: where’s Kildorf? I take back all those mean things I said, baby. We can make this work. Give me another chance… ;_;

    Things I’ve done this week

    Things I’ve done this week

    I added 4 new ways for fucntions to be called in verge3: trigger.onStep, trigger.afterStep, trigger.beforeEntityScript, and trigger.afterEntityScript. They are neat, and explained in detail in a news post and a new docs page.

    Updated Sully using trigger.onStep so in battle zones every step you take decrements the counter until the next battle. When it hits 0, you enter the battle system, and when you exit the battle system the counter is replenished beginning the cycle anew.

    I also bound trigger.beforeEntityScript to EntStart() and trigger.afterEntityScript to EntFinish(), and removed every single reference to these functions in map vc. Previously, to make things all kosher, these functions needed to be in every entity’s function at the top and bottom. So annoying.

    Then I fixed up Sully so you could get through a lot more of the game linearly again. Yay! You can presently get up to getting sara to the room with the thermal activators in the chests.

    I also have fixed two of the major battle system bugs: the original field music now resumes after a battle, and the renderstack seems to work right after any number of battles (whereas before it would slowly corrupt.)

    Pretty awesome, eh?

    You can get the updated Sully in the SVN. Anonymous/Anonymous

    Carried away.

    Another postlet: Instead of composing a big old fancy blog entry, i sorta got sucked into coding of various kinds. Been at this chunk of work for almost a full workday in hours now. Some people play videogames for fun. I work on a decade-old tech demo.

    First item: I added a seperate windowsize verge.cfg variable for x/y on top of the “screen size”. Say you want your game to be 320×240, but want it to run in windowed mode. Every single computer that runs verge3 will have a minimum res of 800×600, and even that’s small for the majority. automax makes an ugly-ass screen with lots of jaggies, and fullscreen mode isn’t guarunteed to be a square aspect ratio in this age of LCDs (320×240 on a 1280×1024 native res LCD looks like ass in fullscreen.) So I added new variables to give you a playable window port of 640×480 (or whatever you specify, really) so you can have your perfect aspect ratio and remain windowed. Whee!

    Next item: I did a hella lot of scripting of the Lance stuff on Mt. Jujube. Yay for scripting!

    As usual, go check it out at the svn repo if you’d like. Username and password both “anonymous”, as usual.

    I’m going to bed now. Some of us have to work in very, very scant hours :(

    v3 for you, v3 for me!

    To make a new vergec function:

    Step 1.

    You must create a C function to actually implement your new vc function’s logic. The naming convention is vc_NAMEofYOURnewFUNCTION, and convention says to put it in vc_builtins.cpp. If you’re returning a string, you will want to alter the std::string variable vc->vcretstr within your new function. If you’re returning an int, you’ll want to alter the integer vc->vcreturn instead.

    Step 2.

    You must add a function call to the array of libfuncs, also in vc_builtins.cpp. This is an ordered list of droupings of 3 c-style strings apiece. Each grouping represents a vc function: The first is the return signature, the second is the name, the third is the argument signature.

    Here is an example line: {“3”, “DictListKeys”, “13”},

    The “3” for the return type says it returns a vc string. “DictListKeys” is the name of the vc function. The “13” signifies that this function takes two arguments: an int and a string, in that order. The character “1” represents a vc int, and the character “3” represents a vc string.

    The order of this list determines what integer represents each function in the vergec bytecode. Fun, eh?

    Step 3.

    Whenever you add a function to the libfuncs list, you must also increment the NUM_LIBFUNCS define in opcodes.h. libfuncs is a static array, and NUM_LIBFUNCS is that static array’s size declaration.

    Step 4.

    Finally, you must add a new case clause to the giant switch in VCCore::HandleLibFunc() within the vc_library.cpp file. The case’s integer is the opcode in the vergec bytecode that represents the function. This is the index of the function’s definition in the libfuncs array from step 2.

    Step 5.

    Compile a new verge.exe, and debug your function. Congrats, you’ve made your first vergec function.

    Grue, why are you altering vc?

    Good question, me. I thank myself for asking it.

    Anyways, I wanted to add a way to get the list of vergec functions presently defined by the user in their code. To this end I first set out to make ListUserFunctionsm, which would work like ListBuiltinFunctions. However when I made this it failed horribly because I have so many functions: the string was simply too big for vc to handle. Not wanting to venture into vergec’s string handling functionality tonight, I looked for an alternate method.

    Quickly I settled on a vc_GetUserFunctionCount() and GetUserFunctionByIdx() solution, which was better by far in my opinion instead of returning a ginormous pipe-character-delimited string. However, I failed at this for mysterious and retarded reasons unknown to me at this time. So… I’ve utterly failed where I was trying to rock.

    But… why do you want those functions?

    Excellent follow-up, self. 10 points to Ravenclaw.

    While these two functions have several fun uses, I was making these functions so I could introduce a light unit-testing framework within vc. With some function-name introspection, I could find any function starting with, say, “grunit_” and use CallFunction() on it to execute said test. Making it automatically execute like that would be a great boon overall in the future, and would make it so I could develop a complicated system (such as say… a battle system) without fear of time lost in the future to hidden bugs caused by future feature implementation.

    Yeah, that’s right. I’ve caught the Agile bug. Don’t ask why I’m still using vergec, though: I’ve only partially caught it. ;)

    No SVN update this week. 4 hours in and I’ve still got a wash. I’m going to continue on, but I wanted to get this post out without too much more of a delay. So as I don’t feel bad about today, though, it should be noted that the development copy of improved by leaps and bounds today. Hooray!