Farm with Code / JavaScript
Welcome to Farm with Code
In this game your task is to program a drone so it does farming and earns money for you. Epic battles, challenging monsters, amazing graphics, nostalgic music - all of these you'll find in some other game. In this one you'll write code in JavaScript.
This game is not for everyone: it requires you to code, which not everyone can (and probably not everyone wants after a 72 hours of jamming) and it will take a relatively large (on jam game scale) amount of time to understand how it works, but if the idea of coding a farming drone sounds interesting - give it a try and let me know what you thing in the comments. Don't hesitate to ask questions - I'll answer all!
Before you start
Paste better starting code: Gist to the editor. It is mostly the same, but it properly loops (farms and earns money indefinitely).
You don't need to read this whole doc before you start playing, but I suggest you skim through the headlines to get familiar with what's in the doc in case you need it later
Basic gameplay
Move around map with WASD or arrow keys (map view needs to be focused - click on it). Press "Center" if you ever lose your island out of view (yeah, I had a big vision).
Press "Patch" to update your drone with the current version of the code in the editor.
Be sure to play in fullscreen for more available space (Itch button at the bottom right of the game window).
You can also change the vertical split of left/right (map/editor) views. There is a small icon at the bottom right of map view, which you can drag left/right to adjust horizontal sizes.
Warning
Game doesn't save it's state, but code is always auto-saved.
You can try to regenerate map if you want and tinker with numerous params, but be aware that any tiny move of any slider (except "Moisture" group) will wipe the current state (except code) and regenerate world from scratch.
Most notably, you might want to test out various seeds: Map Gen => Island => Seed
How it was made (video)
As you see, this is a pretty advanced game. If you are interested in a more advanced game-dev (unlike "I added this cube to the scene, it was super hard" kind of devlogs), you might like my YouTube channel:
Videos take a ton of work, so I don't post often (yet), but I hope I'll manage to make a video about this game, so if that sounds interesting and you liked the video about the maze - subscribe:)
But I don't know JavaScript
If you are coming from C#/C++/Java, you should get the hang out JavaScript pretty quickly. Most things are the same:
a = b * c + d * e // Variable assignment and expressions if (cond) { } else { } // Conditions while (cond) { } // Loops array[20] // Array indexing obj.x // Object field access Math.cos(0) // Calling functions
Here are the most notable differences to get quickly up to speed:
- No typings in JavaScript
- You define variables with `let` (normal variable) or `const` (constant):
// C#: float x = length * Math.cos(angle); // JavaScript const x = length * Math.sin(angle) let y;
- Defining functions is different:
// C#: float multiply(float a, float b) { return a * b; } // JavaScript: function multiply(a, b) { return a * b; } // Or (shorter syntax): const multiply = (a, b) => a * b;
- Creating arrays is different:
// C#: new int[] { 1, 2, 3, 4 } // JavaScript [ 1, 2, 3, 4 ]
- You can just create objects "out of thin air", no need to pre-define classes, structs and other stuff:
// C#: struct Point { float x; float y; } // later: var point = new Point { x = 10, y = 20 }; // JavaScript: let point = { x: 10, y: 20 };
Logging
You can log into the console with:
console.log(obj1, obj2, obj3) console.warn(1009, 'is prime') console.error('something went wrong', 5 * 9)
It will output in your browser console (not in-game console), open it with "Right Click on empty space -> Inspect element" or Ctrl+Shift+I. There are some commented out debug console.log's in the starter code.
Starter code
The only two functions you need to code are at the end of the file: "start" and "update".
`drone` object provides you with very barebones control like setting motor "force", but if you want to fly to some point, you have to program it yourself, same if you want to sequence some "jobs" (e.g. fly to (200, 160) then plant). It's similar in this regard to programming AI for your game: game engine provides you with minimal per-frame control and it's your task to keep track of what AI does to make sure it finishes jobs and not switches them every frame.
The starter code contains this functionality for higher level drone control with job sequencing, but you don't have to use it. If implementing job/time-sequencing system sounds interesting, you can remove all of the starter code and start from scratch:
function start(drone) { } function update(drone) { }
Moving
Fly to given point once flyToJob(100, 200) // Patrols infinitely between given points patrolJob({x: 0, y: 10}, {x: 300, y: 20}, {x: 30, y: 400})
Buying and selling
// Buy maximum possible (money-wise and inventory-capacity-wise) amount of specified item buyMaxJob('orangeSeed') // Buys up to specified amount of specified item buyUpToJob('orangeSeed', 5) // Sells all of the specified item sellMaxJob('orange') // Note, example code buys 'orangeSeed', but sells 'orange' - those are different items
Watering
// The next two are without parameters, // because they act on the current location intakeWaterJob // intake water until waterContainer is full outtakeWaterJob // outtake water until waterContainer is empty // fly to given point then intake water intakeWaterAtJob(300, 400) // Water plants while patrolling between two given points waterLineJob(new Point(10, 40), new Point(10, 200))
Planting and extracting
plantJob('orangeSeed') // Plants given seed at the current tile plantAtJob('orangeSeed', 10, 80) // Fly to the specified point, then plant extractJob // Extracts whatever is on the current tile extractAtJob(10, 80) // Fly to specified location, then extract
Job combiners
// Following four jobs can have any number of parameters // Executes all jobs simultaneously, completes when at least one of them completes anyJob(patrolJob(p1, p2), outtakeWaterJob) // Same but completes when all jobs complete, continues to execute other jobs meanwhile allJob(job1, job2, job3, jobN) // Executes provided jobs in sequence once sequenceJob(job1, job2, job3, job4, jobN) // Executes jobs in sequence, but loops forever loopJob(job1, job2, jobN) // On a less abstract level, you have: performAtJob(intakeWaterJob, x, y) // which creates a job which executes given job at a given location
Combination examples from the starter code
const performAtJob = (job, x, y) => { const destJob = flyToJob(x, y); return sequenceJob(destJob, allJob(destJob, job)); } const extractAtJob = (x, y) => performAtJob(extractJob, x, y); const patrolJob = (...points) => loopJob( ...points.map(p => flyToJob(p.x, p.y)) );
Dynamic world
World lives it's own life. Most notably:
- moisture spreads to nearby tiles and evaporates
- plants grow or decay and die (their health increases or decreases)
Moisture
Moisture originates at water shores, spreads to adjacent tiles and evaporates from surface. It influences plant's health.
Health change of a plant is proportional (although capped) to:
tile.moisture - 24
which means that when moisture is above 24, plants grow, and when it's below 24, plants decay.
When plant's health reaches zero, it automatically dies. This is the same for the default grass as well as the plants your drone plants.
I chose the value of 24 to be quite simple on the default-seed map, but if you want more difficulty, you might regenerate map with another seed (read "Warning" paragraph above).
In any case, watering plants significantly increases their growth speed. For example, growth at `tile.moisture` = 72 compared to `tile.moisture` = 30 will be 8 times as fast ((72 - 24) / (30 - 24) = 48 / 6 = 8).
Tiles
All tiles except water function essentially the same: you can plant on any tile and you can extract any tile. Game idea is about farming, but nothing stops you from mining some rocks and selling them. Sample code sells grass.
Drone interface
All methods below (except setting `.motor.force`) operate for one frame only, so if you want to plant a seed, you need to call `.plant` numerous times until it is planted.
Memory
Any object you want to persist between drone patches. Anything saved here will stay the same throughout playthrough unlike top-level variables, which will re-initialize every patch.
drone.memory = { patchNumber: 4 };
Memory is like HDD.
Top-level variables - like RAM.
Refreshing the page will wipe memory as well though.
GPS
Provides access to drones location and velocity
drone.gps.position.x drone.gps.position.y drone.gps.velocity.x drone.gps.velocity.y
Time
Provides access to frame delta time (in milliseconds)
drone.time.delta
Motor
Allows to control drone's motor to make it move
drone.motor.force = { x: 1000, y: 500, };
Force will be automatically capped at
drone.motor.maxForce
You can also read from `drone.motor.force` if you need to.
Water container
Provides information to the state of drone water storage
drone.waterContainer.currentAmount drone.waterContainer.volume // maximum amount
Pump
Pump to move water in- and out- of water container.
drone.pump.intakeSpeed drone.pump.outtakeSpeed drone.pump.intake() drone.pump.outtake()
`.intake()` and `.outtake()` only affect one frame.
Shovel
Your main tool, use it to plant seeds and gather crops. Plant crops with:
drone.shovel.plant(item: string | Item): boolean
It takes either seed's itemKey (string) or item (Item) as a parameter and returns whether the seed was planted this frame. Before the seed can be planted, the current tile needs to be destroyed (think of getting rid of weeds or/and preparing soil) = it's health needs to reach zero. This tile damaging will happen automatically when you call `.plant`, but you need to continue calling `.plant` until you receive `true` which means that the seed has been planted.
drone.shovel.damage()
You can also just `.damage()` tiles without trying to plant anything, if you want it for whatever reason.
When you use `.plant()` or `.damage()` the current (under drone) tile is eventually destroyed no matter what was located on it. Typically, you want to gather crops instead of destroying them though. For that you use:
drone.shovel.extract(): boolean
Same as `.plant()`, it returns whether a tile (any tile) was extracted this frame. And same, it doesn't happen instantly: tile's firmness needs to reach zero before extraction will finally succeed. And same once again, `.extract()` will automatically decrease tile's firmness.
Inventory
The stuff drone carries. Some properties (hopefully) need no explanation:
drone.inventory.maxWeight drone.inventory.totalWeight drone.inventory.money
There are two ways to access information about specific item in your inventory:
drone.inventory.content.<itemKey>: Item drone.inventory.content[itemKey]: Item drone.inventory.content.orangeSeed.quantity drone.inventory.content['orangeSeed'].density
You can also enumerate all items with:
drone.inventory.list
`.list` has the same content as `.content`, but shaped as an array and not an object
Market
A place to buy your seeds and sell your crops at shitty prices. How shitty exactly? These params will tell you:
drone.market.buyPenalty drone.market.sellPenalty
They were planned to be upgradable (as everything else ... I mean as everything else was also planned to be upgradable), but they are just equal 2 for now, which means that real purchase and sell price of an item is:
item.price * drone.market.buyPenalty item.price / drone.market.sellPenalty
You can access information about various items with:
drone.market.availableItems.<itemKey>: Item drone.market.availableItems[itemKey]: Item drone.market.availableItems.orange.price drone.market.availableItems['orange'].density
And as with the inventory, there is a field to get the same information in the form of an array:
drone.market.availableItemsList
Item
Both `.inventory` and `.market.availableItems` contain objects of type `Item`, which has the following fields:
// item: Item item.key // key to access this item item.name // human readable name item.density // how much each unit of this item weights item.price // per one unit item.quantity // in case item is in your inventory
Full list of available methods
drone.memory (get, set) drone.gps.position (.x, .y) drone.gps.velocity (.x, .y) drone.time.delta drone.motor.force (get, set) drone.motor.maxForce drone.waterContainer.currentAmount drone.waterContainer.volume drone.pump.intakeSpeed drone.pump.outtakeSpeed drone.pump.intake() drone.pump.outtake() drone.shovel.damage() drone.shovel.plant(item: string | Item): boolean drone.shovel.extract(): boolean drone.inventory.maxWeight drone.inventory.totalWeight drone.inventory.money drone.inventory.content.<itemKey>: Item drone.inventory.content[itemKey]: Item drone.inventory.list drone.market.buyPenalty drone.market.sellPenalty drone.market.availableItems.<itemKey>: Item drone.market.availableItems[itemKey]: Item drone.market.availableItemsList item.key item.name item.density item.price item.quantity
Available items
soil: $1, 1kg stone: $25, 8kg sand: $0.9, 0.7kg grass: $3, 0.3kg tree: $20, 15kg orange: $4, 0.5kg potato: $2.5, 2kg rose: $75, 4kg sunflower: $6, 3.5kg wheat: $0.6666666666666666, 0.25kg whiteFlower: $30, 3kg
Available seeds
Seed is also an item, but the one which can be planted
Tree seed: $140, 80kg // yes, this one is "Tree seed", mistake orangeSeed: $80, 30kg potatoSeed: $75, 40kg roseSeed: $135, 250kg sunflowerSeed: $80, 120kg wheatSeed: $90, 25kg whiteFlowerSeed: $105, 170kg
Share your thoughts
Unusual games likes this are hard to get played during game jams. That means that if you've made it to actual game and tried to code something, I'd be triple glad to hear your thoughts. Criticism is welcomed:)
I also understand that despite this long text, it might still be more confusing than it should be. Ask any question and I'll answer!
See you in the comments
Status | Released |
Platforms | HTML5 |
Author | Igor Konyakhin |
Comments
Log in with itch.io to leave a comment.
Not realy in the mood to learn how to code in Javascript at the moment, but I hope this does well
Thanks for kind words. This is probably not the best game to learn coding, but I imagine a game like this, with a campaign/story/missions which will provide gradual learning curve, might be a great way to learn programming.
If you transition from C#/C++/Java, I think it should be ok though, as they are quite similar.