Published
Edited
Apr 19, 2021
1 fork
1 star
Insert cell
md`# Douglas and the Deluge: an interactive comic by Emma T Capps `
Insert cell
md`### Project Description:
This comic is created by you, the reader. Your choices decide the appearance and story of the comic, and each choice is dependent on your own prior choices. However, you are not directly creating the artwork - your choices are. Remember, once you make one choice, you can't take it back - the story must go on, after all! Once you have made a certain number of choices, the comic has finished, a silent collaboration between me and you.`
Insert cell
md`### The Concept/"What's At Stake":
The aim of this project is to further the boundaries of creating online comics/interactie literature, which is something I have been experimenting with in varied forms since 2011. I have made standard online comics with no interactivity ranging to completely interactive text adventure games, but this project would be somewhere in between: enabling the user to create their own work of graphic fiction, while still being constrained to the choices and images I provide them with. This will be an experiment for me, too, in embracing the online nature of many comics careers these days (and what made my own career and got me published), instead of railing against it. After all, it's not like the Internet is going anywhere.`
Insert cell
Insert cell
css = html`
<style>
html, body {
margin:0;
padding:0;
}

.comic {
display:flex;
flex-wrap:wrap;
font-family:'Museo';
padding:1vmin;
}

.panel {
background-color:#fff;
margin:2px;
display:inline-block;
flex:1 1;
height:310px;
overflow:hidden;
position:relative;
}

.image {
width: 100%;
height: 100%;
}
.text {
display:none;
background-color:#fff;
border:solid 2px #000;
margin:0;
padding:3px 10px;
}

.top-left {
left:-6px;
position:absolute;
top:-2px;
transform:skew(-15deg);
}

.bottom-right {
display:none;
font-size: 60%;
background-color:#fff;
border:solid 2px #f97ab5;
padding:0px 7px;
bottom:4px;
position:absolute;
right:5px;
transform:skew(-15deg);
}

.speech {
background-color:#fff;
border:solid 2px #000;
border-radius:12px;
display:inline-block;
margin:.5em;
padding:.5em 1em;
position:relative;
}

.speech:before {
border:solid 12px transparent;
border-left:solid 12px #000;
border-top:solid 12px #000;
bottom:-24px;
content:"";
height:0;
left:24px;
position:absolute;
transform:skew(-15deg);
width:0;
}

.speech:after {
border:solid 10px transparent;
border-left:solid 10px #fff;
border-top:solid 10px #fff;
bottom:-19px;
content:"";
height:0;
left:27px;
position:absolute;
transform:skew(-15deg);
width:0;
}

</style>
`
Insert cell
start = {init()}
Insert cell
init = ()=>{
renderStep();
bindEvents();
}
Insert cell
nextStep = ()=>{
let theSelect = view.querySelector('#choices select')
mutable currentScene = theSelect.value
mutable currentText = theSelect.options[theSelect.selectedIndex].dataset.description

}
Insert cell
renderStep = () => {
console.log("renderStep: currentScene", currentScene);
view.querySelector('#log').appendChild(html`
<div class=panel style='flex-basis: ${story[currentScene].wide}; min-width:${story[currentScene].wide}; max-width: ${story[currentScene].wide}'>
<img class=image src="${story[currentScene].img}">
</div>
`);

view.querySelector('#choices').replaceChild(
html`<select id="choicesSelect">
<option value="-1">Make your choice</option>
${story[currentScene].choices.map(x => {
return html`<option data-description="${x.description}" value="${x.gotoScene}">${x.label}</option>`;
})}
</select>`,
view.querySelector('#choices').childNodes[0]
);
}
Insert cell
bindEvents = ()=>{
view.querySelector("#choices").removeEventListener("change", nextStep)
view.querySelector("#choices").addEventListener("change", nextStep)
}
Insert cell
mutable currentScene = 0

Insert cell
mutable currentText = 'You wake up...'
Insert cell
story = [
{
scene: 0,
img: await FileAttachment("Panel 1@1.png").url(),
text: 'Douglas is in bed. It is morning.',
wide: '310px',
choices: [
{
id: 1,
label: "Eat quickly before heading out.",
gotoScene: 1
},
{
id: 2,
label: "Stay in bed a bit longer.",
gotoScene: 2
}
]
},

{
scene: 1,
img: await FileAttachment("Panel 2a.png").url(),
wide: '310px',
choices: [
{
id: 3,
label: "Get going for work.",
gotoScene: 3
}
]
},

{
scene: 2,
img: await FileAttachment("Panel 2b@2.png").url(),
wide: '310px',
choices: [
{
id: 5,
label: "Get going for work.",
gotoScene: 3
}
]
},

{
scene: 3,
img: await FileAttachment("Panel 3a.png").url(),
wide: '310px',
choices: [
{
id: 8,
label: "Leave the apartment and start walking.",
gotoScene: 4
}
]
},

{
scene: 4,
img: await FileAttachment("Panel 4.png").url(),
wide: '310px',
choices: [
{
id: 8,
label: "Duck into an alleyway for shelter.",
gotoScene: 6
},
{
id: 10,
label: "Take a shortcut.",
gotoScene: 8
}
]
},

{
scene: 5,
img: await FileAttachment("Panel 3c MOCKUP@1.jpg").url(),
wide: '310px',
choices: [
{
id: 8,
label: "Duck into an alleyway for shelter.",
gotoScene: 6
},
{
id: 10,
label: "Try to fix the umbrella.",
gotoScene: 8
}
]
},

{
scene: 6,
img: await FileAttachment("Panel 5a@2.png").url(),
wide: '310px',
choices: [
{
id: 11,
label: "Ignore the stranger.",
gotoScene: 9
},
{
id: 12,
label: "Talk to the stranger.",
gotoScene: 9
}
]
},

{
scene: 7,
img: await FileAttachment("Panel 5b@1.png").url(),
wide: '310px',
choices: [
{
id: 13,
label: "Take a shortcut.",
gotoScene: 8
},
{
id: 14,
label: "Run to work.",
gotoScene: 11
}
]
},

{
scene: 8,
img: await FileAttachment("Panel 5c.png").url(),
wide: '310px',
choices: [
{
id: 13,
label:
"Doug decides he's already late enough to work. Try to pet the dog!",
gotoScene: 10
},
{
id: 14,
label: "The dog probably has rabies!",
gotoScene: 10
}
]
},

{
scene: 9,
img: await FileAttachment("Panel 6b.png").url(),
wide: '310px',
choices: [
{
id: 15,
label: "Agree, and ask what the favor entails.",
gotoScene: 15
},
{
id: 17,
label: "Politely decline.",
gotoScene: 16
}
]
},

{
scene: 10,
img: await FileAttachment("panel 6a@3.png").url(),
wide: '310px',
choices: [
{
id: 17,
label: "Call the dog's owner.",
gotoScene: 12
},
{
id: 17,
label: "Ask the dog about, well, it talking and everything.",
gotoScene: 13
},
{
id: 18,
label: "Offer to join the dog's self-care journey.",
gotoScene: 14
}
]
},

{
scene: 11,
img: await FileAttachment("Panel 5c.png").url(),
wide: '310px',
choices: [
{
id: 19,
label: "Option 3 TBA",
gotoScene: 14
},
{
id: 17,
label: "option 1 TBA",
gotoScene: 12
},
{
id: 20,
label: "Option 4 TBA",
gotoScene: 15
}
]
},

{
scene: 12,
img: await FileAttachment("Panel 7a.png").url(),
wide: '310px',
choices: [
{
id: 19,
label: "Look for the owner's info to call.",
gotoScene: 24
}
]
},

{
scene: 13,
img: await FileAttachment("Panel 7b.png").url(),
wide: '310px',
choices: [
{
id: 19,
label: "Decide to walk with the dog for a bit.",
gotoScene: 17
}
]
},

{
scene: 14,
img: await FileAttachment("Panel 7c@1.png").url(),
wide: '310px',
choices: [
{
id: 19,
label: "Work wasn't really joy-inspiring, anyway.",
gotoScene: 17
}
]
},

{
scene: 15,
img: await FileAttachment("Panel 7d.png").url(),
wide: '310px',
choices: [
{
id: 19,
label: "Explain finances.",
gotoScene: 19
}
]
},

{
scene: 16,
img: await FileAttachment("Panel 7e@1.png").url(),
wide: '310px',
choices: [
{
id: 20,
label: "Explain the futility of said curse.",
gotoScene: 20
}
]
},

{
scene: 17,
img: await FileAttachment("Panel 8a.png").url(),
wide: '310px',
choices: [
{
id: 22,
label: "Continue together...",
gotoScene: 21
}
]
},

{
scene: 18,
img: await FileAttachment("Panel 8a.png").url(),
wide: '310px',
choices: [
{
id: 24,
label: "option 1 TBA",
gotoScene: 20
},
{
id: 25,
label: "option 2 TBA",
gotoScene: 22
}
]
},

{
scene: 19,
img: await FileAttachment("Panel 8e.png").url(),
wide: '310px',
choices: [
{
id: 26,
label: "Continue the kvetching.",
gotoScene: 22
}
]
},

{
scene: 20,
img: await FileAttachment("Panel 8b.png").url(),
wide: '310px',
choices: [
{
id: 26,
label: "Continue the discussion.",
gotoScene: 23
}
]
},

{
scene: 21,
img: await FileAttachment("Panel 9a.png").url(),
wide: '310px',
choices: []
},

{
scene: 22,
img: await FileAttachment("Panel 9c.png").url(),
wide: '310px',
choices: []
},

{
scene: 23,
img: await FileAttachment("Panel 9b.png").url(),
wide: '310px',
choices: []
},

{
scene: 24,
img: await FileAttachment("Panel 8f.png").url(),
wide: '310px',
choices: [
{
id: 26,
label: "Commiserate about Donna.",
gotoScene: 25
}
]
},

{
scene: 25,
img: await FileAttachment("Panel 9d.png").url(),
wide: '310px',
choices: []
}
]
Insert cell
md`# Story Layout/Schematic:
First Panel: Only one option, and one drawing.

Second Panel (#1 and #2): Two potential panels, and two drawings. These each then link to two potential options, totaling four options. But two of these options spit out the same panel result.

Third Panel (#1, #2, and #3): Three potential panels, and three drawings. Each of these three options has two options it links to, resulting in six different variants, but there are only three potential panels (three choices link to the same panel).

Fourth Panel (#1, #2, and #3): Each of the three potential images for panel number four will have two options, resulting in six total potential choices to be made. However, three of them link to the same panel drawing, which means there are only three potential routes to go.

Fifth Panel (#1, #2, and #3): Each of the three potential images for panel number five will have three options, resulting in nine potential different images. But, as before, not all of these will be distinct – in fact, only four will.

Sixth Panel (#1, #2, #3, and #4): Each of these four potential images for panel number six will have only one option. As in, there is only one way to go in each choice.

Seventh Panel (#1, #2, #3, and #4): Finally, the return of choices! Each of the four potential panels for the seventh panel will span two potential choices, totaling eight possible choices to be made. However, some of these choices will spawn the same result, and in actuality there are only three options that will prompt a different image to appear.

Eighth Panel (#1, #2, and #3): Three potential panels, and each will have three different options, resulting in nine different potential variants for the subsequent ninth panel.

Ninth Panel (#1, #2, #3, #4, #5, #6, #7, #8, #9): There are nine potential endings to the story.

That is, in total: 32 distinct panels for me to draw, as those are the various different iterations for the story itself. That sounds like a lot, but I’m planning on using a relatively simplistic/abstract style with a limited color palette, and some of the potential choices might not differ too dramatically from the others.

The story will follow a vague three-act structure, with three rows of three panels – so the first row will be Act 1, the second row Act 2, and the third and final row Act 3. `
Insert cell
md`# Beginning panel summaries (not yet complete):

A Day for Douglas

First Panel: Douglas is in bed. The subsequent options are: "Stay in bed" or "Get up for work."

Second Panel (“stay in bed” variant): Douglas stays in bed too long and realizes he’s late for work. The subsequent options are: "Eat quickly before heading out" or "Leave right away."

Second Panel (“get up for work” variant): Douglas gets up for work. He gets dressed, too. The subsequent options are: "Leave right away" or "Check the weather report".

Third Panel (“leave right away” variant): Douglas leaves the house and is immediately trapped in a massive rainstorm. He realizes he will be soaked upon arriving at the office. The subsequent options are: "Go to work like this" or "Duck into an alleyway for shelter".

Third Panel (“eat quickly before heading out” variant): Douglas quickly eats a bowl of cereal and realizes it is raining outside, so he grabs an umbrella before he heads out. But the rain is too strong and his umbrella flips inside-out. The subsequent options are: "Duck into an alleyway for shelter" or "Try to fix the umbrella".

Third Panel (“check the weather report” variant): The weather report forecasts heavy rain, so Douglas brings a sturdy umbrella and a rain-jacket. Still, as he steps out, the umbrella starts to fail. The subsequent options are: "Go to work like this" or "Try to fix the umbrella".

Fourth Panel (“duck into an alleyway” variant): Douglas ducks into an alleyway, hoping the rain will offer shelter – there’s someone else there with the same idea. Doug realizes he can cut through this alley as a possible shortcut to work. The subsequent options are: "Take a shortcut" or "Talk to the stranger".

Fourth Panel (“go to work like this” variant): Doug decides he’ll just make it work and get to work as soon as possible. The subsequent options are: "Run to work" or "Take a shortcut".

Fourth Panel (“try to fix the umbrella” variant): Doug tries to flip the umbrella right-side out. He’s not totally soaked, so there might be saving this yet. As he does, he notices a stranger in a nearby alleyway who might be able to help, but that seems a little sketchy for Doug’s taste. The subsequent options are: "Talk to stranger" or "Run to work".`
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more