<%$(function(){
story.render("[[gridhack]]")
story.show("[[#AXp2]]")
})%>
p.addLayers("bg","arm","birds");
p.art.path('./art/ax/')
p.addArtAssets(
["bg", "bg.png"],
["arm-rustle", "arm1.png"],
["arm-throw", "arm2.png"],
["birds", "birds1.png"],
["birds-squawking", "birds2.png"]
)
const firstStepU = 1200;
p.step.create(
{
a: "bg", l: "bg",
u: firstStepU
},
{
a: "birds", l: "birds",
u: firstStepU
}
)
p.step.create(
{
l: "arm",
a: "arm-rustle",
u: firstStepU/4
}
)
p.step.create(
{
p: "replace", l: "arm",
a: "arm-throw",
u: firstStepU/4
},
{
p: "replace", l: "birds",
a: "birds-squawking",
d: 400,
u: firstStepU/4
}
)
p.destination.main = "[[#AZp1]]";
p.destination.main = "[[#BXp1]]";
p.addLayers("art");
p.art.path('./art/az/')
p.addArtAssets(
["title", "../title.png"],
["bg", "bg.png"],
["text1", "text1.png"],
["text2", "text2.png"]
);
const timing = 800;
p.step.create(
{
l: "art", a: "bg",
u: timing/2
}
);
p.step.create(
{
l: "art", a: "text1",
u: timing
}
);
p.step.create(
{
l: "art", a: "text2",
u: timing
},
{
a: "title", l: "art",
u: timing*4,
d: timing*1.2,
xy: [-600, -40],
s: "async"
}
);
p.destination.main = "[[#BYp2]]";
p.art.path('./art/bx/')
p.addArtAssets(
["bg-buzz-gif", "bg.gif"],
["head-buzz-gif", "head.gif"],
["computer-whitescreen", "bgwhite.png"],
["computer-lineart", "bglineart.png"],
["frame","frame.png"],
["head1", "head1-shaded.png"],
["head2", "head2-shaded.png"],
["text", "text.png"],
["porn1","porn1.png"],
["porn2","porn2.png"],
["porn3","porn3.png"],
["porn4","porn4.png"]
)
p.addLayers(
"bg-buzz",
"bg-lineart",
"porn",
"head-buzz",
"head",
"frame"
);
p.step.create(
// init
{
l: "bg-buzz",
a: "bg-buzz-gif"
},
{
l: "head-buzz",
a: "head-buzz-gif",
e: "hidden",
},
{
l: "bg-lineart",
a: "computer-lineart"
},
{
l: "frame",
a: "frame"
},
// porn
{
l: "porn",
a: "porn1",
u: 400
},
//
{
l: "head-buzz",
a: "head-buzz-gif",
e: "fadeInRight", p:"effect",
d: 400,
u: 1000
},
{
l: "head",
a: "head1",
e: "fadeInRight",
u: 800
},
);
p.step.create(
{
l: "porn",
a: "porn2",
p: "replace"
}
);
p.step.create(
{
l: "porn",
a: "porn3",
p: "replace"
}
);
p.step.create(
{
l: "porn",
a: "porn4",
p: "replace"
},
// head turn
{
l: "head",
a: "head2",
p: "replace",
u: 400,
d: 400
},
//)
//p.step.create(
{
l: "head",
a: "text",
d: 600,
u: 600
}
);
p.addLayers("art");
p.art.path('./art/by/')
p.addArtAssets(
["bg", "bg.png"],
["text1", "text1.png"],
["text2", "text2.png"],
["text3", "text3.png"]
);
p.step.create(
{
l: "art", a: "bg",
u: 400,
}
);
p.step.create(
{
l: "art", a: "text1",
u: 600,
}
);
p.step.create(
{
l: "art", a: "text2",
u: 800,
}
);
p.step.create(
{
l: "art", a: "text3",
u: 1000
}
);
p.destination.main = "[[#CXp1]]";
p.art.path('./art/cx/');
var slow = s.slow;
p.addArtAssets(
{
name: "big-shadow",
type: "asset",
src: "big-shadow.png"
},
["frame", "frame.png"],
["lineart", "lineart.png"],
["shadow", "shadow.png"],
["shadow-pattern", "texture.png"],
["text1", "text1.png"],
["text2", "text2.png"]
);
// background setup
p.addLayers('shadow', 'art', 'text');
p.step.create(
{
l: "text", a: "frame",
u: slow, s: "async"
},{
l: "shadow", a: "shadow",
u: slow, s: "async",
xy: [-2,-2]
},{
l: "art", a: "lineart",
u: slow, s: "async"
},{
l: "shadow", a: "big-shadow",
u: slow, s: "async", d: slow/4
},{
l: "shadow", a: "shadow-pattern",
s: "async",
xy: [-2,-2]
}
);
p.step.create(
{
l: "text", a: "text1",
u: 800,
}
);
p.step.create(
{
l: "text", a: "text2",
u: 800
}
);
p.destination.main = "[[#CYp1]]";
p.art.path('./art/cy/');
p.addArtAssets(
["text", "text.png"],
["art", "lineart.png"],
["animated-art", "dishdoing.gif"]
);
p.addLayers('art');
p.step.create(
{
a: "animated-art", l: "art",
u: s.slow*.75, s: "async"
},{
a: "text", l: "art",
d: s.slow/4, u: s.slow/2
}
);
p.destination.main = "[[#CZp1]]";
p.art.path('./art/cz/');
p.destination.main = "[[#DXp2]]";
p.addLayers("bg", "cat", "arm", "robot", "text");
p.step.create({
a: "frame", l: "text",
u: 250
},{
a: "bg", l: "bg",
u: s.slow/2,
d: 100
},{
a: "cat1", l: "cat",
u: 250,
},
{
a: "robot1", l: "robot",
d: 600, u: 600
},
{
a: "text", l: "text",
d: 1000, u: 600,
});
p.step.create({
a: "robot2", l: "robot", p: "replace",
u: 600
},{
a: "arm0", l: "arm",
u: 600
},{
a: "cat1", l: "cat", p: "remove",
u: 600,
d: 600,
e: twize.effects.extend("fadeOut", {
easing: function (t) { return t*t } })
},{
a: "cat2", l: "cat", s: "with",
u: 600
});
p.step.create({
a: "arm1", l: "arm", p: "replace",
u: 600
},{
a: "cat3", l: "cat", p: "replace",
u: 400,
d: 100
},{
a: "cat3", l: "cat", p: "remove", s: "after",
u: 800,
d: 200
},{
a: "arm0", l: "arm", p: "replace",
u: 1000,
d: 800
});
p.addArtAssets(
["cat1", "cat1.png"],
["cat2", "cat2.png"],
["cat3", "cat3.png"],
["robot1", "robot1.png"],
["robot2", "robot2.png"],
["text", "text.png"],
["bg", "bg-patterned.png"],
["frame", "frame.png"],
["arm0", "arm0.png"],
["arm1", "arm1.png"]
);
p.art.path('./art/dx/');
p.addArtAssets(
["inset1", "inset1.png"],
["inset2", "inset2.png"],
["inset2-blush", "inset2-blush.png"],
["text1", "text1.png"],
["text2", "text2.png"],
["bg", "animated-bg.gif"]
)
p.addLayers(
"art",
"inset",
"text"
);
p.step.create({
a: "bg", l: "art",
u: s.slow, s: "async",
});
p.step.create({
a: "inset1", l: "inset",
u: s.slow/4,
},{
a: "text1", l: "text",
d: 600,
u: s.slow/4,
});
p.step.create({
a: "inset2", l: "inset",
u: 200,
},{
a: "inset2-blush", l: "inset",
u: s.slow/2, d: 50,
},{
a: "text2", l: "text",
d: 900,
u: s.slow/4,
});
p.destination.main = "[[#DZp1]]";
p.art.path('./art/dz/');
p.addArtAssets(
["cat", "cat.png"],
["end", "end.png"],
);
p.addLayers('art');
p.step.create(
{
a: "cat", l: "art",
u: 1200,
},{
a: "end", l: "art",
d: 400,
u: 2500,
s: "async"
}
);
p.destination.main = "[[end]]";
<%
function sizeCss(square, unit) {
let css = '';
const sizes = {
p1: [1,1],
p5: [1,0.5],
p5v: [0.5,1],
p2: [2,1],
p2v: [1,2],
p3: [3,1],
p3v: [1,3],
p4: [2,2],
p6: [3,2],
p6v: [2,3],
p9: [3,3],
p12: [3,4]
};
const labels = Object.keys(sizes);
labels.forEach(function(p){
const width = square[0]*sizes[p][0]
const height = square[1]*sizes[p][1]
let rule = (
`.passage.${p} .panel {
width: ${width}${unit};
height: ${height}${unit};
}`)
css += rule;
})
return css;
}
function gridSizeCss(square, unit, grid) {
const width = square[0]*grid[0];
const height = square[1]*grid[1];
let css = `#passages.page {
position: relative;
width: ${width}${unit};
height: ${height}${unit};
}`;
return css;
}
function positionCss(square, unit, grid) {
let css = '';
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const rows = alphabet.slice(0, grid[1]).split(/\s*/);
const columns = alphabet.slice(-1*grid[0]).split(/\s*/);
function halver(n){ return [n, n+"h"] }
function reducer(r,e){
r.push(e[0], e[1]);
return r;
}
const halfRows = rows.map(halver).reduce(reducer);
const halfColumns = columns.map(halver).reduce(reducer);
halfRows.forEach((row, rowOffset)=> {
halfColumns.forEach((column, columnOffset)=> {
const left = square[0]*(columnOffset/2);
const top = square[1]*(rowOffset/2)
let rule = (
`.passage.${row}${column} {
position: absolute;
top: ${top}${unit};
left: ${left}${unit};
}`);
css += rule;
})
})
return css;
}
twize.grid = function(hash = {}){
const square = hash.square || [300,300];
const unit = hash.unit || "px"
const grid = hash.grid || [3,4];
const sizeClasses = sizeCss(square,unit);
const posiClasses = positionCss(square,unit,grid);
const gridClass = gridSizeCss(square,unit,grid);
const css = (sizeClasses + posiClasses + gridClass);
let style = document.createElement('style');
style.innerHTML = css;
document.querySelector('body').append(style);
document.querySelector('#passages').className += "page";
}
twize.grid()
window.theReusedPanel = function(p, txt) {
const text = marked(txt);
p.addArtAssets(
{
name: "text",
type: "text",
text
}
);
p.addLayers('text');
p.step.create({
a:'text',l:'text', u:500
})
}
$(document).on('showpassage:after', function(e, data){
const passage = data.passage;
let panelDef = data.passage.name.match(/#(\d)?([A-M]h?[N-Z]h?)(p\d+v?)/);
if (!panelDef) {
const tagDef = _(passage.tags).find((tag)=>{ return tag[0] === "#" })
panelDef = tagDef ? tagDef.match(/#(\d)?([A-M]h?[N-Z]h?)(p\d+v?)/) : null;
}
if (panelDef) {
const [str, page, position, size] = panelDef;
const $p = $('.passage.active')
if (position && size) {
$p.addClass(position).addClass(size);
}
}
})
%>
const text = story.render("end-content");
//
p.addArtAssets(
{
name: "text",
type: "text",
text,
}
);
p.addLayers('text');
p.step.create(
{
a:'text',l:'text', u:500,
},
{
p: "code", code: function() {
$(`.passage:not(.passage--end) .panel`).addClass('faded');
$(`.wand`).toggleClass(`wand`);
$(document).one("click", ".passage--end a", function(e){
if (e.target.className === "replay") {
snabbt($(".passage"), {
fromOpacity: 1,
opacity: 0,
delay: function(i, total) {
return 200+(total - i - 1) * 100;
},
duration: 500,
complete: function(i,t) {
if (i === t-1) {
window.setTimeout(()=>{ story.show("[[#AXp2]]")}, 1000);
}
}
})
} else {
$('.faded').removeClass('faded');
snabbt($(".passage--end"), {
position: [0,-100,0],
fromPosition: [0,0,0],
opacity: 0,
fromOpacity: 1,
duration: 500,
easing: function(t) {return (--t)*t*t+1}
})
}
});
}
}
)
1. PROCESS
I made the drawing for this comic in about an hour and a half on 5-26. Inking, on the whole, ended on the night of 9-16, although I had a couple things to animate and clean up after that.
The two panels that went through the most revisions and saw the most work were the panel of the grocery store and the panel of the lake.
3. ASPEC
During the process of finishing this comic, I started to ... learn? explore? discover? my identity as someone on the asexuality / aromanticism spectrum.
Commentary from July 10th:
"I really want it to be clear that the robot has this really nice fulfilling life and is very happy despite having no idea what love is
that's very important to me, i hope it reads correctly??? I think it does. i'm not trying to be sarcastic or ironic about it in the comic u no
this is an absence and not a lack"
4. INKING
Something extremely weird has happened now that I've finished inking this comic. It looks more ... serious?
Something about the hard, definite lines of this inked comic produces a totally different statement than it did when it was rough sketchy pencil lines.
I really enjoy inking. It's a calm, meditative activity, slightly laborious, but not drudgery: inking is that special kind of flow-inducing labor
## THE LOVE ROBOT
Written and drawn for Twine by Derek Timm-Brock with the Jinx interactive comics engine (0.6.10) in 2019.
<a class="replay" href="javascript:void(0)">Play Again</a> | <a href="javascript:void(0)">Close</a>
<div class="credits">
<p class="credit-header">Thanks to the patrons of Wizard Town for making this comic possible!
</p>
David Brock, Steve Timm, Ian Isaboss, Yung Hui, Kellan Jett, Ben Kicic, Brendan, Craig Park, Sam Fisher
<p class="credit-footer">
<img src="art/patreon-rondel.png" alt="Patreon Logo">
<span>
If you liked this comic and want to see more, please consider <a href="https://www.patreon.com/wizardtown">supporting Wizard Town on Patreon</a>.
</span>
</p>
<div>