- Jan 22, 2020
- 59
- 157
I'm a self taught hobbyist programmer, for what it's worth. My latest project is a JavaScript based choose your own adventure game using Twine (Tweego) as the framework. If you're not familiar with Twine, I don't believe it will hinder your understanding. I'll outline the issue in relation to they framework.
Twine's recommended variable storage objects are as follows: the setup object for variables that will load every time the game starts (refreshes), and the state object for variables that will be saved to file when the user saves their game. Since my game is planned to be early access, I need to be clever about how I do updates. If I add a new feature to the player, I don't want to force them to start the game over. Rather, handle it in a way that "auto" updates. The obvious way, to me, was leveraging Twine's setup object for default values. For instance, if the player's default hacking skill is 15 and during development I reason that value too low, I can increase it with minimal fuss. I accomplished this by doing the following:
In the above code I created a constant variables for the PLAYER_BASE stats, so the program knows what the player minimum values are. Then I created a constant variable for PLAYER_INIT, which is only used when the game starts. When a new game begins, the following code is run:
Before I explain the Twine syntax, I'll explain why I store $player with 0 values for all stats. As the game progresses, the player will gain points to apply to these stats, so this object tracks what the player has changed, not what the values originated as, which is what setup.PLAYER_BASE defines.
In Twine, the $ signals that a value will be stored to the state object (things that will be stored when the game saves). The :: tells Twine that what follows is a passage. I mention this, because there is another character I'll use in the next bit of code that represents a variable local to the passage, which is _. Next I'll demonstrate how this all ties together.
Now, here is that `PlayerObj` code to make sense of it all.
Okay, so now every time a game is loaded from a save file, first everything in `setup` is defined, then the passage the player left off on is loaded. So, if I decided the player's hacking skill should be 30, it will now be 15 points higher than it was when the player saved. This to me feels incredibly sloppy and not DRY whatsoever. First, the `setup.PLAYER_INIT` feels redundant, because everything except the hacking skill value has no relevance. I'm sure this is a common task among programmers, which is why I'm seeking wisdom to expand my knowledge. Thank you in advance for the reviews.
Twine's recommended variable storage objects are as follows: the setup object for variables that will load every time the game starts (refreshes), and the state object for variables that will be saved to file when the user saves their game. Since my game is planned to be early access, I need to be clever about how I do updates. If I add a new feature to the player, I don't want to force them to start the game over. Rather, handle it in a way that "auto" updates. The obvious way, to me, was leveraging Twine's setup object for default values. For instance, if the player's default hacking skill is 15 and during development I reason that value too low, I can increase it with minimal fuss. I accomplished this by doing the following:
JavaScript:
setup.PLAYER_BASE = {
// primary stats
charisma: 0,
manipulation: 0,
wits: 0,
// skills
hacking: 15,
lockpicking: 0,
negotiation: 0,
sneaking: 0,
// perks
appearance: 0,
goodness: 0,
leadership: 0,
wickedness: 0
}
setup.PLAYER_INIT = {
// primary stats
charisma: 0,
manipulation: 0,
wits: 0,
// skills
hacking: 0,
lockpicking: 0,
negotiation: 0,
sneaking: 0,
// perks
appearance: 0,
goodness: 0,
leadership: 0,
wickedness: 0,
// Inventory
credits: 0,
items: [],
laptop: {}
}
JavaScript:
:: InitStory
<<set $player = setup.PLAYER_INIT>>
In Twine, the $ signals that a value will be stored to the state object (things that will be stored when the game saves). The :: tells Twine that what follows is a passage. I mention this, because there is another character I'll use in the next bit of code that represents a variable local to the passage, which is _. Next I'll demonstrate how this all ties together.
JavaScript:
:: chapterOne
<<set _playerObj = new setup.PlayerObj($player, setup.PLAYER_BASE)>>
JavaScript:
window.setup = window.setup || {};
setup.PlayerObj = function(playerData, playerBase) {
this.firstName = playerData.firstName;
this.lastName = playerData.lastName;
// primary stats
this.charisma = playerData.charisma + playerData.charisma;
this.manipulation = playerData.manipulation + playerData.manipulation;
this.wits = playerData.wits + playerData.wits;
// skills
this.hacking = playerData.hacking + playerBase.hacking;
this.lockpicking = playerData.lockpicking + playerBase.lockpicking;
this.negotiation = playerData.negotiation + playerBase.negotiation;
this.sneaking = playerData.sneaking + playerBase.sneaking;
// perks
this.appearance = playerData.appearance + playerBase.appearance;
this.goodness = playerData.goodness + playerBase.appearance;
this.leadership = playerData.leadership + playerBase.leadership;
this.wickedness = playerData.wickedness + playerBase.wickedness;
// items
this.items = playerData.items;
// equipment
this.laptop = playerData.laptop;
// methods
this.fullName = function () {
return this.firstName + " " + this.lastName;
}
}