My Intent: Making a CYOA Using Objects
I'm quite new to Javascript and have been trying to make a simple CYOA game, using this code from this Reddit comment as a template. However, I want to use objects (whose values are intended to be constant) to store the various string values for the messages and the object each choice points to, as opposed to having all the objects in arrays and having to point to them using using their index in the array. My reasoning is that it'd be (theoretically) simpler for me to organize using strings like "msg_001" or "story5_28" rather than having to change a bunch of numbers in the event I inserted some new set of messages in the middle of an array.
My Problem: The First Message Isn't Displayed Again
Basically, I want to loop back to the first message and its set of answers, but it won't.
The initial printCurrentMsg()
works (changing the content of the "message" divs to the values of msgText
, and looping through the object's choices
array to set the buttons in the "choices" div, based on the object specified in currentMsg
) and the buttons' respective onlick
attributes seem to work, until they're set to show msg_000
.
It appears to be that whatever the value of currentMsg
is, printCurrentMsg
won't show the object the string refers to, other than when it does initially. Additionally, after using console.log
at various points in the script, I noticed that currentMsg
isn't changed, and using console.log(typeof)
for both currentMsg
and window[currentMsg]
shows that the former is a string and the latter is an object. Am I unintentionally creating two separate variables?
I've tried...
- ...using parameters in
printCurrentMessage
. - ...using
currentMsg
in the functions instead ofwindow[currentMsg]
. - ...using dot notation instead of bracket notation.
- ...using
this[]
instead ofwindow[]
.
I'm not sure whether this has to do with asynchronicity, I'm accessing object properties incorrectly, my comprehension of scope is flawed, or if I'm erroneously using global variables. Should I be using some sort of callback?
Using a "dummy" msg_000
—making another object with a different name but the same properties—serves as a stopgap solution, but I still wouldn't understand what the problem is. Having all the msg_***
objects in an array and referring to them by index number instead of string would also work, but I'm hesitant to rely on that for both the aforementioned tediousness and the fact that I still don't understand why the value of currentMsg
remains unchanged.
In order to better articulate my problem, here is a jsfiddle with my code, and I shall post it below as well.
//messages
var msg_000 = { //Starts with this one, I want to be able to go back to it
msgName: "msg_000",
msgText: "Sup! Choose an option!",
choices: [
ans_000 = {
ansText: "Climb a hill!",
ansGoto: "msg_001" //this works
},
ans_001 = {
ansText: "Skin a cat!",
ansGoto: "msg_002" //this works
},
ans_002 = {
ansText: "Build a birdhouse!",
ansGoto: "msg_003" //this works
}
]
};
var msg_001 = {
msgName: "msg_001",
msgText: "You summit the great snowy peaks!",
choices: [
ans_000 = {
ansText: "Talk to the Recursion Guru!",
ansGoto: "msg_000" //this doesn't work
}
]
};
var msg_002 = {
msgName: "msg_002",
msgText: "You suffer severe lacerations to the face!",
choices: [
ans_000 = {
ansText: "Start Over",
ansGoto: "msg_000" //this doesn't work
}
]
};
var msg_003 = {
msgText: "You build a pretty average looking birdhouse. Some grackles have moved in nonetheless, placing their various knicknacks, bedding materials, and chrono-gateways within their new abode.",
choices: [
ans_000 = {
ansText: "Step through the chrono-gateway!",
ansGoto: "msg_000" //this doesn't work
},
ans_001 = {
ansText: "I think I wanna climb that mountain over there.",
ansGoto: "msg_001" //this works
}
]
}
var currentMsg = "msg_000"; //the first message is "msg_000"
printCurrentMsg = function() {
document.getElementById("message").innerHTML =
window[currentMsg].msgText;
//sets the message (the div with the id of "message")
//based on the "currentMsg" variable. "currentMsg.msgText"
//doesn't seem to work.
var choices = "";
for (var i = 0, l = window[currentMsg].choices.length; i < l; i++) {
choices += "<p><button onclick='setMessage(" +
window[currentMsg].choices[i].ansGoto + ")'>" +
window[currentMsg].choices[i].ansText + "<br>Goto " +
window[currentMsg].choices[i].ansGoto + "</button></p>";
//make the buttons, sets the button's onclick
//"setMessage" function's parameter to the the value of
//the "ansGoto" property -> in the answers object at the
//i/th index of the choices property array -> in the
//"msg_(number)" object."
};
document.getElementById("choices").innerHTML = choices;
//takes the value of the "choices" [local?] variable and puts
//it in the "choices" div.
};
setMessage = function(msg) {
window[currentMsg] = msg; //I think this is the source of all
//my problems, it's supposed to set "currentMsg" to the value
//of the "msg" parameter, but when I check it with
//console.log(currentMsg) it hasn't been changed (i.e., still
//it's initial value of "msg_000") and when I use
//console.log(window[currentMsg]) it returns "[Object
//object]"; using typeof shows me that "currentMsg" is a
//string and "window[currentMsg]" is an object. I thought
//they both were the same object, am I unintentionally
//creating two different objects?
printCurrentMsg(); //runs that function, seems to display the
//messages except the ones from object "msg_000".
};
printCurrentMsg(); //Displays the initial message and choices
//from "msg_000", but after a new message is chosen it won't
//display "msg_000" if it's pointed to from an "ansGoto"
//property.
<!DOCTYPE html>
<html>
<body>
<div id="message"></div>
<!-- "msgText" goes here -->
<div id="choices"></div>
<!-- "choices" go here -->
</body>
</html>
Thank you for your time.