Released: Factory Farming

This is a development thread for my upcoming automation game, now titled Factory Farming. The game will be a simplified "Factorio clashes with Stardew", when you will exploit the land using automation to maximise throughput; maximise profit.

factoryfarming_a1_tease

I am more of a build-it-then-release it kind of developer, but as the performance of this game is going to be so very dependent on the hardware, and as I don't expect to be able to get an actual Playdate any time soon, I will post snapshots at various points so as to be able to get some continued feedback on the performance.

In Alpha 1 ( Efficient sprite animation? For a large number of sprite instances - #9 by ncarson9 ), I experimented with the Playdate's sprite system on its own, and saw how far I could push it. The answer: not nearly far enough for my goals! But this was not unexpected. The sprite system is a general-purpose tool, it is obviously not optimised to form the backend of a factory simulation...

It's all in the chunks

In Alpha 2 I wrote a proper backend to handle the sending of data to the sprite system and the simulation of the factory. The world gets split into chunks, with sprites in the current and surrounding 8 (when zoomed out), or current and neighbouring-corner 3 (when zoomed in) chunks are delivered to the sprite system and simulate (or "tick") at a fast rate of 16 'regular' ticks/sec.

To balance performance, the sprites for individual conveyors (which are animated) only get added when zoomed in. When zoomed out, all of the graphics except for the moving cargo sprites are baked into the background images.

The rest of the map outside this small region is kept out of the sprite system, but still ticks at a slow rate of 2 'big' ticks/sec. Hence the factory still operates outside of the visible range, just at a lower granularity. The simulation is hence also not in "lockstep", unlike Factorio proper. This Alpha 2 build can still be found on discord in the testing channel ( Discord ).

Adding I/O & Farming Game Fundamentals

Now I am ready to post Alpha 3, the game most importantly now has an automated saving and loading system - so you don't have to start from scratch each time! The game's systems are also expanded to support building more than conveyor belts. Now some crops, a harvester building and a filtering conveyor splitter can all also be placed / planted too (Note: the filtering splitter filters based on the first crop-type to pass over the tile). Hence now the fundamentals of growing crops and moving them around are in place. There is also a box to "sell" crops, though nothing can be subsequently bought yet.

Alpha 4 comes shipped with a small world I was messing around with, but you can reset it from the system menu. You can also manually save and load from here, though you should not need to.

I will try and maintain save-compatibility moving forward, but this obviously cannot be guaranteed at this point.

The world is little less uniform in Alpha 3+. with some different ground types, rivers and lakes. Also to stress: no graphics are final, and I am aware that the visual readability is rather poor in places.

Summing it up

Factory Farming is written entirely in C (and is open source: GitHub - timboe/FactoryFarming ), with the goal of supporting the simulation of good-sized factory setups. I want to support at least 2000 conveyors, hopefully more. Target FPS is 32, the simulation speed is currently tied to the FPS (and it would be tricky to decouple it).

Alpha build UI: Menu items displayed on the right, info ticker along the bottom

  • Crank: rotate building in Menu and Placement modes, or zoom in & out in Wander mode.
  • A: Enter 'Menu Mode' from 'Wander Mode', select current item in 'Menu Mode' and enter 'Placement Mode', place building or crop in 'Placement Mode'.
  • B: Exit from 'Placement Mode' to 'Menu Mode', and from 'Menu Mode' back to 'Wander Mode'

Next Steps: I just started Trello to keep track of what needs doing.

The latest public build is Alpha 6

7 Likes

@timboe The Alpha 3 build you linked here doesn’t work when I sideload to my Playdate. It’s a blank screen for a bit, then the white light on the top button goes on (I think this means something… like out of Memory?, but I’m not sure if it can have many meanings), and then the Playdate crashes. Not sure if others are experiencing this too !

Thanks @fosterdouglas

This is possible... in the sim I have a few MB free, but maybe this is cutting it too fine.

I will post an alternate version later with a much smaller world to check if this is the issue.

EDIT: Here's another build with an 8x8 world rather than 16x16. I tried to fill it up with >1k conveyors again - this time they pretty much cover the map.

The memory requirements are, unsurprisingly, around 25% at this level.

If this is OK then in the future I can try and find the sweet-spot, as this map is overall a bit on the small side.

1 Like

Tested it out recently, it all seems to work pretty well.

One piece of unsolicited UX feedback, it took me a while to figure out how to switch the “directions” of each of the tiles. I eventually saw that you can change it in the side menu or also use the crank to switch the tiles while place them, but that feels pretty clunky. I’d love to see a more intuitive way to handle this. Maybe, as one example, if you hold B and hit the d-pad, the “placing tile” direction changes to the d-pad direction pressed, then release B to move/place again as normal. Just one of many potential options.

Similarly, maybe while holding B outside of Menu Mode or Place Mode, the character speed is increased to make getting around snappy.

Overall though, very cool ! Didn’t encounter any crashes of note. A tiny bit of slowdown in dense areas, but nothing below 24fps that I saw.

Thanks @fosterdouglas for the input - all very useful stuff.

There will be a new alpha soon with an overhauled UI replacing the dev UI in V4, in the new UI the only way to rotate pieces is the crank. I need to find a good way to communicate this to the player... There will be a tutorial, I will mention it there. Let's see if that suffices.

Interesting idea about holding B. Holding B to get a speed boost when walking about - yes, the B button currently has no purpose when in "wander mode". Giving it something like this sounds good (especially as I was considering slowing the player down a bit vs. their speed in the alpha builds).

Having press-B to exit "placement mode" vs. hold-B to enter another mode, this I'll have to try and see how intuitive it is. I am also not happy about the klunky object placement, though I put this down in part to the very simple player movement code. I intend to replace this a proper one which will allow finer movement control from rest, and then improve the placement controls on top of this.

1 Like

Generally speaking (both in HCI/UX design and suggested in the Playdate accessibility docs), it's good to give the player as many options as possible for input unless the input is specific to the gameplay (like in Crankin's Time Traveling Adventure, for example).

That said, you're making a relatively complex game, and the Playdate has only so many buttons... so I get it !

Excited to play with the new alpha, let us know when it's ready to test out.

1 Like

Moving this thread into the Games forum, given the updated classifications.

Alpha 6 is ready to be shared (5 is skipped, had a bug).

Alpha 1 was messing with sprites, Alpha 2 was the proof of concept & demonstration of scalability, Alpha 3/4 was the expansion of the game's internals systems and addition of the save/load mechanics, and now Alpha 5/6 further expands on the game's systems and contains the proper UI system which replaces the temporary dev-UI from the previous iterations.

v6 is now up to 7,039 lines of MIT licensed C code (source above).

New in Alpha 5

World & Navigation

  • Bigger world. v3 was 16x16 but crashed on device (RAM...), v4 was 8x8 but felt small. v6 is 12x12. Happy middle ground?
  • World wrapping, the playing world now wraps visually seamless as well as mechanically seamless in both directions. (The visual wrapping was much harder than the mechanical wrapping, which was in essence just teleporting things)
  • Hold B to move faster (nice idea, thanks @fosterdouglas for the suggestion. Will be kept when the player controls are overhauled later)
  • Lakes and rivers are no longer impassable, but do prevent building (except Pumps) and have a movement penalty instead.
  • Addition of impassable rocks and tree trunks, which also block building. These are placed sparingly.
  • Classification of tile dampness into Dry, Moist, Wet or literally-Water.
  • Classification of tile ground into Sandy, Chalky, Clay, Peat, Loamy or Silty soil, Lake, River or Paved.

User Interface

  • Main Player UI: Press A to access the inventory. Select a Building to place down/plant, Cargo to place down, or a Tool such as "Pickup"
  • Shop UI. Press A when standing next to The Shop to access. Purchase unlocked Crop Seeds, Extractors, Conveyor Bels, Factories and Utility items.
  • Sell UI: Press A when standing next to the "Sell Box" (not final name...) to manually sell any Cargo you have in your inventory.
  • Right hand permanent UI: Re-tasked to display player's money and number of items remaining when placing buildings.
  • Bottom permanent UI: Re-tasked to display details about the tile the player is standing on: Ground wetness, soil type, building on the tile, cargo on/transiting through the tile.
  • New Game Tutorial: 9-stage tutorial to cover up to the building of the first factory. Will be possible to disable this in future updates.
  • Pickup Mode: New mode - collects cargo from nearby tiles and places them in the inventory.

Buildings

  • Work towards Crop likes and dislikes, based on soil dampness and ground type. Actual buffs/debuffs not yet active.
  • New Conveyor: "I" Filter. Added along side the "L" Filter to harmonises the Filters with the Splitters.
  • New Harvester: Pump, must be placed partially over water. Produces buckets of water (no use yet)
  • New Harvester: Chalk Quarry. Must be placed partially over Chalky Ground. Produces chalk.
  • Updated Harvester: Crop harvesters now come in 7x7 and 9x9 variants
  • New Building type - Factory: Factories consume up to 5 Cargo types as "Ingredients" and combine these into an output product (Cargo).
  • New Factory: Vitamin Factory. Consumes Chalk and Carrots to produce low-quality mass-produced vitamin tablets (the profit mark-up is wonderful, however!)
  • New Building Type: Utility, for the items which defy neat classification!
  • New Utility: Well, acts as a place-able water source. Creates Wet and (further out) Moist soil in the vicinity.
  • New Utility: Conveyor Grease. Conveyor belt upgrade material, speed x2. Only one application possible per belt. Can be placed on existing conveyors or added automatically to newly placed conveyors (settings menu to enable this feature not yet added).

Note on saves: I was overly optimistic above regarding preserving backward compatibility of saves (at least while the game is still in alpha, and I need to change things around the backend often). So please note that launching v5/v6 will sense and automatically delete any save file present from v4! Without this auto-delete, the game would crash when trying to load the old save.

Next: I will publish a "big factory" save game file for v6 soon, for people who want to look at all the items whizzing about but don't want to have to do the building. The UI work is not finished, there is still an "Inspection" UI and the Setting menu to be added. But soon it will be the time to start massively expanding on the available Crops, Factories and Extractor types beyond the current demonstrators. Also coming soon is the Storage Box Utility object, to act as an item buffer, or store.

After That Player movement and object placement overhaul, graphical consistency overhaul, sounds and music, enter beta for polish + juice + balance + play testing.

FactoryFarming_Alpha_6.pdx.zip (132.0 KB)

GIF showing some of the new menus and the Vitamin Factory.

factory_farming_v5

3 Likes

I've shared my feedback in Discord but I need to say.
The performance you've achieved here is impressive!
This game has quickly moved to the top of my list of most anticipated games.

Can't wait to see what it becomes.

1 Like

About time for another update. Does feel now like a full playable beta is not too far away.

As some of the change log could start to spoil mid-game revelations, I am starting to use the spoiler tag below.

Factory Farming Alpha 7

World & Navigation

  • New physics based player controller and player sprite.
  • Updated landscape graphics.
  • Juice: Screen shake
  • Asynchronous save & load system - less likely to crash the playdate for long save or load operations.
    • Save first to temporary file, crash during save will not corrupt the previous save.
  • Hold B + D pad as an alternate to the crank when rotating buildings. (suggestion from @fosterdouglas)
  • Major new midgame system: 8 different plots of land with different soil & world gen properties. Plots Manager to unlock and move between plots, Exports Manager to handle the exporting of Cargo and Imports Manager to handle the importing the Cargo into other plots
    • Only one plot may be loaded into memory at any time, but unloaded plots will sill export resources which can be imported into the loaded plot

  • Background music

factory_farming_v7_plots

User Interface

  • Animated title screen, now supporting three different save slots.
  • Game paused info box.
  • Main menu with game settings, save/quit, overview of controls and credits.
  • "New Building" UI, whenever you visit the shop after having unlocked something.
  • Crank to follow conveyor!
  • Resizable Pickup & Destroy areas with the crank
  • Right hand permanent UI: Added Shop Compass and new building unlocked notification icon.
  • Mid game tutorial covers moving between plots of land and exportin/importing items.
  • Inspect mode: Provides many details and statistics on the current tile.

factory_farming_v7_menus

Buildings

  • Full crop soil and moisture system with bonuses and penalties.
    • Including lake-only and ocean-only plants

  • Major content update - covering much of the games core progressions systems. Balance and pricing still to be added.
    • 14 Crops
    • 6 Extractors
    • and 31 Factories
  • New Utility: Sign - label your crops!
  • New Utility: Path - movement is faster on paths
  • New Utility: Fence - cosmetic
  • New Utility: Landfill - can be used to cover water, can be built over.
  • New Utility: Obstruction Remover - clears "Obstructed Land" tiles, allowing for them to be built on.
  • New Utility: Bin - deletes unwanted Cargo.
  • New Utilities: Storage Box & Buffer Box, used to manage the flow of Cargo around the map.
  • New Utility: Retirement Cottage - ends the game

factory_farming_v7_utility

4 Likes

Almost forgot the line count! Alpha 7 comprises 11,566 lines of code, that's +64% lines compared to Alpha 6.

Note: No public build of Alpha 7 being posted here, but one more playtest is expected.

2 Likes

Factory Farming just entered Beta! Meaning the game is complete and playable. Next comes more playtesting, more tuning and more polish - but the initial release is now in sight!

The full change set is Comparing Alpha_7...Beta_1 · timboe/FactoryFarming · GitHub

Summary of what's new:

  • Updated art. All placeholders are now replaced (some art still not final)
  • Updated player animation + controls when in water & on paths
  • Updated end credits
  • Updated "What next" box when game is paused
  • Updated fence placement
  • Sound effects added
  • Music volume control added
  • Full game progression path added
  • Cheats added
  • Added factory recipes & some flavour text
  • Added various end-game Cargos and Factories
  • Destroying now returns some % of the building/plant's value (currently 75%)
  • Values set for all prices, unlock thresholds, make/grow times. Mix of manual and guided algorithmic progression.
  • Hold B + D-Pad alternates for all Crank actions.
  • Addition of Multiplier at the Shop & Sales to make buying/selling large numbers of items faster
  • Moved spawn point to the centre of the world rather than the top-left (as far away from the seams as possible)
  • Refactored world's ground tiles save format (Alpha build saves are not compatible :frowning: )
  • Turned down screen shake
  • Bug fixes in Conveyor placement / replacement / upgrade / refund
  • Bug fixes in Conveyor Cargo rendering
  • Bugfix: Factory production time should not reset upon new Cargo being added.
  • Bug fixes to I/O systems

Beta 1 comprises 14,023 lines of code, a 21% increase over Alpha 7.

A quick tour of part of the first factory which I managed to build up all the way to the end of the game.
(GIF compressed to 16 FPS, game targets 32 FPS on device)
factory_farming_b1_tour_small

2 Likes

Hey! Really enjoying Farming Factory beta. Nice work! I tried joining the discord channel linked in the first post but it didn’t seem to work. Any tips?

Hi @pietvanzoen - sorry, missed this!

This moved over to here: Discord when the discord re-did its channels.

I am continuing to playtest the game without using cheats, adjusting the balance as I go. Going a bit slowly but I'm making progress here...

With big thanks to some bitmap code from @Daeke you can now take pictures of your factory :open_mouth:

I had thought that I'd filled up this world in my playtesting, but looking at it like this I see there is still room for some more industry here, will get on with filling in the gaps...

7 Likes

So the playtesting and balance-as-I-play is going well, I'm over 16 hours into this no-cheats playthrough and the end of the game is in sight now (if it were factorio, it'd be similar to having built the launchpad - and now needing to fuel it etc.)

Something I noticed with these large factories such as the one above was something was not quite right with the off-screen simulation. As a reminder: the on-screen factory small tick updates 16 times a second, while the off-screen factory big tick updates only twice a second (but the update is 8 times as large, to compensate).

The factory was always functioning, but running around it you could tell that items were not propagating around the conveyors as expected.

To debug I switched everything to the big tick twice-a-second updates to be able to see what was nominally going on in the off-screen parts, the main issue looked to be with the heavy use of mid-game fast conveyor belts which move cargo at two tiles per second, so exactly one tile per big tick.

Because each conveyor is updated in turn, depending on the direction the cargo was moving it could get moved many many tiles in just a single big tick - i.e. if the conveyor belt pieces were iterated over in the same order as the cargo was moving. As seen here in this loop where the chalk seems to teleport from the top left of the cycle down to the bottom right in an instant.

playdate-jumping

So some belts (E to W, S to N) were moving things normally, others (W to E, N to S) were zipping them around at amazing speed. And it all depended on the direction the belts faced. Not great.

The solution was to flag the target conveyor with the frame number when moving a cargo between tiles. Then when iterating over the conveyors, we skip any conveyors we find which are flagged with the current frame number.

This was super simple and worked perfectly.

playdate-steady

Unfortunately though... now I had another, nastier problem. How to move a packed belt? We want to move each cargo by one tile on each big tick, but a cargo can only move if its destination is free. For two cardinal directions it works naturally. But for the other two we end up only half-filling the belt!

playdate-cardinalissue

The current solution here is a bit more extreme, and I'll need to check its performance on device.

During the iteration phase over the conveyors, any conveyor which wants to move its Cargo to a currently occupied tile registers a Desire To Move in an array. Then, after all conveyors have been updated, the Desire To Move array is iterated over in reverse order and we attempt to move the Cargo once more.

The ones which still cannot move are saved into a second array, which gets iterated over next: either move or save back into the first array...

The procedure is iterated, alternating between the two arrays, until either a) we only moved 0, 1 or 2 Cargo in the previous iteration or b) we have made 8 iterations total. These numbers were chosen to try and balance the CPU load of the function. Here is an excerpt from the debug logs from this running on a single big tick for the above factory, 6 iterations were made on this frame.

A Iteration: moved 322 of 865
B Iteration: moved 33 of 543
A Iteration: moved 60 of 510
B Iteration: moved 7 of 450
A Iteration: moved 21 of 443
B Iteration: moved 2 of 422

With this in place, everything off-screen is back to moving as was intended! (At least, for the vast majority of the Cargo. Most of the 422 Cargo not managing to move here are likely genuinely stuck on a blocked belt, continuing to iterate to zero Cargo moved typically only requires a few more iterations)

Shown here with small tick turned back on in the vicinity of the player. The belts feeding in from far off-screen are all delivering items at a constant two Cargo per second from all four directions.

playdate-fixed

I'm now of course wondering if there was anything more efficient I could have done to fix this particular issue...?

4 Likes

Next milestone complete - I've finished my first full run through the game!

Total time for this balance-the-game-as-I-go playthrough? A little over 23 hours! And I knew exactly what I was doing. I'm glad I stopped adding content when I did... It's ended up longer than I anticipated.

factory_farming_final_time

Few residual things left on the trello to sort out which came up during the playthrough, but it seems like the end is in sight now.

I'm going to post my final world I built up over almost a solid day of gameplay, but note this could be considered a big ol spoiler so I'll flag it as such

4 Likes

Now at release candidate 4, there have been a number of additional quality-of-life suggestions and fixes

  • Fixed bug getting stuck walking after an auto-save
  • Updated sound effects on options which don't toggle any more
  • Demolition with 90% cash-back mechanic is replaced with Deconstruction -> this returns buildings/crops/utility items to the player's inventory
  • Prices also update in the shop or sales with crank buy/sell multiplier
  • Buy/sell multiplier resets on exit of the shop / sales, and no longer cycles
  • Made the screenshot and load procedures asynchronous (generation and saving were already asynchronous), added progress display to saving/loading/generating/screenshotting.
  • Removed auto-save on lock and exit, could not guarantee save within the allotted 10s window.
  • Optimised sprite creation for cargo
  • Finished game balance changes and text
  • Updated some conveyor belt graphics for better clarity

I also already binned the "Desire To Move" system I posted about a little over a week ago in favour of a slightly faster and hopefully an overall better solution.

The quick recap of the problem to solve is how to move cargo from A -> B, and from B -> C when A and B are both occupied and C is clear. It works when we first move from B -> C, then move from A -> B, but what about if we happen to iterate over A before we iterate over B? What if it's not A -> B -> C but is instead A -> B -> ... -> X -> Y where there is cargo everywhere except for Y?

The new solution is to harness the power of recursion! If A wants to move to B, but B is blocked by another cargo, then A attempts to call B's update function (there is still code in place from before such that each entity will only run its update function once per tick). B can then try move its cargo into C, or if C was also blocked it could recursively call C's update function, which could call D's etc. etc.. This cascading call will snowball down the conveyor belt until it reaches a dead end, or it reaches a point where the cargo can move into an empty space. At this point the stack unwinds, and as it does so each of the cargo move forward one tile into the newly freed space.

I need to figure out what the stack size is on the PD, but I also set a hard-limit at a recursive call of 128 levels deep which should be pushing something like 1 kB on the stack. Hopefully safe, to be tested...

This alternate approach came with additional bonuses:

  • I could also wire in sources and sinks of cargo to the system. Sources (harvesters, factories) are able to start a recursive call into a chain of conveyors in order to try and free space to place a new item. Sinks (sales depot, factories) are able to receive (but nor propagate) recursive calls - allowing them to consume a cargo and leave space for another to be moved onto the tile.
  • Conveyor splitters only cycle through their outputs if the output is free, but it was hard to know if a given output was free (for the same reason as above). Now after a splitter has moved an item, it can make a recursive update call down the next output in order to check if it is free or not. This makes the splitters work much more "as expected" rather than often taking more than one item before moving to the next output.

It also has at least one downside, a recursive chain starting off-screen (where the updates are infrequent but large) can end up cascading down and finding an empty spot on-screen, causing the visible end of the stack of cargo to lurch forward by one tile! So far this has happened pretty infrequently, though I'm considering what I can do to keep this recursive update method only operating on the off-screen parts of the factory...

My non-device testing suggests this solution is around 1/3 faster than maintaining and reverse-iterating over an array of conveyors whose cargo wants to move, but cannot due to being blocked. With this solution there is no additional chunk of code of logic to be processed after the loop over buildings, but each building can now receive multiple update calls in a given tick (even though they will only action the first, and will return quickly for the later ones).

RC4 is currently under testing over on the discord, with the goal of better stress testing the megafactory on-device. The megafactory was the next thing to be made after the factory posed above on Oct 19th, I wired the screenshot feature into autosave for this one to get a nice time lapse.

factory_farming_timelaps

6 Likes

Nothing to report from the last month, the game is 'done', but I've been hesitant to release (for money) a complex game like this which is trying to push the PD to it's limits... without having personally given it some proper testing on the actual hardware.

The community has been great in providing testing support, however there is a limit to what can really be achieved this way.

So, the time had come - I fired up eBay and... Hello PlayDate!

I already found one must-fix and a few would-be-nice in the first minutes of playing on device.

More to follow!

4 Likes

Cool! You really went the extra mile to test then. Congrats on finishing it, looks neat!

1 Like

And it's finished! :tada:

:factory: :corn: :factory: :corn:

I only needed Sat-Thu with an actual playdate in order to perform the final performance checks, on-device debugging and gameplay testing. While the vast majority of the development went fine on the simulator, having the physical device was invaluable to bring the project up to publication quality.

Some of the things which got updated in this last week:

  • Too many sprites were being added to the render list in the UI, all possible sprites from all UIs - totalling over 800! This tanked the framerate on the hardware. Fixed by only adding the sprites for the current UI screen, and by not adding cargo sprites when a UI is showing. This keeps the number of sprites at around the 200 level.
  • Re-rendering surrounding chunks on change was optimised to only draw the minimum number of chunks. The music is also paused while the water table is re-computed (e.g. wells)
  • Prevent recursive slow-tick update calls from recursing into a fast-tick area (near the player)
  • Disable auto-lock on device
  • New option: auto zoom-in on move.
  • Fix an unsigned vs. signed int visual glitch - only visible on device!
  • Fix printing of floating point numbers, snprintf with %f does not work on device!
  • Fix riding a conveyor over x=0 or y=0, did not work on-device.

Device-specific bugs asside, performance was the key thing to test on the physical hardware.

The simulation performance is good! Only in the largest factories is a small slow-down apparent from the execution of the simulation. :+1:

Too many sprites on-screen will drop the framerate however, especially when the player is moving too. This can happen in areas with lots and lots of full conveyors, but the problem goes away when zoomed-in (which renders 2x2 instead of 3x3 chunks), the new Auto Zoom-In When Moving option can then keep the framerate always high, even in dense parts of the factory.

Release V1.0 is available now on itch: Factory Farming (Playdate) by timboe

5 Likes