Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs

How do you implement "floating objects"?

A topic by Garry Francis created 64 days ago Views: 61 Replies: 12
Viewing posts 1 to 4
Submitted

A "floating object" is an object (usually scenery) that can appear in multiple locations. For example, if you have ten forest locations and you want to implement a tree (or trees) in every forest location, you don't want to create ten trees with lots of duplicated code, you just want to create one tree and move it around as the player moves around.

I tried doing this with code similar to the following:

: if (is_at "room01" && is_just_entered()) {
   : create "front_gate";
}
: if (is_at "room02" && is_just_entered()) {
   : create "front_gate";
}

I tried putting this in on_describe{} and on_tick{}. In both cases, the front_gate was moved, but it didn't appear in the list of objects until I refreshed the display with LOOK. Apparently, both of these blocks are executed AFTER the display has been drawn.

Then I tried something like this in the on_command{} block in locations{}:

: match "n _" {
   : create "front_gate" target = "room02" ;
}

The front_gate moved, but I didn't, as it didn't fall through to the normal movement routine, as it should have.

I had to force a move with:

: match "n _" {
   : create "front_gate" target = "room02" ;
   : goto target = "room02";
   : redescribe;
}

This seems a bit extreme.

So what's the best way to implement floating objects?

In a way, although I can see why you might want the functionality, I'm struggling to see why you would want this functionality in the specific examples that you're giving.

Your trees and gates would surely be non-conspicuous (i.e. invisible from the object list) scenery items, and would be mentioned instead in the location description... "You are standing in a forest, surrounded by trees."... in which case whether they are created before or after the object list is printed doesn't matter.

If you really want "object list visible" trees in each case, then I would suggest that creating multiple "dumb" tree objects would be the way to go, because it would be probably just as easy to define the interactions with each "tree" based on the location range/zones.

But yes, Adventuron doesn't seem to give you a way of doing something between printing the location description and listing the objects, like a system such as PAWs does.

[Now, if it really was a floating object you wanted... with this theme, literally a ghost (that's defined as an object) that maybe follows you around, then I can definitely see the need of that sort of functionality. You'd probably have to have a "The ghost floats into the room..." message printed in the on_describe section to explain why it was initially missing from the "objects visible" list.]

Submitted

I actually have something like that, which is another reason why I asked. I don't want to give anything away. Let's just say it's for NPCs that can move around.

Submitted

I use floating objects a lot in order to avoid duplicated code. The example was just that (to keep it simple). I used scenery for debugging purposes. Now that I know about conspicuous, I would use that for the trees in a real game.

The problem surfaced with doors. I had implemented my own doors and they worked perfectly, except that I had to duplicate the door in each room. "There must be a better way" thinks I to myself. Then I discovered Adventuron's doors, but they are one-way doors and require duplication, but you can't access their booleans and you can't have multiple doors in the same room and you can't unlock a locked door other than with a key, so it's back to square one.

Host

Adventuron's doors are a work in progress, and largely there for absolute beginners. If you need anything atypical, you can certainly code your own doors, which is what you did. Door will get better but I'm wary about introducing a whole bunch of commands just for doors (to interrogate their properties for example). I think that if you need to go that far, maybe a door template is not appropriate anyway.

Submitted

Your doors look quite flexible with respect to messages, you just need to have a two-way door option and you need to be able to get and set the open and locked properties. For example, a door can be locked (to prevent it being opened), but it is unlocked by using a swipe card, not a key. In fact, this might be an example where unlocking and opening happens at the same time, so you need to be able to set the open property and clear the locked property when you SWIPE CARD. Oh, and you need to be able to customise the description so that you can say whether the door is open or closed within the description. This means you need to be able to get those properties.

Host (4 edits)

You're welcome :-)

start_at = field
locations {
   field      : location "You are in a field." ;
   meadow     : location "You are in a meadow." ;
   river_bank : location "You are at a river bank." ;
}
connections {
   from, direction, to = [
      field,  east, meadow, 
      meadow, east, river_bank, 
   ]
}
objects {
   sparrow : scenery "a sparrow" ;
}
on_pre_describe {
   : if (is_just_entered ()) {
      : create "sparrow" ;
   }
}
(1 edit)

Is there a command to manually print the "You can also see..." line in Adventuron? (I can't remember off the top of my head)

If so, or if there was, then another possible simple solution would be to drop the object list from the location format, and manually print it (on first enter) from the on_describe block, once all the object moving around stuff is done.

Host

Yes, you can print an object list for a location but I feel it's  easier to rely on the layout mechanism.

How I see it, the problem is really "how do I execute something before layout", not "how do I manually perform layout".

The suggested workaround will work, and once pre_describe {} is added, then the layout won't have a problem any more.

Submitted

Can you explain why the:

: match "n _" {
   : create "front_gate" target = "room02" ;
}

didn't fall through to the normal direction processing? I've actually got a test after the match statement (not shown here) and if the test fails, it falls through to the normal processing, but when I added the create, it didn't fall through. There is no done or return statement, so it should have continued with the normal processing.

Host (1 edit)

I just to say wrote a section of the document on masking, which is my (just before bedtime) quick demonstration of how overridding works in adventuron:

https://adventuron.io/docs/tut/#MaskingCommands

To be more specific as to your example:

: match "n _" {
   : create "front_gate" target = "room02" ;
}

If you perform ANY operation in response to something that might otherwise be handled by the system matching "n _" or "get _" or "drop _" etc, then the system will no longer handle the command. It's treated as if it's an override.

If statements are not statement that do anything themselves, they only decide what commands will be executed, and which will not (same with match, else_if, else).

 Only commands that actually do something or affect the game state are treated like overrides.

In your example, create is a command that affects the game state therefore because you put that inside your match, the direction is not handled by the system, it's treated as if you want to do the create INSTEAD of moving in the direction.

To flag that you still want to execute the system handler, you have to mask the commands that you want to execute in addition to the system handler. That's here the : mask {} command comes in. It's been in Adventuron for over a year, but you are the first person to figure out the need for it. You win some documentation. Much joy.

Maybe it's badly designed or counter intuitive, but this design is the design, for better or for worse. I hope you better understand the model now.

Submitted

Thank you. That explains it quite nicely. Now I also know what you were talking about when you mentioned masking somewhere. Now, if I need masking, I know how to do it.