Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411511 Posts in 69375 Topics- by 58430 Members - Latest Member: Jesse Webb

April 26, 2024, 12:25:19 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsMenagerie ✧ A Magical Virtual Pet Garden
Pages: [1] 2
Print
Author Topic: Menagerie ✧ A Magical Virtual Pet Garden  (Read 5821 times)
sand-bird
Level 0
**



View Profile
« on: February 17, 2018, 02:57:12 PM »



A virtual-pet game about studying and cultivating magical flora and fauna in your own zoological garden.

Menagerie is a love letter to games like Creatures, Viva Piñata, The Sims, Animal Crossing: New Leaf, and Sonic Adventure 2's Chao Garden. It aims to give the player a chunk of space they can express themselves in, fill it with virtual pets that are smart enough to seem endearingly lifelike, and stick it in the middle of a world they'll want to come back to.


BREAKING GAMEPLAY FOOTAGE

✧ ✧ ✧

Goals:

  • Believeable, robust creature AI -- probably most of this devlog will be about implementing behaviors & personality
  • Training monsters: everything a monster does can be encouraged or discouraged to permanently alter its psychology
  • Customize your garden by filling it with stuff! Make it beautiful and unique ❄❦❀
  • Lots of forms for monsters to evolve into, Tamagotchi-style, depending on how they're raised
  • A vibrant, cohesive world with its own mythos and history, including a unique calendar and holidays
  • An in-game Encyclopedia that fills with detailed info and collectible stories about the world as you discover it
  • An overarching story, told through procedurally-assembled letters, that you can influence through key choices
  • Support for super robust content modding built right into the data engine (and thorough documentation, too!)
  • Input support for mouse and keyboard, touch, or joypad, as well as externally bound controllers

Info:


  • Single-player
  • Suitable for everyone
  • Made (with love) in Godot

✧ ✧ ✧


an art

Hi there!

This is a solo project, and also my first game. I do this in my free time, and it's still very much in the early stages of implementation, so the going is gonna be pretty slow. This project means a lot to me, though, and I think I'm at a point where I'll be able to see it through -- even if it takes forever -- so I'm gonna go ahead and start a devlog now.

I'm glad to have you all with me!
« Last Edit: September 04, 2018, 07:19:24 PM by sand-bird » Logged

sand-bird
Level 0
**



View Profile
« Reply #1 on: February 17, 2018, 03:37:38 PM »

MOVEMENT (part 1 of probably a lot)

Monster AI is pretty core to the game, and I've been putting it off for a while now, so it's time to get started!

The monsters in Menagerie are AI-controlled, though they can be directed by the player. Monster behaviors are built from components: either simpler behaviors, which themselves have components, or atomic actions, like sleeping and emoting. The first and maybe most important action will be moving -- or rather, navigating -- to a target.

There are two kinds of (non-monster) things in the garden. Objects are things like plants and furniture; they align to the 16px grid and are immovable except by the player. Items align to pixel coordinates, like monsters do, and include stuff like food and toys. Many items can also be picked up or pushed around by monsters.

To get from point A to point B, a monster has to be smart enough to avoid all this stuff, and other monsters too. I didn't know the first thing about AI navigation so I did a bunch of research, and discovered that there's really two pieces to the puzzle: pathfinding and obstacle avoidance.

Pathfinding is about figuring out a route across a static map where parts of it are walkable and parts are not, and we know which parts are which in advance. It's generally solved through algorithms like A*. Godot has a handy premade navmesh-based navigation system that works with tilemaps, and with a little finagling I'm pretty sure I can get it to work with garden objects.

Obstacle avoidance is about going around things that get in your way. Since items and other monsters don't align to the tilemap (and since they're liable to move around anyway), I'll need to implement obstacle avoidance for them instead.



This is basically Menagerie's baby picture. That sad little sprite is a Pufig (the trees and grass are placeholders). He's going straight to the cursor and the movement looks really sucky.

For the actual movement code, I'm going to (try to) implement steering. Basically, instead of a character straight up moving where it wants to move (like to its target), with steering behaviors there's an intermediate force, the steering force. This causes a little delay that makes characters round corners smoother and generally look like they're moving more realistically, and it also opens up a lot of useful behavior.

This was my first attempt at steering force:



(I've been using this tutorial on steering behaviors for code examples. It's actually pretty bad, but it was the top search result and I'm too lazy to find a better one.)

Eventually got the "arrival" behavior working:



This slows your guy down as he approaches his target (important not just for realism, but because otherwise the delayed response from the steering force will cause him to rubberband around instead of stopping).

Okay, this post is already massive. NEXT UP, we'll give pathfinding a shot...
Logged

whistlerat
Level 1
*



View Profile
« Reply #2 on: February 18, 2018, 07:55:24 AM »

I'm all over this like a rash Kiss Do you have a twitter? I'd love to follow you.

Also gonna be watching how you solve a lot of the kinds of problems that pop up with interest, because it sounds like we've got similar problem spaces and it's fascinating to see how other people approach the same tasks, because of slightly different priorities and end-goals. Looks great already, keep it up, you've got one eager cheerleader already  Beer!
Logged

bynine
Level 0
**



View Profile WWW
« Reply #3 on: February 18, 2018, 08:18:50 AM »

it's a lot of fun to see the creative process here. i'll be watching this with interest!
Logged

https://bynine.itch.io/ - check out my games here!
sand-bird
Level 0
**



View Profile
« Reply #4 on: February 18, 2018, 08:36:27 AM »

whistlerat!! I love your devlog!! Seriously, I've been catching up on all your posts since I found it -- about halfway through right now. I've gotta make sure to comment there when I'm done Kiss

(Actually, my immediate reaction to it was a terrified "oh no, is this my idea but better?!" -- happily though, I think our goals are different enough that I won't have to challenge you to a blood duel)

I've got a twitter but it's still pretty dumpy. I should be the one who's following you, honestly!

Thank you both so much for commenting! I am filled with joy and pride Coffee
Logged

whistlerat
Level 1
*



View Profile
« Reply #5 on: February 18, 2018, 08:47:33 AM »

(Actually, my immediate reaction to it was a terrified "oh no, is this my idea but better?!" -- happily though, I think our goals are different enough that I won't have to challenge you to a blood duel)

bring it Evil

Nah we definitely have different goals and main focuses, but even if we didn't I'm making Monstrus 'cause I want to play it, so, feel free to make it but better Tongue I'm happy to discuss stuff if you need someone to bounce ideas off, you'll know I've probably thought about something similar at some point Smiley

Followed you on twitter, and I look forward to any of your feedback on Monstrus Hand Thumbs Up Right
Logged

sand-bird
Level 0
**



View Profile
« Reply #6 on: February 18, 2018, 01:10:09 PM »

MOVEMENT (part 2 of XX: pathfinding)

Okay, so that was moving to a single point. What happens if we have a path of them?



PERFECT

This path is generated by Godot's Navigation2D node. Basically you have to chant an incantation over a tilemap, and then when you put the tilemap inside the nav node it Just Works™. This demo (for Godot 2.1) is invaluable: https://github.com/FEDE0D/godot-pathfinding2d-demo

Two hours of carefully tuning numbers for code that will probably be scrapped anyway later...



Once I give Pufig some proper animation and put him somewhere more palatable than a freaky existential void, I think it'll look pretty good! There's still a couple problems, though. The more obvious one is the lack of collision (those grass tiles are supposed to represent walls, btw, so trampling all over them is not ideal), but also I forgot to have the path update during movement, so it can recalculate if I add or remove pathable tiles. Like this:



This really makes the first problem way more obvious, though.

Okay, time to deal with collision. That's gonna be another post, maybe two -- to be honest I don't quite have it figured out yet, so I might end up writing the "problem" half first to try and get my thoughts in order.

NEXT UP: blue semitransparent boxes forever
Logged

sand-bird
Level 0
**



View Profile
« Reply #7 on: February 18, 2018, 04:48:36 PM »

MOVEMENT (part 3: blue semitransparent boxes forever)

You mave have noticed from the previous screenshots that the pathing waypoints (which I have colored #00FFFF) are placed right at the corners of the navigable terrain. I don't think there's anything I can do about this; it's just how Godot's Navigation2D works. Unfortunately it makes this happen when I add collision shapes to non-navigable terrain:



If Pufig is going fast enough his momentum carries him around the corner, but at ambling to strolling speeds he'll get stuck.

(This is actually what speeds in the game are called right now, because I have an unhealthy obsession with enumerators)



I managed to come up with a couple of possible ways around this:

First, you can see that we now have a RayCast coming out of Pufig, for detecting incoming collisions with stuff (monsters, items) we can't path around. It is evidently quite useless for our cornering problem, though, unless I figure out a way to expand it into a pig-sized cone. Even then, I suspect it will be more finicky than it's worth. I'll revisit this when I actually get started on the obstacle-avoidance steering behavior, which I've been procrastinating on by writing these posts.

Second, notice that Pufig sorta slides against the grass wall for a sec when he collides into it. This happens because he is a KinematicBody2D, which is Godot for "thing what can bump into other things," and is getting around via a method aptly called move_and_slide. If I wanted I could swap this out for move_and_collide, which returns some collision data when the thing bumps into another thing so you can handle it manually instead. Then I could, I dunno, adjust the steering force accordingly to move him more parallel to the wall and less inside it. This should only happen pretty close to corners anyway, thanks to how Navigation2D works.

Honestly this is probably the most robust solution, meaning I'll probably have to implement it someday regardless. But it seems like way more trouble than it's worth right now. So, next:



IF THE WALLS HAVE ROUND CORNERS INSTEAD OF SQUARE CORNERS IT JUST WORKS™

Pretty cool, but this is only part of a possible solution. You can (kinda) see in the gif that every grall tile now has a circular collision box, which makes the collision area for the formation as a whole sort of caterpillar-shaped.



As you can also kinda see in the gif, this makes our dude bob along the sides in a not-very-wall-like manner. The obvious answer is to have square hitboxes on connecting pieces and round ones only on edges, but that's... well, actually, lemme back up and talk about objects some more.

I mentioned that objects include stuff like plants. This game takes place in a garden and so there will be a ton of plants. Accordingly, objects have to be stateful, with each state potentially having different sprites or animations, different logic (like when/how to spawn fruits), and even different collision boxes (like in the case of a growing tree). While tile objects in Godot have a few limited properties, like the collision shapes we've seen, there's no way they can handle all the stuff needed for a garden object.

But we need tiles for navigation. And objects do have a relationship to tiles, since they exist on the grid. (Actually this is a many-to-one relationship, since you can put objects (eg flowers) on top of other objects (eg flowerpots) on the same tile.) So -- at least the plan is -- the tilemap used for navigation will actually be invisible and consist of two tiles: unpathable and pathable, or "there is an object here" and "there is not an object here", respectively. Placing or removing an object will change the invisible tile it's on top of and voila, pathing. This is slightly more complicated for multi-tile objects, but it should still be doable.

As a final aside, I definitely want the game to be open to modding. Godot is actually pretty good about this: when you build a game it compresses all your resources into a binary file, but the executable can load resources that haven't been packed as well. All a user would have to do is create custom items in the right format and stick them in the right directory.

So, back to object collision boxes. Since objects can be (but are not necessarily) different-ish sizes in different states & yadda yadda, these ought to be defined per-object and overridable per-state. For stuff like park benches or whatever that's dandy, make 'em nice and oval and call it a day, though for "tileable" objects like hedgerows and walls it's going to be a little more complicated. Basically, though, since I don't see any way to avoid having to define specific collision boxes in-engine for each and every in-game object (sorry modders, you'll just have to use Godot I guess), the ultimate solution's gonna have to wait until objects are a bit more of a thing.

NEXT UP: something completely different!
Logged

katastrophic88
Level 0
**


View Profile
« Reply #8 on: February 18, 2018, 07:45:29 PM »

I was sold when I read Tamagotchi in your description. Nostalgia hit HARD. Looking forward to seeing this come along and playing it one day!
Logged
whistlerat
Level 1
*



View Profile
« Reply #9 on: February 19, 2018, 04:00:57 AM »

Is it possible to use the pathfinding as-is, but remove the actual physics collision between the critters and the scenery? So when the Pufig tries to go around that hedge because it recognises it as non-navigable, but when the actual Pufig sprite comes close to the square hedge, it doesn't truly collide, and just clips past. This probably wouldn't look great right now because it's clear from the momentum of the Pufig in the first gif of your last post that it would clip through the hedge a LOT. Are you not able to control the location of the pathfinding points at all? Maybe rather than placing them directly at points, you can place them a little further away?


gaze upon my paint-with-mouse-skills and despair

I don't know how Godot works though, and it sounds like you're using a lot of out-of-the-box functionality and that might not be trivial to adjust. If it's current based on sprite size, though - and automatically detecting the sprite corners - could you create transparent borders around sprites, so visually there is no difference but the pathfinding finds the 'true' corners?

But then you'll be dealing with a lot of unnecessary transparency so it's almost certainly a non-ideal solution Huh? I'm sure you'll figure out a solution which feels good!
Logged

sand-bird
Level 0
**



View Profile
« Reply #10 on: February 20, 2018, 10:35:56 AM »

I don't know how Godot works though, and it sounds like you're using a lot of out-of-the-box functionality and that might not be trivial to adjust. If it's current based on sprite size, though - and automatically detecting the sprite corners - could you create transparent borders around sprites, so visually there is no difference but the pathfinding finds the 'true' corners?

So Godot's navigation uses navmeshes, which are graphs of polygons representing walkable area. Convex polygons have the geometric property of being "traversable," which means that for any two given points inside one (including on its edges), a straight path will always exist between them. So navigating across a single polygon is trivial, and from there, you just graph search to find the next closest polygon and repeat. (Here's a short implementation tutorial that helps explain it a little better, if you're interested!)

In Godot you can define your own navpolygons, and it will stitch them together for you as long as the edges line up. With a tilemap this is super automatic: add a polygon to any tile you want to be traversable, and bam, your tilemap becomes a working navmesh.

The problem is that Godot's pathfinding calculation uses lines, not shapes, because while fitting a line segment completely inside a polygon is trivial, fitting a shape completely inside a polygon is a whole other thing. So the path has no area, and ends up right against the bounds of the mesh.

I was a dummy and didn't test this, but a lot of monsters will be too big to fit through single-tile passages. What will happen, as I realize now, is that they'll try to go through anyway and either get stuck (if there's collision) or clip horribly (if no collision). Both this and the cornering problem are issues of clearance, which, in the world of pathfinding algorithms, evidently does not come standard on the base model.

So, since it looks like I'm gonna have to roll my own navigation after all, I've been looking into it at work over the past couple days. Found some neat stuff, like this paper (pdf link), which is overkill for my situation (and a little over my head), but super interesting. At this point I have a general idea for where to go next -- just gotta find the time to experiment with it Smiley
Logged

Zireael
Level 4
****


View Profile
« Reply #11 on: February 23, 2018, 08:15:09 AM »

That getting stuck on square shapes thing is a Godot 3 bug methinks. At least I think I've seen it reported on GitHub.
Logged
sand-bird
Level 0
**



View Profile
« Reply #12 on: April 12, 2018, 08:13:12 PM »

This thread ain't dead yet!

I've spent the last couple months being overworked and gearing up to look for a new job (in that order), so I put the game on the backburner for a while. It sucked -- eventually, without even really planning to, I found myself coming back to this thing, even though I still have Actual Resume-Boosting Personal Projects to finish. Anyway, I've been working on this devlog/update thing on and off that whole time, so I apologize if it's a bit scattered. Somehow I managed to organize it into three parts, so there's two more posts coming Very Soon. Now then!



1. TILES

One of the core aspects of Menagerie's design -- and something I'd really love to talk about in depth at some point -- is creative control over your environment; thematically, garden customization is super important. In light of that, I wanted to give the player control over the terrain as well as the objects on it -- let them place grass or dirt or sand or water tiles wherever they want. This seems simple enough, but it turns out it comes with a whole mess of problems and extra design considerations.

Unless you're going for a really old-school look, different types of terrain on a tilemap have to transition into each other. As obvious as this is, it did not occur to me until I actually started drawing a dirt tile next to a grass tile and went "...oh."



Transitioning tiles programmatically is not difficult, but not trivial either. Each tile has to be aware of its neighbors (through bitmasking, usually), and then a sprite is chosen accordingly. Generally, edge sprites are partially transparent, so in tiles where a transition takes place, the basic sprite for the adjacent terrain is drawn first, and then the edge sprite is layered over it.

Without transparency, the number of sprites you'd need to create for this would scale exponentially with the number of terrain types that are allowed to touch. A bare-minimum tileset for transitions is 16 tiles, but when you start accounting for t-junctions and so on, it goes up to a maximum of 256 (2^8, on or off for each of a tile's 8 corners and sides), just for a single type of terrain. For a reasonable middle ground, there's the "blob" tileset pattern from here and here, which consists of 47 tiles.

These each have their own issues. Aside from taking longer to draw, the "blob" tileset suffers from an effect I'll call "layer bias" (or "layer dependence"), which is best explained visually:



This is a map composed of only (ugly placeholder) grass and dirt tiles. The presence of grass or dirt on each individual tile remains the same, but changing the layer order (grass on top of dirt versus dirt on top of grass) changes the appearance of the map drastically. Because edges in the blob tileset are "skinny" and leave transparent space within the tile, there's no way to make a hole in the blob smaller than one-tile-and-then-some, so the tiles underneath appear huge in comparison.

(Note: A designer with the liberty to pick and place tiles out of the tileset individually has ways around this. Player-customizable terrain must rely on autotiling, though, or else the UI would be far too complicated for kids and grandmas, and that cuts down on options.)

The 16-sprite transition tileset, also known as the two-corner Wang tileset, doesn't involve skinny tiles, but it suffers from another issue:



The blue dots are "join points" or "seam points," where 2-corner tiles must meet each other, as this post explains. The blue dashed lines are the borders of the actual tiles, so what you get, visually, is a blob of terrain offset half a tile away from the tiles it's supposed to be "on".

Well, that's an easy fix -- just offset the tilemap so it looks like it's aligned to the grid! Again, fine for a developer who can place individual tiles, but not compatible with autotiling. For autotiling to generate the terrain above, every tile in that 9x9 grid must be grass (over a layer of dirt, of course), except the top-left one. There's no way around this -- you can't even have single-tile strips of terrain when using 2-corner tiles with regular autotiling logic.

Godot's tilesets incorporate a pretty decent autotiling feature as of 3.0, but as with pathfinding, it's not really suited to our use case. Sadly, customizable terrain isn't a core enough feature for Menagerie that it'd be worth the time to engineer a suitably robust solution, so I'm going to table it for now. If I get a chance to come back to it, I'll probably look into using edges or corners to represent terrain data, and drawing the tiles programmatically that way.
Logged

SamLouix
Level 1
*


Solo Game Developer


View Profile WWW
« Reply #13 on: April 13, 2018, 11:07:16 AM »

Keep at it, I appreciate what you're trying to do. Don't be cookie cutter - make it amazing. There's something only you can do. What is it? Do that.
Logged

← Avatar from my  Healing Process: Tokyo. 3 years in so far. Daily dev-log is here. I have advice for composers looking for work, join here, I'll tell you.
sand-bird
Level 0
**



View Profile
« Reply #14 on: April 13, 2018, 03:57:17 PM »

Keep at it, I appreciate what you're trying to do. Don't be cookie cutter - make it amazing. There's something only you can do. What is it? Do that.

Hey, thanks, that means a lot! I'll do my best Smiley


Next up:

2. ASSETS & ART

Every game developer and his dog will tell you to get the mechanics down before you worry about nice artwork. And I tried! But I kept running into situations where I'd have a much easier time making implementation decisions if the right assets already existed. One example is the pathfinding problem: I have a few possible solutions in mind that vary greatly in complexity and implementation, and without a reasonable sample of different objects and monsters, I won't be able to tell which is the best one for the job.

I also need assets to make other assets. It appears there is a sort of "art hierarchy" that determines the order in which assets should be created. (This seems kind of obvious to me now, but it definitely came as an epiphany).

I had a really tough time with garden assets until I realized that the root of Menagerie's art hierarchy is the monster sprites. How big is a tree supposed to be, or a flower, or a piece of fruit? Well, if a small monster sprite (eg. Pufig) is about 20 square pixels, a normal-sized piece of fruit like an apple should probably be somewhere between 10 and 16 pixels wide, depending on how much detail we need to squeeze in there. (Smaller items can be pretty liberally oversized without becoming too cartoonish, cf. the fruits in Tiny Chao Garden:)


I got really good at speedrunning Sonic Advance 1-1 to grind rings for this little guy

Visually, the monster sprites are the heart of the game. They need to be perfect. I think I'm a decent enough pixel artist to make it happen, but it's going to take a lot of practice and trial and error -- especially on the animations. From crunching a couple numbers, I can expect to spend six or seven hundred hours on monster art alone -- given an average of 3 free hours a weekday and maybe 16-20 on weekends, thats 20 weeks, bare minimum. Just monsters, and that doesn't even include concept art!

Anyway, also high up on the art hierarchy is the color palette. I really suck at picking colors, so ideally I'd use a single pallet for the entire game, and keep it as small as realistically possible for consistency and style (128 colors or less is probably ideal).

Since I really suck at picking colors, I went looking for premade palettes, and found a few that I liked: AAP-64 by Adigun Polack, Nature's Embrace by GrafxKid, and Famicube by Arne. Unfortunately, there doesn't seem to be much demand for curated palettes greater than 64 colors or so, and that evidently just isn't enough. So I did some back-alley surgery and spliced those three into a Frankenstein's monster-palette of a hundred-something colors:


The X's over swatches are colors I've used and definitely want to keep. Hopefully I'll be able to whittle away at the others over time.

So far I've found it pretty useful to keep both the palette and my sprite drafts in the same big ol' messy GIMP document; I can colorpick from the palette to experiment with stuff like grass and plant colors (going to need a lot of greens), and refine the palette itself in the process. Once I refine it a little bit more I'll be able to export the palette itself, and work in indexed mode with individual files.

Eventually I'm going to have to buy a real pixel art tool to make animations a little easier, and hopefully there'll be some way to enforce palette consistency across multiple files, such that if I change a swatch in the master palette, it should update every file that index occurs in. (I guess an automated script would do the trick? I could probably write one myself if I had to.) Godot accepts pngs for sprites and couldn't care less how many colors are in them, performance and memory aren't at issue, and probably nobody would notice or care about a couple extra shades, so it doesn't really matter, but... I dunno, there's still the principle of the thing, at least for me.

In the meantime, I've got a whole bunch of UI assets I did before the palette that I need to convert. Here's a before and after of the inventory screen mockup, kept at 1x to avoid magnifying its numerous flaws:


Please forgive the lame placeholder text

(Note: those item slots are 20-something pixels square, which I figure is probably too big. It remains to be seen: this is another case of something depending on yet-to-be-made assets.)

Here's part of the HUD inside the garden, a clock that tells you the time the old-fashioned way (it only has an hour hand because time moves too fast in Menagerie for minutes to be relevant):



Sorry, I know the "main menu is a book" thing is a little cliche. It actually didn't start out that way, but I changed it for a good reason, I swear. Shrug As far as "background info" posts go, I definitely want to do a nice big one about input schemes and UI/UX design, since it's something I've thought a lot about. Let me know if that's something you wanna see, I guess! I'm also planning a post on monster design, since that's most of what I've been actively working on lately; hopefully that'll be the next big writeup after this one.

Logged

bacon
Level 1
*


View Profile
« Reply #15 on: April 13, 2018, 08:14:47 PM »


1. TILES

One of the core aspects of Menagerie's design -- and something I'd really love to talk about in depth at some point -- is creative control over your environment; thematically, garden customization is super important. In light of that, I wanted to give the player control over the terrain as well as the objects on it -- let them place grass or dirt or sand or water tiles wherever they want. This seems simple enough, but it turns out it comes with a whole mess of problems and extra design considerations...


Ah I'm sad you didn't reach a positive conclusion here! I'm having all the same issues and was hoping for a silver bullet. Baking in the transitions as well is also definitely an issue, especially if you want to have customizable terrains.
Logged

CANTATA
sand-bird
Level 0
**



View Profile
« Reply #16 on: April 13, 2018, 09:04:18 PM »

Ah I'm sad you didn't reach a positive conclusion here! I'm having all the same issues and was hoping for a silver bullet. Baking in the transitions as well is also definitely an issue, especially if you want to have customizable terrains.

The more I think about it, the more I feel that for player-controlled autotiling, storing terrain data on the "corners" of your tilemap is the way to go. The last image in my post, with the join points, is a pretty good illustration of what I mean: the player clicks what looks to them like the middle of a tile, but it's actually the corner of four tiles on the tilemap. It sets the value of that corner, and the autotiling logic (which would probably have to be hand-rolled) updates the four surrounding tiles accordingly.

I haven't tested it or anything, but it makes sense in my head Giggle

(CANTATA looks awesome by the way, I'll have to remember to check it out!)

Last one:


3. ROADMAP

So, I took a hot second and wrote down a, uh, wishlist for an extremely minimal vertical slice. I mean dang this is really aiming low. And yet it's still so much:

ASSETS

garden:
  • one tree (seed, sprout, sapling, adult)
  • one bush (seed, sprout, grown)
  • Pufig standing (front and back)
  • Pufig walking (front and back)
  • one flower (seed, bud, flower)
  • one or two pots
  • grass tiles with transitions
  • one or two dirt background tiles

ui:
  • game font
  • buttons
  • clock hud with time and date
  • monster drives (eg. hunger, mood, etc) HUD
  • cursor (idle and "grab")
  • basic (non-shader) hover/select highlights (floor ring)
  • monster/object context menus
  • placeholder title graphic
  • "load game" menu with list of saves
  • basic "options" menu with save and quit to title
  • basic title menu with new game and load game

nice to have:
  • one other monster, maybe just a standing sprite
  • main menu with "options" menu tab
  • basic ui transitions


MECHANICS

garden:
  • camera scrolling (drag, rts-style)
  • cursor snap
  • time-based screen tinting (day and night)
  • grid-based object positioning
  • object states (plants that grow)
  • monster "walk" action (simple pathfinding is fine)
  • monster "wander" behavior that uses the walk action
  • monster "idle" behavior
  • monster memory for behaviors and targets

system:
  • switching from title scene to garden scene
  • in-game clock
  • new game
  • load game

persistence (serialize & deserialize):
  • game time
  • basic player info
  • garden objects & their states
  • garden monsters & their states

nice to have:
  • camera scrolling (wasd, joystick)
  • placing objects
  • an "input mode" setting


So this is what I'll be tackling in the immediate future. Actually, most of these are pretty easy; the hardest ones are probably the remaining assets (especially the other walking animation oh dear), the context menu handling (you'll see), and maybe object states if they give me trouble -- I'll need to figure out a consistent, generalizable format to serialize the state data in (and pray that it's futureproof enough), and that ought to inform how I handle the logic.

This isn't really my favorite kind of post, but I think it's important to do every so often. It'll probably feel good to check off a bunch of these in the next one!

Speaking of, I'd like to take the next update to talk a little more in depth about some aspects of the design. I mentioned monster design, though there's also UI/UX design, including control schemes -- something I've put a lot of thought into, since this game is supposed to be equally compatible with joypad, mouse & keyboard, and touch input. There's also story/world/theme design, which I hinted at with the customizability stuff. If anybody responds with some kind of a preference, then that's what I'll do.

Until then -- thanks for reading! Grin
Logged

Yong
Level 0
***


View Profile WWW
« Reply #17 on: April 13, 2018, 10:44:25 PM »

Your Inventory page looks great Hand Thumbs Up Left. UX/UI is something I struggle a lot with so I'd definitely look forward to a UX/UI post.
Logged

sand-bird
Level 0
**



View Profile
« Reply #18 on: April 20, 2018, 02:25:45 AM »

Your Inventory page looks great Hand Thumbs Up Left. UX/UI is something I struggle a lot with so I'd definitely look forward to a UX/UI post.

Thanks! I'll go with that then -- hopefully it can give you some inspiration! Grin

In the meantime, I wanted to write up a short SURPRISE POST on something I've been working on that I'm pretty excited about: data-driven conditions!

For Menagerie to be extensible -- both for modding and for my own development -- it needs to be as data-driven as posible, so I've been spending a lot of time lately working out the data structures for stuff like monsters, items, NPCs and so on. Some of this is immediately necessary for saving and loading game state, which is what I'm officially working on right now, but I'm also trying to get ahead of the curve on planning out the rest of it.

Here's kind of a dumpy example of a datafile for a monster:

Code:
{
  "id": "pufig",
  "width": 22,
  "height": 20,
  "evolves_into": [
    {
      "id": "pufine",
      "condition": {
        ">": ["@patience", "@aggressiveness"]
      }
    },
    {
      "id": "pufrit",
      "condition": {
        ">": ["@aggressiveness", "@patience"]
      }
    }
  ],
  "traits": {
    "appetite": 2,
    "iq": 1,
    "aggressiveness": -1,
    "openness": 1,
    "sociability": 1
  }
}

The real thing will have way more stuff in it, but that's the gist. Once it's all set up right, to add a new monster, I (or a modder!) can just drop a file like this in the right folder along with some sprites or whatever, and that's it -- the game crawls the directory and incorporates all the data automatically. It's gonna be pretty cool.

Anyway -- conditions! Which items an NPC will be able to sell you, which requests you can get, which text snippets will show up in your weekly letters, which other monsters your monster will be able to evolve into, what the weather is going to be like tomorrow -- all of this stuff is conditional. Pretty much all of this stuff is also stored away in data files, so the conditions need to be too.

So, according to that datafile, Pufig can evolve into Pufine if its patience is greater than its aggressiveness (these are traits, which dictate monster behavior and which I promise I'll write a huge essay about sometime), or Pufrit if its aggressiveness is greater than its patience. That's a condition:

Code:
{ ">": ["@aggressiveness", "@patience"] }

The structure is just like JsonLogic, but with some changes (really simplifications) specific to my use case. For example, to mark an argument as a variable, Menagerie's conditions simply use a string prefixed by one of two sigils, $ or @. (String arguments without a sigil are treated as static and evaluated as-is.)

The @ sigil represents a property local to the entity described by the datafile: when the condition is processed, "@patience" will resolve to the patience value of the specific monster in question. It can also chain properties, so "@mother.patience" will resolve to the monster's mother's patience, and so on. (Of course, if the person writing the datafile makes a typo or uses a property that doesn't exist, the condition resolution will break and possibly crash the game -- I could probably implement some basic file-checking to help mitigate this, though since all this stuff is resolved during runtime it will never be waterproof. I'll likely just stick with detailed docs and a warning.)

The $ sigil represents a global property, like the player's funds or the current day of the week. This one's actually gonna take some extra finagling, since internally, most such properties are less convenient to access than the kind of identifiers I'd like to expose. For example, Menagerie has a Time singleton: you can get the current day of the week from anywhere in the game through Time.day_of_week, or the current day of the month through Time.day. However, these are integers that start at 0, so on Monday the 5th, Time.day_of_week and Time.day would be 1 and 4 respectively -- not the most intuitive.

A better example: a request that becomes available when you have a certain type of monster in your garden. Currently, the garden scene isn't a singleton like Player and Time, since it has so many children (monsters, objects, items, terrain tiles) that are actual instantiated nodes (Godot for "thing what exists in the game object hierarchy"). The condition for such a request would look something like this:

Code:
{ "in": ["pufig", "$garden.monster_species"] }

But that sort of information isn't stored in a variable anywhere, let alone one called monster_species in garden -- it'll have to be fetched through a function, first.

In other words, rather than directly correlating to object properties, most (if not all) of the global condition arguments will end up being manually-defined aliases for functions in the game code. Which is fine, really -- it's less decoupled than I like things to be, but it also means I get to write even more documentation, which I actually secretly enjoy.

Anyway, this is all working great already; just gotta add those aliases for global identifiers as they become necessary. Feels nice, man -- "completing" a piece of functionality is always really satisfying, even if it's not something users get to see. Beer!

On that note, 'til next time: THE USER EXPERIENCE.
Logged

sand-bird
Level 0
**



View Profile
« Reply #19 on: August 04, 2018, 05:22:09 PM »

Hello again!

I've still been working on stuff. Lots of stuff! All different kinds of stuff... just not very much UI stuff. Periodically I think, "hm, I should probably write a devlog about this," and then I remember that I promised that the next post would be about UI, and there's not much sense in writing a post about UI without a functioning UI. So I end up not writing anything.

On top of that, having mostly written big, fat, exhaustive multi-part posts, I've come to both expect that from myself and dread having to set aside all the time and effort it requires. And honestly, it wasn't a very smart strategy in the first place, anyway. The people want consistency, not walls of text! So heck it! Time for a different approach. These things always stretch longer than I planned them to, but I will at least try to keep it shorter, sweeter and fresher from now on.

There's a lot to catch up on, but I have the memory of a goldfish so let's start with today.



These are emotes! Emotes are super important for giving feedback on what a monster is thinking. Most will be standalone, but some emotes will be chained together in sequences. This particular sequence is one I'm really psyched about: a composure roll.

TIME FOR A DESIGN POST

The most obvious aspect of a monster's status is its drives. These are your standard Sims-style meters, and we've got four: BELLY, ENERGY, SOCIAL, and MOOD.

Drives are necessary but boring, so monsters also have traits. My monster design currently includes about two dozen of these, though I expect the number to fluctuate as I find opportunities to consolidate them, or discover a need for new ones.

The design philosophy here is: every trait should have at least one noticeable effect, and just about every aspect of behavior should be affected by traits. It's supposed to work behind the scenes, mostly -- there's actually no accurate information on your monster's traits inside the game. There are ways to get a rough idea of them, but you never see numerical details.

Anyway, one of the more important traits is called composure: it affects how much control a monster has over its own mood. Whenever something upsetting happens to it, like getting bullied or going hungry for too long, the monster's MOOD takes a penalty -- I call this a "mood hit". And any mood hit has a chance to proc a composure roll.

The monster will emote with a sad face when it takes a mood hit, of course. But sometimes, instead of getting upset, it'll try to compose itself and shake off the hit. When this happens, it goes through a different sequence.

Step one is that wibbly-wobbly "waaah" sort of face. If its composure really sucks, it might just give up here, and segue into the normal sad emote. But usually, it'll transition to a "determined" emote, hold it for a moment of implied internal struggle, and then display either a "proud" emote if it passes, or a "dejected" emote (below) if it fails.



All this will be animated someday, which will make the transitions look super cool and polished and also help convey emotion better. I'm pretty happy with the static faces so far though!

Not all traits can be this flashy, of course. So why does composure work like this, instead of just quietly decreasing the frequency or the magnitude of mood hits? The obvious answer is because it makes the monster seem like it's got a lot more going on it its head. That's a big part of it, but there's one other reason.

If you see a monster attempting a composure roll -- even if it doesn't succeed! -- you can act to encourage (or discourage) it, which will actually change its composure trait with enough time and repetition. (Another design goal for traits: they must be able to be influenced to some extent by player actions.) I call this mechanic discipline, and it's a big part of the design, though there's still a lot of other stuff to finish before I can actually implement it.
Logged

Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic