Changing Player Portrait

Hello everyone

I’ve started my first Twine/Sugarcube story and I’m still pretty inexperienced. I’ve already spent several hours working on the following and haven’t found any answers on the internet. But I don’t think the whole thing should be difficult, which annoys me all the more.

I have defined a portrait image for my player character in the CSS, which can be seen in the speech boxes during the story. Below is the CSS code:

.speech {
	color: white;
	border: 2px solid white;
	border-radius: 5px;
	padding: 8px 8px 8px 8px;
	box-shadow: 5px 5px 3px Black;
}
.avatar {
	display: block;
	padding: 1px;
	height: 84px;
	width: 84px;
	float: left;
	margin: 0px 10px 0px 0px;
	border: 2px solid white;
	border-radius: 5px;
	background-size: contain;
	background-repeat: no-repeat;
	background-position: center;
}

.You {
	background-color: #333333;
}
.You .avatar {
	background-image: URL("img/Portraits/Player_Standard.jpg");
}

At the beginning of the story, the player can choose whether to embody a male or female character. Depending on the selection, the background image of .You .avater should be changed from “Player_Standard.jpg” to “Player_Male.jpg” or “Player_Female.jpg”.

So far, I have only managed to change the image for the current passage. On the next one, however, the standard image is used again.

In HTML, I display the speech box as follows:

<<speech "You">>Ugh, what time is it?<</speech>>

Can you tell me the easiest way to do this?
Thank you and best regards!

Could you share the code of the <<speech>> macro/widget? (cause I think that’s where the code is going to end up :stuck_out_tongue: )

Without know which <<speech>> widget/macro implementation you are using it is difficult to know what features it has. But the general answer to a question like yours is a two layer approach.

1: Use a “dialogue” display system that allows both the Character’s Identifier and the image to show to be passed as arguments.

<<say "jane" "jane-happy.jpg">>Hello, how are you?<</say>>

<<say "mary" "mary-sad.jpb">>Hi, I'm not feeling that good today<</say>>

2: Create a series of widgets, one for each Character, that know how to determine which image to show.

<<widget "jane" container>>
	<<if $jane.gender is "female">>
		<<set _image to "jane-female.png">>
	<<else>>
		<<set _image to "jane-male.png">>
	<</if>>
	<<say "jane" _image>>_contents<</say>>
<</widget>>

<<widget "mary" container>>
	<<if $mary.feeling is "happy">>
		<<set _image to "mary-happy">>
	<<elseif $mary.feeling is "sad">>
		<<set _image to "mary-sad">>
	<<else>>
		<<set _image to "mary.png">>
	<</if>>
	<<say "mary" _image>>_contents<</say>>
<</widget>>

…and they the character widgets would be used thus…

<<jane>>Hello, how are you?<</jane>>

<<set $mary.feeling to "sad">>
<<mary>>Hi, I'm not feeling that good today<</mary>>

The above technique also works if the “dialogue” display system accepts a CSS Class name as the 2nd argument instead of the name of an image to be shown.
eg.

<<say "Jane" "happy">>Hello, how are you?<</say>>
<<say "Mary" "sad">>Hi, I'm not feeling that good today<</say>>

…in this use-case the widgets in step 2 would be using conditional checking to determine which CSS Class to use.

<<widget "jane" container>>
	<<if $jane.gender is "female">>
		<<set _class to "female">>
	<<else>>
		<<set _class to "male">>
	<</if>>
	<<say "Jane" _class>>_contents<</say>>
<</widget>>

…and the CSS Selector of the related CSS Rules in your Story > Stylesheet would need to be changed to react to the additional CSS Class being assigned to the HTML structure being created by the “dialogue” display system.

1 Like

Thanks alot for your answers! Please excuse me, here is the code for the <> macro:

Macro.add('speech', {
	tags     : null,
	handler  : function () {
		var id = this.args[0], name = id;
		if (this.args.length > 1) name = this.args[1];
		var output = '<div class="speech ' + id + '">';
		output += '<span class="avatar"></span>';
		output += name + '<hr>' + this.payload[0].contents + '</div>';
		$(this.output).wiki(output);
	}
});

Since you want to give the choice to the player in the avatar, I’d suggest saving the URL of the avatar in a variable:

<<link "Picture 1" "Next Passage">>
  <<set $avatarImage to "URL">>
<</link>>

And add an argument to your macro, so that this becomes valid:

<<speech "You" $avatarImage>>Some text<</speech

Maybe something like?

Macro.add('speech', {
	tags     : null,
	handler  : function () {
		var id = this.args[0], name = id;
        var avatar = this.args[1];
		if (this.args.length > 1) name = this.args[1];
		var output = '<div class="speech ' + id + '">';
		output += '<span class="avatar"><img src=" ' + avatar + '"></span>';
		output += name + '<hr>' + this.payload[0].contents + '</div>';
		$(this.output).wiki(output);
	}
});

(fair warning, this is untested - you could also nuke the <span class="avatar">)

The variation of the <<speech>> macro you’re using accepts two arguments, the 1st is the CSS Class to apply to the HTML being generated, and the 2nd is the Character’s Identifier/Name. If only one value is passed to the macro, it is used as both the CSS Class and the Character’s Identifier/Name.
eg.

/* this would use "you" as both the CSS Class and the Name. */
<<speech "you">>Ugh, what time is it?<</speech>>

/* this would use "you-male" as the CSS Class and "You" as the Name. */
<<speech "you-male" "You">>Ugh, what time is it?<</speech>>

/* this would use "you-female" as the CSS Class and "You" as the Name. */
<<speech "you-female" "You">>Ugh, what time is it?<</speech>>

And CSS like the following could be used to distinguish between each of the above three situations.

.You .avatar {
	/* properties to set for when "you" is both the CSS Class and Name */
}
.you-male .avatar {
	/* properties to set for when "you-male" is the CSS Class */
}
.you-female .avatar {
	/* properties to set for when "you-female" is the CSS Class */
}

You will need a way to track the End-user’s selected Gender for You, and that can be as simple as variable named $gender or as complex as using an Object to store all the details of You.
eg.

Is the You character \
<<link "Male">><<set $gender to "male">><</link>> or \
<<link "Female">><<set $gender to "female">><</link>>

So you don’t have to keep typing something like the following each time you want to write dialogue for You…

<<speech `"you-" + $gender` "You">>Ugh, what time is it?<</speech>>

…you can create a Character specific widget like the following that hides some of the complexity…

<<widget "you" container>>
	<<speech `"you-" + $gender` "You">>_contents<</speech>>
<</widget>>

…which you could then use instead…

<<you>>Ugh, what time is it?<</you>>

And if you decide to let the end-user also give You another name, that gets stored in a variable (like $name), you could then alter the Character Specific widget to use that variable as well…

<<widget "you" container>>
	<<speech `"you-" + $gender` $name>>_contents<</speech>>
<</widget>>
1 Like

Thanks a lot! I used the following solution, because I found this to be a very good compromise between usefullness and complexity:

<<set $gender to "male">>
<<speech `"You-" + $gender` "You">>contents<</speech>>