How would i go about making an image that changes depending on a variable?

hey fellas, so im trying to make it so an image changes in the character creation based on your choices
for example if you choose the class “warrior” the image changes to that of an warrior or if you choose “rogue” it changes to an image of a rogue. i have all the pictures set up already but now i need to figure out how to make the image change. using twine 2.3.9 and sugarcube 2.31.1
I tried playing around with if statements but I couldnt figure it out. I thought it would be important to mention that im a total noob at this and have never used css or html

You might want to start off by taking a look at my “Displaying Images in Twine” sample code (click “Jump to Start” in the UI bar to see other sample code there). That shows you how to make images display properly, both when launched from Twine and when the published HTML is opened, plus it shows you how to use variables to set the images’ filenames.

You could then combine that with the “Simple Update Without Reload” sample code to make it so that they’d see the image update as soon as they changed the character class.

If you’d like it to update with a nice transition, then you could do something like this:

What's is your class?<<set _classes = ["warrior", "rogue", "wizard"]>>
<<listbox "$class">>
	<<optionsfrom _classes>>
<</listbox>>
<span id="class-image"></span>
<<script>>
	$(document).one(":passagerender", function (event) {
		$(event.content).find("#class-image").empty().wiki("[img[" + setup.ImagePath + State.variables.class + ".jpg]]");
		$(event.content).find("select.macro-listbox").on("change", function (event) {
			$("#class-image").fadeOut(500);
			setTimeout(function () {
				$("#class-image").empty().wiki("[img[" + setup.ImagePath + State.variables.class + ".jpg]]").fadeIn(500);
			}, 500);
		});
	});
<</script>>

Note that the above code assumes that you’re defining setup.ImagePath as shown in the “Displaying Images in Twine” sample code, and that the images are in an “images” subdirectory and named “warrior.jpg”, “rogue.jpg”, and “wizard.jpg”. You can modify that code if you want it to work differently.

That code will display a dropdown list of options (based on the names in the _classes array). The option selected will be stored in the $class variable. Changing the class in the dropdown list triggers the code which updates the image displayed within the <span> that has the “class-image” ID.

If you want to understand how the stuff inside the <<script>> macro works, take a look at the SugarCube :passagerender event and the .wiki() method, and the rest you’ll find information on in the jQuery API documentation.

Feel free to ask if you have any questions about how any of that works.

Enjoy! :grinning:

Hey,

Thanks for the quick reply and good explanation! This worked perfectly! I’m thinking about possibly reusing this system later on. Lets say I wanted to use this same system for example for weapons or spells, what should I replace in the code?

You can pretty much just change the names of most things with no problem, as long as you change the names consistently. For weapons, simply change “class” to “weapon” and “classes” to “weapons” throughout the code, and then put weapon names instead of classes in the array.

The one thing to note is that, if you have more than one listbox on the page, then you’ll need to change “select.macro-listbox” to “#listbox-variablename” where “variablename” is the variable used inside of <<listbox "$variablename">> (not including the “$” part). So if you do, <<listbox "$weapon">> then “select.macro-listbox” should be changed to “#listbox-weapon”.

Have fun! :grinning:

Hey again,

Thanks again for the help, I think I’ve figured it out and got it working but I noticed a small problem, I noticed that changing the image through the dropdown menu doesn’t change the variable (in this case player.class which tells what class the player is) how would I go about making sure the drop down menu changes the image and the variable.

Thanks again.

Changing the option selected in the dropdown list should change the variable.

That said, if you’re using multiple listboxes in the passage with variable names like:

<<listbox "$player.class">>

then you’ll need to change “select.macro-listbox” to “#listbox-playerclass” for each one, since you can’t have a “.” in the middle of the ID.

If that doesn’t work, then I’ll need to see your code to figure out what’s going wrong.

Hope that helps! :grinning:

Hey again,

I tried solving it myself but I just couldn’t figure it out so here is the code which changes the image but not the variable

Your weapon of choice is <<print $player.weapon>> <<set _weapons = ["sword", "dagger", "staff"]>>
<<listbox "$weapon">>
	<<optionsfrom _weapons>>
<</listbox>>
<span id="weapon-image"></span>
<<script>>
	$(document).one(":passagerender", function (event) {
		$(event.content).find("#weapon-image").empty().wiki("[img[" + setup.ImagePath + State.variables.weapon + ".png]]");
		$(event.content).find("select.macro-listbox").on("change", function (event) {
			$("#weapon-image").fadeOut(500);
			setTimeout(function () {
				$("#weapon-image").empty().wiki("[img[" + setup.ImagePath + State.variables.weapon + ".png]]").fadeIn(500);
			

If it helps heres the way I defined the weapon and class variables

<<set $player = {

  weapon: "sword", 
  class: "warrior",
  
}>>

Thanks

Like I said earlier:

So, if you want it to change the value of $player.weapon instead of $class, then you pretty much just have to replace “class” in the original code with “player.weapon”, and replace “classes” with “weapons”. For example:

What weapon do you choose?<<set _weapons = ["battle axe", "short sword", "wand"]>>
<<listbox "$player.weapon">>
	<<optionsfrom _weapons>>
<</listbox>>
<span id="weapon-image"></span>
<<script>>
	$(document).one(":passagerender", function (event) {
		$(event.content).find("#weapon-image").empty().wiki("[img[" + setup.ImagePath + State.variables.player.weapon + ".jpg]]");
		$(event.content).find("#listbox-playerweapon").on("change", function (event) {
			$("#weapon-image").fadeOut(500);
			setTimeout(function () {
				$("#weapon-image").empty().wiki("[img[" + setup.ImagePath + State.variables.player.weapon + ".jpg]]").fadeIn(500);
			}, 500);
		});
	});
<</script>>

If you didn’t change it that way, then that’s why it didn’t work.