Godot Version
4.4.1
Question
So I wanna try creating a small automation game puzzler all about belt weaving. the problem is that there’s not really any resources or guides on how to implement this stuff. As such I was hoping someone here might be able to point me in the right direction or at the very least help me bounce off ideas. In essence I want my game to have 3 things.
- Conveyor belts, complete with all the usual amenities like splitters, curved rails, and undergrounds. These are the things I think I’m the most unsure of how to handle. Thankfully my scope is gonna be pretty small so I don’t need something complex or super optimized, just something that works.
- Assemblers: These I think I have a decent idea on how to handle. just an inventory and a timer basically. my main question is “how do I put the outputs back on the belt”.
- dispensers/drop-off points: these I think will also hopefully be super simple. my question is similar to the assembler one where it’s 'how do I put stuff on/take stuff off the conveyor belts"
I don’t know if any of my ramblings made sense here but if someone would mind helping me find the right direction then that’d be greatly appreciated
I’d suggest starting this as a 2D project, to keep the complexity down. You can always take it 3D later when you’ve got it working, or do 3D in the sequel. Or stay 2D forever; whatever works for you.
I’d suggest using TileMapLayer
for building/conveyor placement. That gives you a grid layout to work with. Items on the conveyor could be drawn with sprites, or you could float a label over each conveyor saying something like “[icon] steel beams 30/sec” or whatever representing the flow on the conveyor. Maybe do both; it makes life easier for the player in these factory optimization games if they don’t have to eyeball the bottlenecks. To start, though, I wouldn’t draw stuff moving on the conveyor, I’d use “pipes”.
I’d probably be inclined to separate the map representation of the parts from the logic that handles flow. When the player lays down another conveyor belt section, add that to the map, but also add the appropriate length/connection to a simplified flow graph you can use to model production. The flow graph would probably be edges (conveyor belts, pipes, whatever moves stuff around) and nodes(assemblers, dispensers, storage, which modify or hold stuff). So you might have something that looks like:
- mine_1
- produce 1 ore every 0.33 seconds
- next ore in 0.02s
- output connected to conveyor_1
- conveyor_1
- move 1m/sec
- 22m long
- contains [(ore, 0.33m), (ore, 0.67m), (ore, 1.0m), …]
- input mine_1
- output smelter_1
- smelter_1
- convert 1 ore to 1 ingot every 0.5 seconds
- input buffer 99 ore
- output buffer 0 ingot
- next ingot in 0.24s
And so forth. The simplified graph model should make it relatively easy for you to walk the graph updating things without having to concern yourself with the graphical representation, and then you can have a post-update pass that takes care of drawing the current state.
Because it’s a graph, it should make things like “how do I put stuff on the belt” easy; when you’re looking at a conveyor, the logic goes something like:
if is_instance_valid(input): # Are we connected to anything?
if _ready_for_next_input(): # Is it time to take something?
if input.buffer.size() > 0: # Is there something to take?
# Remove it from input.buffer[]
# Add it to contains[] with a position of 0m
_take_item_from_buffer()
1 Like
Alright I know this is a late replay but I just kind of need to talk out loud on how to do this cause my brain is just kind of stuck right now now that I’m actually working on my automation game and I need someone to help unstuck it if that makes sense. Because I think what’s going on is that my brain just can’t comprehend the idea of a tile in a tilemap doing something if it’s not a scene if that makes sense. Like it is just utterly flummoxed by that idea.
One idea I had, just to throw it out there, is to have the items basically move themselves. like after 0.2 seconds or whatever I can have each item “check underneath itself” through like like a reference to the tilemap and something along the lines of tilemap.local_to_map(to_local(self.global_position))
.
I would just need someway for each tile to convey what it’s “forward direction” is and again for some reason my brain just can’t figure that.
sorry if this was kinda rambley, like I said my brain is just not agreeing with me right now.
I’m going to assume this is 2D, but it extrapolates to 3D…
If you want to do actual items on a conveyor belt, maybe what you want to do is to generate a Path2D
along the conveyor belt, and items can use PathFollow2D
to move along the conveyor. You’ll need some logic to keep them apart (either collision or some simple distance mechanism), but it ought to work.
You’d have to regenerate the complete path for a conveyor belt if the player edits one of the conveyer elements, and possibly even merge/split conveyors and paths if the player is messing around in the middle of the belt. It should just be a matter of stitching together predefined line segments, though. If you’re tile-based like Factorio, each conveyor tile would have an associated path segment you (as the programmer) could rotate and place with the tile. If you’re making arbitrary Satisfactory-style 3D noodle conveyors, you can pull the path segment from whatever you did to generate the visible geometry.
With that, you could have items move themselves, but you could also just have each conveyor contain an array of what’s on it. If each item on it has an attached PathFollow2D
node, each conveyor could loop over the array of contents and set positions fairly efficiently.
Thinking about it, having objects move themselves is likely to cause problems. Not unsolvable problems, but I think the solutions will mean more code complexity:
- if you have conveyor belts that move at different speeds, an object that moves itself is going to have to find out how fast it should be moving (and where) depending on where it is
- object/object collision becomes a giant whole-world billiards simulation rather than a per-conveyor beads-on-a-string simulation
- the ends of the conveyor belt get weird; what adds objects to a conveyor, what removes them, and where do they go when they’re “in” a processing step between conveyors?
- if you ever need to optimize the game, being able to treat an entire conveyor as a unit gives you much more latitude to do things like attenuate the update rate based on distance from the camera