From 725845376198ae583ebb7d21fcc5f5e99da1aa9b Mon Sep 17 00:00:00 2001 From: Jeff Clement Date: Sat, 25 Feb 2023 16:38:20 -0700 Subject: [PATCH] initial version --- LICENSE | 2 +- README.md | 19 +++- neko.js | 235 ++++++++++++++++++++++++++++++++++++++++++++++ res/alert.gif | Bin 0 -> 206 bytes res/dead.gif | Bin 0 -> 235 bytes res/dying1.gif | Bin 0 -> 174 bytes res/dying2.gif | Bin 0 -> 180 bytes res/dying3.gif | Bin 0 -> 187 bytes res/dying4.gif | Bin 0 -> 195 bytes res/dying5.gif | Bin 0 -> 205 bytes res/dying6.gif | Bin 0 -> 209 bytes res/erun1.gif | Bin 0 -> 180 bytes res/erun2.gif | Bin 0 -> 176 bytes res/escratch1.gif | Bin 0 -> 179 bytes res/escratch2.gif | Bin 0 -> 172 bytes res/itch1.gif | Bin 0 -> 175 bytes res/itch2.gif | Bin 0 -> 175 bytes res/nerun1.gif | Bin 0 -> 173 bytes res/nerun2.gif | Bin 0 -> 183 bytes res/nrun1.gif | Bin 0 -> 166 bytes res/nrun2.gif | Bin 0 -> 186 bytes res/nscratch1.gif | Bin 0 -> 187 bytes res/nscratch2.gif | Bin 0 -> 182 bytes res/nwrun1.gif | Bin 0 -> 178 bytes res/nwrun2.gif | Bin 0 -> 180 bytes res/serun1.gif | Bin 0 -> 183 bytes res/serun2.gif | Bin 0 -> 184 bytes res/sleep1.gif | Bin 0 -> 156 bytes res/sleep2.gif | Bin 0 -> 159 bytes res/srun1.gif | Bin 0 -> 171 bytes res/srun2.gif | Bin 0 -> 190 bytes res/sscratch1.gif | Bin 0 -> 180 bytes res/sscratch2.gif | Bin 0 -> 183 bytes res/still.gif | Bin 0 -> 170 bytes res/swrun1.gif | Bin 0 -> 178 bytes res/swrun2.gif | Bin 0 -> 181 bytes res/wrun1.gif | Bin 0 -> 180 bytes res/wrun2.gif | Bin 0 -> 174 bytes res/wscratch1.gif | Bin 0 -> 180 bytes res/wscratch2.gif | Bin 0 -> 174 bytes res/yawn.gif | Bin 0 -> 193 bytes 41 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 neko.js create mode 100644 res/alert.gif create mode 100644 res/dead.gif create mode 100644 res/dying1.gif create mode 100644 res/dying2.gif create mode 100644 res/dying3.gif create mode 100644 res/dying4.gif create mode 100644 res/dying5.gif create mode 100644 res/dying6.gif create mode 100644 res/erun1.gif create mode 100644 res/erun2.gif create mode 100644 res/escratch1.gif create mode 100644 res/escratch2.gif create mode 100644 res/itch1.gif create mode 100644 res/itch2.gif create mode 100644 res/nerun1.gif create mode 100644 res/nerun2.gif create mode 100644 res/nrun1.gif create mode 100644 res/nrun2.gif create mode 100644 res/nscratch1.gif create mode 100644 res/nscratch2.gif create mode 100644 res/nwrun1.gif create mode 100644 res/nwrun2.gif create mode 100644 res/serun1.gif create mode 100644 res/serun2.gif create mode 100644 res/sleep1.gif create mode 100644 res/sleep2.gif create mode 100644 res/srun1.gif create mode 100644 res/srun2.gif create mode 100644 res/sscratch1.gif create mode 100644 res/sscratch2.gif create mode 100644 res/still.gif create mode 100644 res/swrun1.gif create mode 100644 res/swrun2.gif create mode 100644 res/wrun1.gif create mode 100644 res/wrun2.gif create mode 100644 res/wscratch1.gif create mode 100644 res/wscratch2.gif create mode 100644 res/yawn.gif diff --git a/LICENSE b/LICENSE index 2071b23..00d0965 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) +Copyright (c) 2023, Jeff Clement Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index c1d86f6..102d71b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,20 @@ # neko -Rough Javascript implementation of the infamous Neko cat \ No newline at end of file +Rough Javascript implementation of the infamous Neko Cat + +## Usage + +```html + +``` + +## Credits + +Thanks to Evert Pot's post for some inspiration on the structure of +Neko's state machine. +https://evertpot.com/neko/ + +The images (which I believe are public domain at this point) were +taken from here: +https://webneko.net/?white + diff --git a/neko.js b/neko.js new file mode 100644 index 0000000..eeeb40e --- /dev/null +++ b/neko.js @@ -0,0 +1,235 @@ +// Description: Neko +// Author: Jeff Clement +// License: MIT + +// Size of the neko, in pixels +const nekoSize = 32; + +// Speed of running animation +const runSpeed = 0.2; + +// The neko statemachine +const stateMachine = { + sleep: { + images: ['sleep1', 'sleep2'], + imageInterval: 1, + click: 'awake', + }, + yawn: { + images: ['yawn'], + nextState: ['sleep'], + nextStateDelay: 1, + }, + awake: { + images: ['alert'], + nextState: ['normal'], + nextStateDelay: 1, + }, + itch: { + images: ['itch1','itch2'], + imageInterval: 0.5, + nextState: ['normal'], + nextStateDelay: 2, + click: 'dying', // OMG. Don't click an itchin' neko! + }, + normal: { + awake: true, + images: ['still'], + nextState: ['normal','normal','normal','itch', 'yawn'], + nextStateDelay: 1, + }, + + nrun: { + awake: true, + imageInterval: runSpeed, + images: ['nrun1','nrun2'], + }, + nerun: { + awake: true, + imageInterval: runSpeed, + images: ['nerun1','nerun2'], + }, + erun: { + awake: true, + imageInterval: runSpeed, + images: ['erun1','erun2'], + }, + serun: { + awake: true, + imageInterval: runSpeed, + images: ['serun1','serun2'], + }, + srun: { + awake: true, + imageInterval: runSpeed, + images: ['srun1','srun2'], + }, + swrun: { + awake: true, + imageInterval: runSpeed, + images: ['swrun1','swrun2'], + }, + wrun: { + awake: true, + imageInterval: runSpeed, + images: ['wrun1','wrun2'], + }, + nwrun: { + awake: true, + imageInterval: runSpeed, + images: ['nwrun1','nwrun2'], + }, + + + dying: { + images: ['alert','dying1','dying2','dying3','dying4','dying5'], + imageInterval: 0.5, + nextState: ['dead'], + nextStateDelay: 3, + }, + dead: { + images: ['dying6'], + imageInterval: 0.5, + }, +} + +// Preload all the images +var images={}; +for(let state in stateMachine) { + stateMachine[state].images.forEach(function(x) { + let img = new Image(nekoSize, nekoSize); + img.src = 'res/'+x+'.gif'; + images[x] = img; + }); +} + +class Neko { + // Neko's current state + state = null; + + // Neko's current animation frame and timer to flip to the next one + animationInterval = null; + animationIndex = 0; + + // Timer to switch to the next state + nextStateDelay = null; + + // where is Neko heading (current mouse position, or last press) + targetX = -1; + targetY = -1; + + constructor(x = window.innerWidth - nekoSize,y = window.innerHeight - nekoSize) { + this.x = x; + this.y = y; + + // build up the placeholder for the neko in the DOM + this.image = new Image(nekoSize, nekoSize); + this.image.style.position = 'fixed'; + this.image.onclick = this.handleClick.bind(this); + document.body.appendChild(this.image); + + // start the movement loop + setInterval(this.update.bind(this), 100); + + // hook into event handlers + window.addEventListener('resize', this.handleResize.bind(this)); + window.addEventListener('mousemove', this.handleMouseMove.bind(this)); + window.addEventListener('touchstart', this.handleTouch.bind(this)); + + // start the neko in the sleep state + this.setState('sleep'); + + // force a resize + this.handleResize(); + } + + setState(state) { + clearInterval(this.animationInterval); + clearTimeout(this.nextStateDelay); + + this.state = state; + this.animationIndex = 0; + + if (stateMachine[state].images.length > 1) { + this.animationInterval = setInterval(this.nextFrame.bind(this), (stateMachine[state].imageInterval || 1) * 1000); + } + + if (stateMachine[state].nextState && stateMachine[state].nextState.length > 0) { + this.nextStateDelay = setTimeout(() => { + this.setState(stateMachine[state].nextState[Math.floor(Math.random() * stateMachine[state].nextState.length)]); + }, (stateMachine[state].nextStateDelay || 1) * 1000); + } + } + + nextFrame() { + this.animationIndex = (this.animationIndex + 1) % stateMachine[this.state].images.length; + } + + handleTouch(event) { + this.targetX = event.touches[0].clientX - nekoSize/2; + this.targetY = event.touches[0].clientY - nekoSize/2; + } + + handleMouseMove(event) { + this.targetX = event.clientX - nekoSize/2; + this.targetY = event.clientY - nekoSize/2; + } + + handleClick() { + if (stateMachine[this.state].click) { + this.setState(stateMachine[this.state].click); + } + } + + handleResize() { + // adjust Neko's X and Y speed based on window size + this.speedX = document.body.clientWidth / 100 * nekoSize/32.0; + this.speedY = document.body.clientHeight / 100 * nekoSize/32.0; + + // keep Neko on the screen + if (this.x > document.body.clientWidth - nekoSize) { + this.x = document.body.clientWidth - nekoSize; + } + if (this.y > document.body.clientHeight - nekoSize) { + this.y = document.body.clientHeight - nekoSize; + } + } + + update() { + const state = stateMachine[this.state]; + if (state.awake) { + + const distanceX = this.targetX - this.x; + const distanceY = this.targetY - this.y; + + // If we're close enough to the target, stop moving + const dx = Math.abs(distanceX) < this.speedX ? 0 : Math.sign(distanceX); + const dy = Math.abs(distanceY) < this.speedY ? 0 : Math.sign(distanceY); + + // determine our new state + var newState = 'normal'; + if (dx == 1 && dy == 0) newState = 'erun'; + if (dx == 1 && dy == 1) newState = 'serun'; + if (dx == 0 && dy == 1) newState = 'srun'; + if (dx == -1 && dy == 1) newState = 'swrun'; + if (dx == -1 && dy == 0) newState = 'wrun'; + if (dx == -1 && dy == -1) newState = 'nwrun'; + if (dx == 0 && dy == -1) newState = 'nrun'; + if (dx == 1 && dy == -1) newState = 'nerun'; + if (newState != this.state) { + this.setState(newState); + } + + // move Neko, if required + this.x += dx * this.speedX; + this.y += dy * this.speedY; + } + + // Draw the neko + this.image.src = images[state.images[this.animationIndex]].src; + this.image.style.top = this.y + 'px'; + this.image.style.left = this.x + 'px'; + } + } + +const neko = new Neko(); diff --git a/res/alert.gif b/res/alert.gif new file mode 100644 index 0000000000000000000000000000000000000000..a135fc310bfbfb3e37834ab7319614ac5f171404 GIT binary patch literal 206 zcmV;<05ShZNk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$0007! zoR6u??SBMh($%=`(CrGqeHCXJ9~c3sMQ-Zqs-&RN$tlNq)NbP|qXAL232r#-bzVmh zlR^tIlTTCBG6mw46r`7%0SN(tplEXQYSD`3n%y3YYjDIi4GzC!`7}~;(r2gU1Os8? zHdS;Oq@@+e$h0N7*X1aaRn;LkiD||{HRmb08D)xidRn*2+UlB60028xs*J0vd9Sds IvJD9UJ5r8Wf&c&j literal 0 HcmV?d00001 diff --git a/res/dead.gif b/res/dead.gif new file mode 100644 index 0000000000000000000000000000000000000000..343052db76170df48fc9e66ce7f3c3bbe1c0f079 GIT binary patch literal 235 zcmZ?wbh9u|RA5kGSi}GVYnYi&aC86v{~yeQ5{f@rI2jmN7<527#+o`j94=pfTuw|`SUD?LkrWzSe25SHtw_?ly literal 0 HcmV?d00001 diff --git a/res/dying1.gif b/res/dying1.gif new file mode 100644 index 0000000000000000000000000000000000000000..e0691b4d8b852ed15d78a63caa0108e9c7f55655 GIT binary patch literal 174 zcmZ?wbh9u|RA5kGn8*ME|Ns97(+r9~SvVOOm>6_GT#!5iQ~i|wm8akGFSbdzy3%1s z$>SxJZYOFNYRp+G;IjPtx_55OWxZZ02fmlsUEWi$>G*}`+E#rhdN&Df=AF+IYV_07 zbmEn#)2^G|JFsodQt@krXBXs3{bJpv@rBw literal 0 HcmV?d00001 diff --git a/res/dying2.gif b/res/dying2.gif new file mode 100644 index 0000000000000000000000000000000000000000..169714bb0f9e673e300e52f400008138ed4b19e9 GIT binary patch literal 180 zcmZ?wbh9u|RA5kGn8*MEYnYk;|NjqUDE?&OWME)s&;f~pFn36p*Wo7AVjD4uI@$yc8yA;!1r`M0|Z{1ArKM@1bhM| zPxjC_navH$T*-_Yym1mblr90zzCYHB74h-!53pJj;7U zvG&%a)7j2hIc>Y=UzxIfO_h9RNmYcMMz7awqr4r>%+1zy@4}9Vn}1LHQ9kX(@?ge} zYr)&w94>`Dacg=atkxzbe6-|JSS3r*XO_-YTT>@Hy6k-X*m9?rc1X2$=kndBqZt^i E0jYabjsO4v literal 0 HcmV?d00001 diff --git a/res/dying6.gif b/res/dying6.gif new file mode 100644 index 0000000000000000000000000000000000000000..b5284082c52a7e7020bdc2fadc347f45fdd5b321 GIT binary patch literal 209 zcmZ?wbh9u|RA5kGn8*MEYnYk;|NjqUDE?&OWME)s&;f~p$T*-_Yym1mblr90zzCYHB74h-!53pJj;7U zvG&%a)7j2hIc>Y=UzxIfO_h9RNmYcMMz7awqr4r>%+1zy@4}9Vn}1LHQ9kX(^58&@ z7iovhK80vJi+CRJyzFI$<%$E6TBj7Es&-B_P)X6c6&#eVwPkCR_|1ea1M@(Q@15VR I0~i>r0TIAexBvhE literal 0 HcmV?d00001 diff --git a/res/erun1.gif b/res/erun1.gif new file mode 100644 index 0000000000000000000000000000000000000000..195d1b2e8812268a285f2935abe5778647a2c6df GIT binary patch literal 180 zcmV;l089TzNk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$0007o zoR6u??GK|oqE1+WwpV2h0$eu;;kl6|iVB^{ww~+7EKP~EeH$O{+r(g@3K6*45Kqfx zDwlGCq)Y^iMiug~&#d+q)g^7-YYA8`enih*YpQG_gG`eb6qujmcHWfn16NnIa1~eQ iVl+|{s3s=CVW()Oa)v`$c}B6A+3EQS8Y((a002Awc1jNb literal 0 HcmV?d00001 diff --git a/res/erun2.gif b/res/erun2.gif new file mode 100644 index 0000000000000000000000000000000000000000..bb871b93973c42ebb9bf9ed6602a2c0e16d3d3ab GIT binary patch literal 176 zcmV;h08jr%Nk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$06+qP zoR6uy0xuX6?g84Y-n_?yN!e9hM)iqOsFa=QYUs&P@k^@u&iAdA;>{Q_TY^%99C0{X zDUiAWnXCzk6mn`Wo1pIt4vSmWuovYOntn=kdz2%-(gSI{?s?OgSANjW=K&H(WprYP eR5;=Uk=W%@X0xUu={Px7_hE?1+39&u0028#+D=vg literal 0 HcmV?d00001 diff --git a/res/escratch1.gif b/res/escratch1.gif new file mode 100644 index 0000000000000000000000000000000000000000..ce892b2b4873676aa1067891d6fa4d27efdec77e GIT binary patch literal 179 zcmV;k08IZ!Nk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$0007n zoR6s|vJaC0E?PC|-6m@uHNf~WAVa2&d3q^XRiLYmj?B@pJ>Z*egZVBr5h<{;G?tVX zC36b_ovI#W`dUt651`SRv|^|`vNqf!*VNAvc5OSSHShJA=lQaq=y08i*0q;4)Wrk_ hRY(MQ7D%Mm6y*40_H@F~D0jKZ+3EQS8j4T=06WF6P5b}= literal 0 HcmV?d00001 diff --git a/res/escratch2.gif b/res/escratch2.gif new file mode 100644 index 0000000000000000000000000000000000000000..cf92cfd359ba31717b12c446a78fa9db30b97d4a GIT binary patch literal 172 zcmV;d08{@*Nk%w1VITk?0FnOy|Ns90006+izyJUMA^8LW00062EC2ui03ZM$0007g zl#i(wu@6%KE?PC|-6m^RaUejFjnIUmSC*-|v8{WG=wg6UXN%Bz9=)K zE8^@)cNnRa;sADzLYU^HL(kIQ3SC&}a!}d6}}w*{M(f06Tj2PEY^< literal 0 HcmV?d00001 diff --git a/res/itch2.gif b/res/itch2.gif new file mode 100644 index 0000000000000000000000000000000000000000..c92541fa9a03defc2ef9875d9d7e9126a2d40c3a GIT binary patch literal 175 zcmV;g08sx&Nk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$0007j zoR6u??GK}zG>IAoxcG3SZQY=KMkr$8hXN^ua;HTQ1q0YB+^aQhH zBL}T8nM3MkI^`LyxS#Vh1q5{1rLxI20vY8ltvW%MybvZyy`d}J?;~W#n d#C6zLmSxd|vl0de(uhT3**LPv+4)ca06WsGO+^3z literal 0 HcmV?d00001 diff --git a/res/nerun1.gif b/res/nerun1.gif new file mode 100644 index 0000000000000000000000000000000000000000..4f53c4bb5f5db12109bece9592f64ea246c2266d GIT binary patch literal 173 zcmV;e08;-)Nk%w1VITk?0FnOy|Ns90006+izyJUMA^8LW00062EC2ui03ZM$0007h zl#dsi?XLh>w8ATboODn8Xq%{6U?NKC8f5L6P9A$kqc_(!&c9$4nW?$yPyhfs4=F}A literal 0 HcmV?d00001 diff --git a/res/nerun2.gif b/res/nerun2.gif new file mode 100644 index 0000000000000000000000000000000000000000..1288849e49735285bebef28baafa0bea68127ede GIT binary patch literal 183 zcmV;o07(BwNk%w1VITk?0FnOy|Ns90006+izyJUMA^8LW00062EC2ui03ZM$0007r zl#i*)?GH_ubVfHp20YwT1>C4*-Y1e9S$;y=m9X}n&Jx(v!e76;^r*?G~2!^)O lCS>=L=O@Sbcj06xgLU@^S$LN=xl@Mena~-^VChl-06V`vPpkj{ literal 0 HcmV?d00001 diff --git a/res/nrun1.gif b/res/nrun1.gif new file mode 100644 index 0000000000000000000000000000000000000000..4d2751f8028d92b2f95ce4f8d3bdc80d2046fcf9 GIT binary patch literal 166 zcmV;X09pS>Nk%w1VITk?0FnOy|Ns90006+izyJUMA^8LW00062EC2ui03ZM$0007a zl#du2>7UpF6vzg%3AJ0TO;*QQ7#LM0wVvqFlIp8?_Dl3Ll5fNC^o}Cn z!gpz!mLSn8$PzwES0@X_1q|t Uc&L}CsK(eBK?pfXc~AfVJDx{HG5`Po literal 0 HcmV?d00001 diff --git a/res/nrun2.gif b/res/nrun2.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ac0b300f9a65381292cdf397d362c8b9e69858f GIT binary patch literal 186 zcmV;r07d^tNk%w1VITk?0FnOy|Ns90006+izyJUMA^8LW00062EC2ui03ZM$0007u zl#du2>3^666i5bBuzT0vby-9$C0KgRD5#Zp#_QP+Htx)f~s;&zim@t9mP>!`z@n4R)nX})LiJ+$AA`D~c`B~u327q|yh oILL?QgC_@<=J*#lhZSk?RS5xe#i_RC0Q#ocLaKI(no|G(JEQJX#sB~S literal 0 HcmV?d00001 diff --git a/res/nscratch1.gif b/res/nscratch1.gif new file mode 100644 index 0000000000000000000000000000000000000000..2ce13f1669bad8d138c171d9f10c4f47fb9dfaa0 GIT binary patch literal 187 zcmV;s07U;sNk%w1VITk?0FnOy|Ns90006+izyJUMA^8LW00062EC2ui03ZM$0007v zlz$e2m6*o~V&xX(mewZ)8hBB%H}?Yu{-%r>9#+Jwv zDz<7Oh)XC<^6?deS8P!E-E^nmDrB6PSkw0?mPGXQ^wq`27a6jb^wY-U`8hNr%EMWTno3as06U=5RdoOW literal 0 HcmV?d00001 diff --git a/res/nscratch2.gif b/res/nscratch2.gif new file mode 100644 index 0000000000000000000000000000000000000000..9c00ed7ad7df15546187c7a2b1d68625192ca906 GIT binary patch literal 182 zcmV;n07?HxNk%w1VITk?0FnOy|Ns90006+izyJUMA^8LW00062EC2ui03ZM$0007o zlz$PnEZdNr4*-~+rkq)*C|cN2!4+B`S(={;qpf>haDB~^qT=?aL-1a`UN8|$8iS!! ztSQp@l(*w!h|5NpsA*~|ohqZpX0mDZP?zQPv+aIMdvABAiQe=rIX_~Y1LMJN5gF5sG3O1k!$Imq%7C=&C~kat4Myqn5^*u7H^iM za_KQWp-s$mS-o7bNoX;vfN{1htIAu}j?q!I(Tg;*;9$raU59AIDv>`Qwg)5#1DKE! gfm2c_#V0hh(B?K4cWC$`ajCP(+3EQSs!#v`J6%OiE&u=k literal 0 HcmV?d00001 diff --git a/res/nwrun2.gif b/res/nwrun2.gif new file mode 100644 index 0000000000000000000000000000000000000000..5627f994b3027bba2868e74ceee6a0078121f89b GIT binary patch literal 180 zcmV;l089TzNk%w1VITk?0FnOy|Ns90006+izyJUMA^8LW00062EC2ui03ZM$0007o zl#i*)?XQBI621U3kULn0O`1k|A2((wX;m1>z3O+!8#$T|CD=I&c~Md-;6=6~-gG-; z^0#UEls3}@G!5NSC}u^)Q7pRe?go2~Ww&+{M@;n)Nbhqq_p(Q*Y;wQVLZ9o_lEPwCm3R4 lL6Kz0NcfN>R;2cbcI7q+@w1_WsTijM8Y((UT53=L06R$}PZajI-wWa3-Gavwx8E8;Gi#k85-IzNxo=_j0@g_745wx--B0{v7LDXZISW6#!Ows>Oa$NdP}y=n)&pcC0eB-~ KNTQff0028MOF;(! literal 0 HcmV?d00001 diff --git a/res/sleep2.gif b/res/sleep2.gif new file mode 100644 index 0000000000000000000000000000000000000000..d9f525a3eab750efb3c7ea8fbba68e333bea2d83 GIT binary patch literal 159 zcmV;Q0AT+|Nk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$0007T zoR6u??GK}zwAzca-n{z{4uTL00GXl3c%~y_0xdPNbuFLj!=8B@lbLpmpzmiC&WgEX z^NDmAlh9~mTCLWYO)7M_Oi+itu9CR=c7tr)!kdiy(4s6gpv%+i+8Zt(Cg%6`2ehZ) Nw*TT`%;@?1zB9%bkjzzY`O8QULUEP2es+p?#w>Q)TiJAh$VR7 Z@|5>i^;Q!Q7q+uSGg5YmnTb*W06Q?NO2_~J literal 0 HcmV?d00001 diff --git a/res/srun2.gif b/res/srun2.gif new file mode 100644 index 0000000000000000000000000000000000000000..46d71de54151d4929543187ad3b71cd71ec4ce40 GIT binary patch literal 190 zcmV;v073spNk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$06+qd zoR1=>xd`JBpxTR{j4JorY!XFb7AcNkxs;Wb8Z6+x^cy>8cEb6DO9X!m97{I*)l3;8 zlG${Ub~c-D)LKFtp_ps=bv|E;Pf~iFq;sTJu(K8&k3gEZ_A#GRTBx1aw{=&=^9NY< sg(!8igJ;MV=mDtbS2jt7*`>4;AUQ~5R<_4>MkfZOsrGovYES?GJA7qPLjV8( literal 0 HcmV?d00001 diff --git a/res/sscratch1.gif b/res/sscratch1.gif new file mode 100644 index 0000000000000000000000000000000000000000..485ececf82b3900043e6620e708174bb1090bab1 GIT binary patch literal 180 zcmV;l089TzNk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$0007o zoR6u?og$oM0)RO4s1|F-UEjocqXI!)dLp3(ckLF}u$jGfjD!0xBJp;w-Xc`dC2u5T z=k{DRRF`VhS}pZ-*zB-|ONqhMn;0VD5>INI(FbIXoZsMw4wcRGc{IBgK-N;`W_Pzy imZCSefyh!a*ys@f$tHO~nG{Khc{$^G`SzJn0028q!cY|e literal 0 HcmV?d00001 diff --git a/res/sscratch2.gif b/res/sscratch2.gif new file mode 100644 index 0000000000000000000000000000000000000000..2e7c08e6115efa8632b5b3f55aca236abbef1693 GIT binary patch literal 183 zcmV;o07(BwNk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$0007r zoR6u?JtCZB0)RL(v=--Cao*>I7ui5tr=p0-#it9)@d(;__tpEYx#?gyis&M%n2L%O z^7&jc4J+lba|}V6HX`)Pd#O}OCu=-C_=dC}5Vh{MvBEHEnH15qd3&!GkmT|Jc9WKJ lCbD&Cbb|H(ITztE83}h$Nd?JBv8m=cSV?I)Sb9(Z06S|pPVN8z literal 0 HcmV?d00001 diff --git a/res/still.gif b/res/still.gif new file mode 100644 index 0000000000000000000000000000000000000000..e534a2ad5021d48238923b0f9c04622659c36e6c GIT binary patch literal 170 zcmV;b09F4-Nk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$0007e zoR6u??GK|oV%4bxxOC&Bc}B>6p*Wo7bb9R?wVNQrj|}8`ZaeC}(e)a?oysHx9x*r| z4@nCJcr+Btsr+=XR&7*B(^`b$v9XM34rAPItkQgj*)yY&1bG$fWS=t0ljTztSQtbV YHJ4U{Xy~|-7#Su>xrTO$iBeJKd1@nBwk^fb!zIghhsIxidMQjJVveP$iC9R@ zOnD47lM*0Gq=QDCK`2v-?N+bc@>F=hk;$I0NNaUdhnYaUJm=lNdHN5$Mg)=4hQ-8z gl*k67xYTFi@*@aSBGk4+IfR+X+3EQSnos}$J0HSMssI20 literal 0 HcmV?d00001 diff --git a/res/swrun2.gif b/res/swrun2.gif new file mode 100644 index 0000000000000000000000000000000000000000..3614ea82678879f359ed54f8bdb6ec7b4ecdad8b GIT binary patch literal 181 zcmV;m080NyNk%w1VITk?0FnOy|NsC00RI300KmY&A^8LW00093EC2ui03ZM$06+qU zoR6u?EC5~<62?`nj(fI4SyTuK-|3K=IgAwORav*ONGO+`jY_tU3JQlGUkO%vVOT2K zN|CG0YK^J$7__diLK0I%42#F)rHdyvCcn?DdITP7chKKtPEYun_&D^cLxZLV$kA5S jVyFn`ck&Rmb>gd?FcS z;z_&orbp%LDV!!zqbyVVz)~gSOsGsoixNPw49&VqnNJ=(W9u&5@We3eRkoFK_ori% ig++r^*E7iBXD7pU;^g&6!KjJ()9LvM8Y=2p0028Rz*H{) literal 0 HcmV?d00001 diff --git a/res/wscratch2.gif b/res/wscratch2.gif new file mode 100644 index 0000000000000000000000000000000000000000..79310681fd86b22f5dec56145fde99c1cecaf054 GIT binary patch literal 174 zcmV;f08#%(Nk%w1VITk?0FnOy|Ns90006+izyJUMA^8LW00062EC2ui03ZM$0007i zlpk@+?Hqu5w2COLO$%rJBuWC5B?m&H$)0IPw(az;lI*_M&C7HeA$exH-D$}Bfsip% zP^5G;aa2_3f}|2R(`5Eju_d+O@Qj=@JJIPd=8KC;#b_&+om}?t@<#9&=h0^X1r>+o c6e1xwV<$rKR8@pfSUGu#nW?$S$yopZJ2aq5VgLXD literal 0 HcmV?d00001 diff --git a/res/yawn.gif b/res/yawn.gif new file mode 100644 index 0000000000000000000000000000000000000000..4b3e56479bc6a7b27126ba907570bf7b33cc3552 GIT binary patch literal 193 zcmZ?wbhEHbRA5kGSoELaKM(*328IR(5IAt)0GMV_{K>+|z`)9&1LA_zGBCGA?7H*M z;FRa;*e6e4bKJOb+;rZGDGwrM9i0`oT4I0bA3-zQ%8I_t(FiJF!^4G4p zk$bt7)6y`NRI#(YQSMC+2EXSWO8xw@@^WqLE5B=JH<~{F_Q85`e$Zs|Fk_AACLga% mLCeIRChMGb*AClyo*b{qGn)FQO_^6Se_`R`B}@4^8LR