From 2c1185cc9f164cb4ea70aa37a544c9e7c7fc9385 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Tue, 29 Dec 2020 20:31:35 -0800 Subject: [PATCH] Doodads: Warp Doors, Bird, Larger State Blocks * The blue and orange ON/OFF state blocks have all been increased in size to better match the player character (42x42 up from 33x33) * Added a new mob: the Red Bird. It flies back and forth while maintaining its altitude, similar to the Red Azulian. Planned AI behavior is to divebomb the player when it gets close. Dive sprites are included but not yet hooked up in JavaScript. * Warp Doors! (WIP). They have a golden "W" on them and come in three varieties: Brown, Blue and Orange. The blue and orange ones are sensitive to the State Block and will become dotted outlines when inactive (and can not be entered in this state). The door opens for the player character, makes him disappear, then closes again. The plan is it will then warp you to the location of a linked Warp Door elsewhere on the level, but for now it will just make the player re-appear after completing the Close Door animation. --- dev-assets/doodads/bird/bird.js | 54 ++++++++++++ dev-assets/doodads/bird/dive-left.png | Bin 0 -> 959 bytes dev-assets/doodads/bird/dive-right.png | Bin 0 -> 989 bytes dev-assets/doodads/bird/left-1.png | Bin 0 -> 1074 bytes dev-assets/doodads/bird/left-2.png | Bin 0 -> 1022 bytes dev-assets/doodads/bird/right-1.png | Bin 0 -> 1089 bytes dev-assets/doodads/bird/right-2.png | Bin 0 -> 1028 bytes dev-assets/doodads/build.sh | 35 ++++++++ dev-assets/doodads/on-off/blue-button.png | Bin 741 -> 785 bytes dev-assets/doodads/on-off/blue-off.png | Bin 648 -> 668 bytes dev-assets/doodads/on-off/blue-on.png | Bin 683 -> 713 bytes dev-assets/doodads/on-off/orange-button.png | Bin 751 -> 805 bytes dev-assets/doodads/on-off/orange-off.png | Bin 650 -> 669 bytes dev-assets/doodads/on-off/orange-on.png | Bin 687 -> 717 bytes dev-assets/doodads/on-off/state-block-blue.js | 2 +- .../doodads/on-off/state-block-orange.js | 2 +- dev-assets/doodads/on-off/state-button.js | 2 +- dev-assets/doodads/warp-door/blue-1.png | Bin 0 -> 850 bytes dev-assets/doodads/warp-door/blue-2.png | Bin 0 -> 976 bytes dev-assets/doodads/warp-door/blue-3.png | Bin 0 -> 934 bytes dev-assets/doodads/warp-door/blue-4.png | Bin 0 -> 807 bytes dev-assets/doodads/warp-door/blue-off.png | Bin 0 -> 685 bytes dev-assets/doodads/warp-door/door-1.png | Bin 0 -> 891 bytes dev-assets/doodads/warp-door/door-2.png | Bin 0 -> 1003 bytes dev-assets/doodads/warp-door/door-3.png | Bin 0 -> 957 bytes dev-assets/doodads/warp-door/door-4.png | Bin 0 -> 830 bytes dev-assets/doodads/warp-door/orange-1.png | Bin 0 -> 832 bytes dev-assets/doodads/warp-door/orange-2.png | Bin 0 -> 967 bytes dev-assets/doodads/warp-door/orange-3.png | Bin 0 -> 922 bytes dev-assets/doodads/warp-door/orange-4.png | Bin 0 -> 803 bytes dev-assets/doodads/warp-door/orange-off.png | Bin 0 -> 687 bytes dev-assets/doodads/warp-door/warp-door.js | 81 ++++++++++++++++++ pkg/uix/actor.go | 17 ++++ pkg/uix/canvas_actors.go | 6 ++ 34 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 dev-assets/doodads/bird/bird.js create mode 100644 dev-assets/doodads/bird/dive-left.png create mode 100644 dev-assets/doodads/bird/dive-right.png create mode 100644 dev-assets/doodads/bird/left-1.png create mode 100644 dev-assets/doodads/bird/left-2.png create mode 100644 dev-assets/doodads/bird/right-1.png create mode 100644 dev-assets/doodads/bird/right-2.png create mode 100644 dev-assets/doodads/warp-door/blue-1.png create mode 100644 dev-assets/doodads/warp-door/blue-2.png create mode 100644 dev-assets/doodads/warp-door/blue-3.png create mode 100644 dev-assets/doodads/warp-door/blue-4.png create mode 100644 dev-assets/doodads/warp-door/blue-off.png create mode 100644 dev-assets/doodads/warp-door/door-1.png create mode 100644 dev-assets/doodads/warp-door/door-2.png create mode 100644 dev-assets/doodads/warp-door/door-3.png create mode 100644 dev-assets/doodads/warp-door/door-4.png create mode 100644 dev-assets/doodads/warp-door/orange-1.png create mode 100644 dev-assets/doodads/warp-door/orange-2.png create mode 100644 dev-assets/doodads/warp-door/orange-3.png create mode 100644 dev-assets/doodads/warp-door/orange-4.png create mode 100644 dev-assets/doodads/warp-door/orange-off.png create mode 100644 dev-assets/doodads/warp-door/warp-door.js diff --git a/dev-assets/doodads/bird/bird.js b/dev-assets/doodads/bird/bird.js new file mode 100644 index 0000000..ca8db3e --- /dev/null +++ b/dev-assets/doodads/bird/bird.js @@ -0,0 +1,54 @@ +// Red bird mob. +function main() { + var speed = 4; + var Vx = Vy = 0; + var altitude = Self.Position().Y; // original height in the level + + console.log("Bird altitude is %d", altitude); + + var direction = "left"; + var states = { + flying: 0, + diving: 1, + }; + var state = states.flying; + + Self.SetMobile(true); + Self.SetGravity(false); + Self.SetHitbox(0, 10, 46, 32); + Self.AddAnimation("fly-left", 100, ["left-1", "left-2"]); + Self.AddAnimation("fly-right", 100, ["right-1", "right-2"]); + + Events.OnCollide(function(e) { + if (e.Actor.IsMobile() && e.InHitbox) { + return false; + } + }); + + // Sample our X position every few frames and detect if we've hit a solid wall. + var sampleTick = 0; + var sampleRate = 2; + var lastSampledX = 0; + var lastSampledY = 0; + + setInterval(function() { + if (sampleTick % sampleRate === 0) { + var curX = Self.Position().X; + var delta = Math.abs(curX - lastSampledX); + if (delta < 5) { + direction = direction === "right" ? "left" : "right"; + } + lastSampledX = curX; + } + sampleTick++; + + // TODO: Vector() requires floats, pain in the butt for JS, + // the JS API should be friendlier and custom... + var Vx = parseFloat(speed * (direction === "left" ? -1 : 1)); + Self.SetVelocity(Vector(Vx, 0.0)); + + if (!Self.IsAnimating()) { + Self.PlayAnimation("fly-"+direction, null); + } + }, 100); +} diff --git a/dev-assets/doodads/bird/dive-left.png b/dev-assets/doodads/bird/dive-left.png new file mode 100644 index 0000000000000000000000000000000000000000..4ec579457c580c56832f39711b802c3e8934c173 GIT binary patch literal 959 zcmV;w13>(VP)nAwr0004mX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00EatL_t(o!_}BgZiFxlh3ye1sgx6R(W}e}!c9i%5y)Xm zXW3$IEj7p;D2xG@qk$2xlm=mIz=R><^p*dYHgF z06IQ!Lg-6TdglNDz`#jLDoqI#Z;B*`bKnyzjai`;V9(C`h5OqTwk9VuD9{qt%4JYP zac+$zg(a*P^KAqd=1_Ub4wlUuMd>z@sY$7__L!}5%_vV}3v|-f-A#i6V^HEy-dimW ztx(cLsN9!So40RTP%?+o`xR%&AtSGZ(!2L6J^<~-oMEFcy%_)Or8ih*9$liX>?MWL z(kdmC{U(qV+kG{XX(3k&shzYB_*w%tp!6o$f&v<;gRqTXo;2QMn4G#J3TJ`v> h@=>8x@FT0t>leO(W1=r>n6Ll<002ovPDHLkV1h7|sd)eZ literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/bird/dive-right.png b/dev-assets/doodads/bird/dive-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8516ae34ad22c02511c88a89b7da341e8d23e063 GIT binary patch literal 989 zcmV<310wv1P)nAwr0004mX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00Fg0L_t(o!`+zCZG$inhVP>6QK^#E5%Su07&Ag72B_2# z@GwnZyMmFBGRgHJIK3DfYy-yBk`)IB^4-txI|D*OBPq#@Q7MGIG?J1C;MQ3X#kZ!1 z*8c@QX8?z}7Z7Hk)V>s_z1hYF&utqF0rbtixhw+!t@$qHYUwfd$*P zcV^a!DnM0#hg5G9-i6~1w9HPjlpLO_ytY)&Ua$9y%JJ@2?YOD?q7_f`V7q=I=Kz;smen zKUfsF%kN!%`+R;HhcEWs_PGWcgFloC{`mpeT>-i)?6;lk;X?fdG(ML9`pVy300000 LNkvXXu0mjf-QB)C literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/bird/left-1.png b/dev-assets/doodads/bird/left-1.png new file mode 100644 index 0000000000000000000000000000000000000000..e3c6e50c07e60cc2e42ff88566d7a96ae4c3de7b GIT binary patch literal 1074 zcmV-21kL-2P)nAwr0004mX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00Ih0L_t(o!|hl>Zo)7ST%){$N|pQu(i0V5K{EY8rAj^V ziQ=m7=%oT~g(oz=^&{Iu?8q!$XG4K-$Vw|&v5aTOg>(Twy0n&EB#U^g z8QEN2l}e-rl|^33=~M<1SrP<->nAwr0004mX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00GuXL_t(o!|hi~Zo?oDeN?_jrAnM3%QQI*IYOn}#B-5u zsyN#mq2@4jVX(${Ft|~E5>G-hX0V4hZw3G=Dk>@}Dk{pMUd2&ojN|>cm!g?yX!l?| zW(oilky<^E2-ZJ#0GgXS>KU>C^xDPvxdGaLr-*UsC;Ue#M+3OSQh$7B%=8`6Y+i7l zN*Q#(v@vJJalrM_bDyy3Gw*o62VCo$$}&wfOalPL%sE3Ob0D$12A0VqFn!3WBrplz zMhML1m=&8bPKs79M9eX!XLbC1+Dx>%-Cv*vkD)x%&bcY;0;>dImtlI;Ylxb!7&>9s z2~0P^>0f)9OxlK(spZIM!FintxsDUi7-%LpZkI~L=6u??@1McxkM~F}vr?jx&O=}w zk)!bx(T)3qB(TbN`^WiBLC%65{> zK3T6mWQ7bisbfRbHw%fy$E_d}%UEA?ELhEaE6BgiFrO=-eWL88P;^!))g3KFfD){0 zVgBKf$L&_wrrXS>HQE$t{if$}Vj2%D5@Vg0M(Zn*dDa_HY0~H9a`zh$XWlZs^XC#g s)Tfn7N;;{nAwr0004mX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00J3FL_t(o!|hm0Zo)7SeMX$4JFB~Hp*w=Q={b-bj!;!% zRjE>MKwNQ^R$T#CNTf>bMchRkY8-#Y5GblLk`CwRsV9_aA2aZo zYg}ZLYMA#aPBb!&HkX#vDbH{Fo~iAwu|A13O9^#={xfp|!U{1pywXUa6xLg*sWe{3 z=qlve70VcNMk@l(NSl>5)QdmLJPXw#JfzFSg;x>Y)3D7L)7`qS0DQcS_S`1ZE%O4m z<&F~oQB%zO+yK721wa=2Zr6N-$#lzDtO_LQb3%ELTtyqeKfmhh{oM%B?H$&_I~Gi; zu0K5f_FtaU%WxEwN|4w}qMuFP!6zW;*g=y+udnZscf=|iGVq%PFuv04ZveJB40PTW z1SM#GX~5TuI$S2``Km4zq^FKaVUFsPZ0iM-dac`X29>fFLOFVt!}4+lm5=NG=DWV$ zKDo!*VDkeGnAwr0004mX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00G=dL_t(o!|j++j)E`{hW~E73TNbw zHvrY~qyhl%u`~jC)ZP)f4Y=tj~v-hl>g02C`$3aIENJcXAeF&pIxnb!X z6Oj}_SSH#4)Btn^h~jT*OXu1(?OBozW|q94ysr}H6Yz|dNNs^8pXc;>YEty;+_R6F zJPE|E3N?|IArj&d1%O~6@1zOTLcWhEMjCyjRn3rZ0rW7(WbApqdRL8G<%BR;AkP z{gv((b1U+82X6Ncm-Ci3Qyp72u;(elOi1K&!?keVy6|uJp?x|&pq`GMy-M)KsFldn z<|S4uo0di0Ko7!Z(dS&rZB8&`lykBni-=doeR=1^%jDHi+NMZL1e=AV&BPCJTMz^~ z8ttXzR@s-5_asr5DCOG+3%S?!<1_LxXY*>(XT(w|ZP%hW_2rau(6WdQhIg&9AGd6p yIBi}T-fh}!+zTHj{G(~J@t{yg_O$~&Rd+-QiV0{$zK@EYAefJr#XNa7O?~gA{10mLKwuZBS8emj&ZNzqd+D9^ zR>`FDic}5>I=`B~#^)C6Yk?!31|G|L2{M1NE;GYRUxJkD{H>K)O~x-&Ww9pm(jF@h zV11%p=+QcIlhtE;aL}29A-Z8lW^@d;J2!k0O2)@e2rN zy|dm~-{){A`$7%{SND6z3i%z!v_+zj7nVT+zzg4ci!#7T^;iG^002ovPDHLkV1j9Y BJDUIi delta 623 zcmV-#0+9WY2IU1IiBL{Q4GJ0x0000DNk~Le0000X0000X2nGNE09WL~Z;>G&99yL# z6$dLw5y?=UEQnt?Y88r5A=C=3I+$Gg1(97Ce{pqEbdeJOmlRsWcyQd0clRE5?*MyH6ykH@QG+f>{K$3L6rkzP=YjV#`lc+_ zarywHsjK7-aBv8W6exS$mj&;|v}a4-Y23(7luE z0VsdHNklZ%WEfO zosjE@7c!A}?eNaZJ1g(3JUe~@Vg8OaMz*+ApN~M$K@$pAzaMXgZVAa#Eh+#2002ov JPDHLkV1fm16lDMa diff --git a/dev-assets/doodads/on-off/blue-off.png b/dev-assets/doodads/on-off/blue-off.png index 6275e2b86b300a6edcee0eb6ce5994a426b301bf..1375fe6ff54ff1d623f211ec694ea71c212fa493 100644 GIT binary patch delta 550 zcmV+>0@?kD1)K#TiBL{Q4GJ0x0000DNk~Le0000g0000g2nGNE0L8<}Tah6k98;wt z6$cB7C}gODU`15KQL9jd3ZYhL)xqTY36WhGe{ytEbdeJOmlRsWcyQd0clRE5?*O4z zVyf9T4yc-CBw|r9m0lGCuLxogy%@om%uIbwlH%|jU-$6w^)AA*ywCkPx-wal0X~s< zmg$B?yg@v@Y3ZEzi9@U)XNb>yg_O$~&Rd+-QiV0{$zK@EYAefJr#XNa7O?~gA{10mLKwuZBS8emj&M#x+KYuk?WI&maORkUE=k6V*2U4gB&pet+L!uY zXN_7+FUZ8m7O6wt!uqxKiMk0}Q)Wk_N=JjG0<6b+0IbJ)f&%b7VLbrWV?AJf5$nC= o%Voh?k*G&99yL# z6$dLw5y?=UEQnt?Y88r5A=C=3I+$Gg1(97Ce{pqEbdeJOmlRsWcyQd0clRE5?*MyH6ykH@QG+f>{K$3L6rkzP=YjV#`lc+_ zarywHsjK7-aBv8W6exS$mj&;|v}a4i_xRd8(7^ z0Vs7~Nkl zB;(!sZGqLLUyg_O$~&Rd+-QiV0{$zK@EYAefJr#XNa7O?~gA{10mLKwuZBS8emj&*mT7d`W2gD)3mS+EsCW)P_Y}2f^@8wao znIxHO$PKJ5kl86@9>EF)QMtE+U8STyV#?DCOHw*Wk(Xn_Ts@$G#(SRTs=KO}WB8dU zCO}=8k_Scdy(zgPObMWXMm8n4svc89jsiCt)RfREAx8lP)Uhd{QxeRStmB(5`=x9u h8&7l^I(dbZqyZj~JkY7}w=4hv002ovPDHLkV1fp955oWe delta 565 zcmV-50?Pf#1*-)iiBL{Q4GJ0x0000DNk~Le0000X0000X2nGNE09WL~Z;>G&99yL# z6$dLw5y?=UEQnt?Y88r5A=C=3I+$Gg1(97Ce{pqEbdeJOmlRsWcyQd0clRE5?*MyH6ykH@QG+f>{K$3L6rkzP=YjV#`lc+_ zarywHsjK7-aBv8W6exS$mj&;|v}a4mgJxMDvsD z0VsciNklyg_O$~&Rd+-QiV0{$zK@EYAefJr#XNa7O?~gA{10mLKwuZBS8emj&5i9_Ib2ZqyeM`O;O?-(T)k(v}_&8L4EQ&W9vtYI>SZx;RuR+OW)FiFAQ%F&*S zJo#(+n2B)DajMrcKV*5*fb9ZQ67J!Lk{IMn4m*_GVV0#IC|Qy2F5M0#wa`ho$gA71 zT1-b1YM9i#V;2xsidZRP7Z9d;Q@yFaOcJVdL|$M0000G&99yL# z6$dLw5y?=UEQnt?Y88r5A=C=3I+$Gg1(97Ce{pqEbdeJOmlRsWcyQd0clRE5?*MyH6ykH@QG+f>{K$3L6rkzP=YjV#`lc+_ zarywHsjK7-aBv8W6exS$mj&;|v}a5Df+DzYmk^ z0VsdRNklyg_O$~&Rd+-QiV0{$zK@EYAefJr#XNa7O?~gA{10mLKwuZBS8emj&M#x+KWOd_EIV&bmo|YE=k6Vp+P^?B`KQXUVBsj z>a1Dw>ViznY|b3=8aAF5|APPk delta 531 zcmV+u0_^>r1&ReBiBL{Q4GJ0x0000DNk~Le0000X0000X2nGNE09WL~Z;>G&99yL# z6$dLw5y?=UEQnt?Y88r5A=C=3I+$Gg1(97Ce{pqEbdeJOmlRsWcyQd0clRE5?*MyH6ykH@QG+f>{K$3L6rkzP=YjV#`lc+_ zarywHsjK7-aBv8W6exS$mj&;|v}a4<=*`NYRt) z0VsE3NklM#x+DnBZ_Sn_K%*h175Oyp*^h>>(>RpfXU;R;g zzL;dZ>sR?002ovPDHLkV1h=i=;r_c diff --git a/dev-assets/doodads/on-off/orange-on.png b/dev-assets/doodads/on-off/orange-on.png index c56e09ea48740edbc0566598f7bc56349fb234f1..0aaae4483f1b837767606b1e09ef9f1bffbc9424 100644 GIT binary patch delta 599 zcmV-d0;v731yg_O$~&Rd+-QiV0{$zK@EYAefJr#XNa7O?~gA{10mLKwuZBS8emj& zgOU{jpbl0c@37J#vrWj{xB{FgYCF)BlD_MiG4bibbwV$Z*)eWXPf&uoJDz&iz18Fx z-b`#Jf?6^qUz+51Q!*l&5`q%cwJ8~Ddzw2E)+j-Jni9U0uto_=P|K!-FD1@W-@kA2 lVHa}QAOW~OovcCvzzIj-JkS&;1(W~)002ovPDHLkV1lU45qbas delta 569 zcmV-90>=H#1+N7miBL{Q4GJ0x0000DNk~Le0000X0000X2nGNE09WL~Z;>G&99yL# z6$dLw5y?=UEQnt?Y88r5A=C=3I+$Gg1(97Ce{pqEbdeJOmlRsWcyQd0clRE5?*MyH6ykH@QG+f>{K$3L6rkzP=YjV#`lc+_ zarywHsjK7-aBv8W6exS$mj&;|v}a4>JkTtU8nH z0VscmNkl43uuxuR=Xa5OC006)V$o?tLv-{&&00000NkvXX Hu0mjfCe-zB diff --git a/dev-assets/doodads/on-off/state-block-blue.js b/dev-assets/doodads/on-off/state-block-blue.js index f09f5cc..b754ea7 100644 --- a/dev-assets/doodads/on-off/state-block-blue.js +++ b/dev-assets/doodads/on-off/state-block-blue.js @@ -1,6 +1,6 @@ // Blue State Block function main() { - Self.SetHitbox(0, 0, 33, 33); + Self.SetHitbox(0, 0, 42, 42); // Blue block is ON by default. var state = true; diff --git a/dev-assets/doodads/on-off/state-block-orange.js b/dev-assets/doodads/on-off/state-block-orange.js index dfea8b7..8989f73 100644 --- a/dev-assets/doodads/on-off/state-block-orange.js +++ b/dev-assets/doodads/on-off/state-block-orange.js @@ -1,6 +1,6 @@ // Orange State Block function main() { - Self.SetHitbox(0, 0, 33, 33); + Self.SetHitbox(0, 0, 42, 42); // Orange block is OFF by default. var state = false; diff --git a/dev-assets/doodads/on-off/state-button.js b/dev-assets/doodads/on-off/state-button.js index 85084d8..c5e7bd7 100644 --- a/dev-assets/doodads/on-off/state-button.js +++ b/dev-assets/doodads/on-off/state-button.js @@ -5,7 +5,7 @@ var state = false; function main() { console.log("%s ID '%s' initialized!", Self.Title, Self.ID()); - Self.SetHitbox(0, 0, 33, 33); + Self.SetHitbox(0, 0, 42, 42); // When the button is activated, don't keep toggling state until we're not // being touched again. diff --git a/dev-assets/doodads/warp-door/blue-1.png b/dev-assets/doodads/warp-door/blue-1.png new file mode 100644 index 0000000000000000000000000000000000000000..4921faf009a01c159aa4600a311711628302e041 GIT binary patch literal 850 zcmV-Y1FigtP)EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00AmVL_t(&-tE~x4uUWg2Jr6@PEtmW;DVQ7(Vdfcp0aQR zMtYSx7?F?$`xGd~uagj({@x!5ML{!o9AM-C0AtcBoI{3#jKe_kP@1C0yrf^u&7&3w zUIW0bHpIrm-_VcR|CY}%~Ti08fVNjB7wc~*QaXuC)BQ-C%bKk#IIlNAdY zv+;~PbZ%3~6f<2gbZ(c@gce*v*iv9iSvMovVM{@E!dSu(INK8e0M!Y&48j+q^pJD! zacy45*9N#1K25XU3J)~$`km^oSpu+G;~!}JcY-}a2qARf9L;wH) literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/warp-door/blue-2.png b/dev-assets/doodads/warp-door/blue-2.png new file mode 100644 index 0000000000000000000000000000000000000000..ca96abffa8d3aaf3cdcc4cd54da1584cdbd469e6 GIT binary patch literal 976 zcmV;>126oEP)EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00F2;L_t(&-tC&fal$YVMZXv-k&h{X3vR}j6hH@=NddW} z22M0!E|lOSnn@+f0YoMX#?r1N%&gpup8_J=H=6Z~8UC)&XaL2l$a1UKKlh#S#0 z!UWc5oMKtwM6~EB-2VlLrhU;NOY036xZ3mAY zfOpOt@28z^33QRkAyzfpa`D*-Q zJG6TMFWfvkcRenxlA4qmZFUgBj5fa`%o(kI>B&GQD!<&DHL>#Zf(Va0@;aiY6AGdr z3Zftiq9BqMvUblpChV#=&vC+KK?Kw1Cp{*SHg4=sPQeHq0NRiL6Qcenxo0geJPndi ya8x)|oLwW5Un~MCDSRJagzwS-0000EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00DkUL_t(&-tE}CZNo4S2H>B9C!tD@kj4hmW(}>N8SGw- zXGoO=s3ID{rML=HP=rN2oJis6WZ(!Gkmy1m$m4-`3T5lCgK+==X#JS6*1u~27UTIa z!vEF+m;8TykRJY;Y>o&~4*$cZ2wV)$`aD43(d`R?Px9R2(04KUxS zAv1ZRZZHba&oBQA&uLFh520>ubV9;v06>*@&!s|jO}Qcyoq)RWTha$a-2(uXYU%UH z`R-t#rV;NtX}VvYM~M0;ze1vIA#CPk+$$kh#TSNHy8}qb6RZ%Xeyenz<@gFjAOaDH zK%VzXAU!lv#Bzw8xI|s@jUmIkNozU;8FTtcVdB#5_dP2Ik)&42Us=2{BRE z@E~Fcah_OT`)-JsuYEU0OxL~)h;i-9gm^%h5kSA;Tehr_ALf*cyDF3EjQ{`u07*qo IM6N<$g5M{fga7~l literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/warp-door/blue-4.png b/dev-assets/doodads/warp-door/blue-4.png new file mode 100644 index 0000000000000000000000000000000000000000..f67689027d0c5b5f07bf67528566ed6ca33bf68b GIT binary patch literal 807 zcmV+?1K9kDP)EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{0093c)P!NfhHCVwjK%a&g zsHl-b5k{c&tzwGAmV$&u<#VKeRop$@oh_eZ;Cw&@u?7GfEFb_x#_xv!=cb&(d8|-L z5JCtcgb+dqA%vum8X(rPG&4xQG0G4D!pZ1oL>rMH&)2wU-$B1e%r(^0tf^^_4f;W0 z(u*aDyJo+gKm*Y3N{*aU-0qk`;<`AbYofK zkZ*`(MhGE<5JCtcgb+gbs+foHRq@xPS9k!gFeAe4n;F6t`hzFyLLiF$!O~<7G~KeW lGz)+z_XiMv3OKJ0`2Y-DH&eP%^%ejC002ovPDHLkV1j~zUIG9B literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/warp-door/blue-off.png b/dev-assets/doodads/warp-door/blue-off.png new file mode 100644 index 0000000000000000000000000000000000000000..a42b51c5f461a5f2c849fa3b354a0cc27c9c6dc5 GIT binary patch literal 685 zcmV;e0#f~nP)EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{004zaL_t(&-tF2=4nQyvfYIq(#UY)+A)SQ{;x8f=)y4aE zgtTeqSt+sBk5dd?Ib5&3x&P&z-I{rMuy)JZ`RgX`PE4&;9u-uajcnya(ol#RYD5h+ zqJ|n#Lyd$lzM_U2QA3TWp@te!Lyf4RMs2I9^+Vh?thLGBHFPC^`F@->5fL#1R^4hQ T!A`5E00000NkvXXu0mjfc{M4- literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/warp-door/door-1.png b/dev-assets/doodads/warp-door/door-1.png new file mode 100644 index 0000000000000000000000000000000000000000..e057d24d6b8a9db586c99f43efc3c66d85efeef9 GIT binary patch literal 891 zcmV->1BCpEP)EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00C1;L_t(&-tCz&Zo)tiML*7#AQ7cVKuCy|E6|w3&{5IQ z<^;X~wGTn(#)TVBfq+zLpj$x-WJ9b)>?~j#^nd5oj{N5Dcs*;^hFu&`0Vx1zeX3F+ z);}5^Dx%7OD3eXL$}j0HvC3wWNu94YmYdbxVp$^uAqYVTLJ)!wgdhYV$kU%|(stif zuCcXY7YCkwU1}suG{VIGNGY9f4HCujEG04GrLoCU;)EDvHc_Gsqxcx}(0$}Q<9sc+ zxFH6~yAmcEQGCq)96;(u^>@~5t{~8v8(HS2F@fHCO?)@%GGi8V43Tc`ej`<0W0cl~ z38Jv4<`MvlRrIdm-wDEX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00F~EL_t(&-tC&bZNoqeg(>3}NaY_G&=@J)NOPq20v<#Q zxK@`c3q*|zjS(P-qACj<;1tRw##yq+BTrEfva}C;pC2iKqMYO@oM8rG007oYgF4)_ z7BJ`CIsfc-wSm|7H)vW5&o4jc^YjY@lh7q~$*|%iN2C&l01Sd~6NbhDW)cdbAPS-& z3Zfti@^3*VnSi#d&F_Ht!hJJtR1gP%5sn73UYa0)pk~F?8UUcIEtIvDb0nnJE~=A2 zX*jiZP8<)02hvw-m;B-0L~#S%BO!^SfH<4|2K1XUv@E2nX2=!)^HBHDAigVQZNEjS zmn!>)R-FK{-8CE(mQ@z9JL~aa0E%H(_Qg2lf-LBjrSE$mBHMLN?r*@79dQ7@D5fNj zPlAI{Xb+4}bV7I6GQ#M?$Ya zebQrrjCFprF@W0nq9EMY9ioot+X)3x5Cu^X1yK-2jBO;%RKjC3jEMz69iBu%INRsH z`I-c~0>{q4Xb{c{yifRY6@dZ?Z8(bXC^`(SJZQY>WT^002ovPDHLkV1hTywjuxk literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/warp-door/door-3.png b/dev-assets/doodads/warp-door/door-3.png new file mode 100644 index 0000000000000000000000000000000000000000..d225a8dfe255952893f7efa2db126e34c44d938a GIT binary patch literal 957 zcmV;u148_XP)EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00EUrL_t(&-tF13PQx$|2H>B_?@)>mc?2fZ0S59Mo!OYW zu<-y4Y)qXqATjX*^+1Na06P*QWaG26ZzrVb78}|3AHduZ950Rxn(q3@?Y|KdZ0kH+)4uJ?nAOaDH zKm;O?gM_&ESr!NdA{au22!>chUK&0~`-ZOzq6RA@^3q^FQ&PU9$I=UNt7BJk-seO) zVi9gG17Yiz{e z-ZwTP7(#{Ug>+R1C886;f$$()2oJ)A*n&_$CkFSvVwUQp8wfW7 fXic88lo#>~!xYl8H00000NkvXXu0mjf01l-? literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/warp-door/door-4.png b/dev-assets/doodads/warp-door/door-4.png new file mode 100644 index 0000000000000000000000000000000000000000..65f3e03ebea572ff92e2d5f1c91e115f672bd39b GIT binary patch literal 830 zcmV-E1Ht@>P)EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{009%$aPWIF5!F)_z7~oEX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{009_DL_t(&-tE~<4uc>N1>o1lli<=Lbi-*_x%VO-$c;x} zDOYJ1H1(&{f;*DjE5JCtcgb+dqA%qY@$m#bruh;#pO+jvPg|F=^+o1Sxyn735S;e0000< KMNUMnLSTZ??rDes literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/warp-door/orange-2.png b/dev-assets/doodads/warp-door/orange-2.png new file mode 100644 index 0000000000000000000000000000000000000000..2bb01fbd6fcb928a11f65366c3259c3b797908ca GIT binary patch literal 967 zcmV;&133JNP)EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00Ey#L_t(&-tC$(Zo@DPMSp^vL>_yDE&@%W>GN>{NijGZos1=m=XgZQAO&C*glmvG_Snc!5Cu^X1yK+MQINX@IaE!^AQVjr$@>YgjZk4k&4D60k^^H0;Q2Hjzcn|m(5?a8Z}IHh zvRzswG&wz5aS%?AR@@`h9<9FVu|Q&(U+l@6oB5(3-0cogkLd1%f+&cBD2Re62&;yy zT(hnUyV@Ycj-)6Er~CX*w@H|l8~v4&(EEX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00DAIL_t(&-tE~ja>6hW1<;QtClMt_NJEj9Yq(04#%D-s zXmW;BTp%j&5h%SyE)ojlAX^qhM(Z^*s~N^vF8s#c)o9m?rot~~FrEOwn9Br_J2wDm zV7?vhIuWpZzYoz=K;cgWH=A%2b3k+;(nBE%QHVkmq7a2B>`l#v4`�Ves)|5&Yukzq(zirY}nN$KJ3b!KLg)~+>ppRVQT=N z-MO#*`Pcr>(v}F;3Ah`VU4Wl0+vWNAS^>L{j89~!6JYCjx{^b`EhfmC^>H{$hye2< zoW5Lrl$#L$wQx3b3h5`ITgAtP5X}I>u}&mIr24JedDiq*h(Z*i5QSWCmOy)GtcY|7 zg`22*KgTCS`g@g}h|$5C8!@`}&5cNga3SIl!yB0Yg9so(h!7%#2q8KU?sZ~x?K>qR wTKi6o7_5CI5JBxLh4_O=BLJ@j-c+)X6ZE5cgu#+2eEEX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{008?*L_t(&-tF134Z<)G1<)VFBu>c)Py~sVHBwR0cm}AU zVFoH{q@)NVQ09s(0);VBgp8t5b^E&*~4X%iA`=*<4jr!op`X3O@`e1635bd-uHTEIe h^#Qzo3iMtd@&t#%Fuus#viJZ1002ovPDHLkV1me7SIYnZ literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/warp-door/orange-off.png b/dev-assets/doodads/warp-door/orange-off.png new file mode 100644 index 0000000000000000000000000000000000000000..476703a5db35acdcf9c2b3557b9259cc05d6fb33 GIT binary patch literal 687 zcmV;g0#N;lP)EX>4Tx04R}tkv&MmKpe$iQ>7vm2MdZQWT=8*MO4I5t5Adrp;lNGFg)WK9P8q>4rtTK|H-_ z>74h8L#!ZYh|h^f4Z0xlBi9v|-#F(T7IO?@AxHhDdZ}G zkz)a6sE{2$_#gc4*33;#xJkh%(EeiEA45Q37pPZl`}^3o>nDK!8MxA#{&EeN`6RvC z)WSzV_cm~G-PDvl;Bp7(d(ve?b|gPdA(sQ*&*+=dK+i4Ex#srP*vIJukfg5SH^9Lm zFr26Cb&q#eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{004(cL_t(&-tF4434kyVK+(&s;*ideA)Q4VBO)SV5mUTh zX;2bEo|Pr`mO0j`MmgWN>o?ERdHMhV002ovPDHLkV1m8mC_n%J literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/warp-door/warp-door.js b/dev-assets/doodads/warp-door/warp-door.js new file mode 100644 index 0000000..2dc73ab --- /dev/null +++ b/dev-assets/doodads/warp-door/warp-door.js @@ -0,0 +1,81 @@ +// Warp Doors +function main() { + console.log("Warp Door %s Initialized", Self.Title); + + Self.SetHitbox(0, 0, 34, 76); + + // Are we a blue or orange door? Regular warp door will be 'none' + var color = Self.GetTag("color"); + var isStateDoor = color === 'blue' || color === 'orange'; + var state = color === 'blue'; // Blue door is ON by default. + + var animating = false; + var collide = false; + + // Declare animations and sprite names. + var animSpeed = 100; + var spriteDefault, spriteDisabled; // the latter for state doors. + if (color === 'blue') { + Self.AddAnimation("open", animSpeed, ["blue-2", "blue-3", "blue-4"]); + Self.AddAnimation("close", animSpeed, ["blue-4", "blue-3", "blue-2", "blue-1"]); + spriteDefault = "blue-1"; + spriteDisabled = "blue-off"; + } else if (color === 'orange') { + Self.AddAnimation("open", animSpeed, ["orange-2", "orange-3", "orange-4"]); + Self.AddAnimation("close", animSpeed, ["orange-4", "orange-3", "orange-2", "orange-1"]); + spriteDefault = "orange-1"; + spriteDisabled = "orange-off"; + } else { + Self.AddAnimation("open", animSpeed, ["door-2", "door-3", "door-4"]); + Self.AddAnimation("close", animSpeed, ["door-4", "door-3", "door-2", "door-1"]); + spriteDefault = "door-1"; + } + + console.log("Warp %s: default=%s disabled=%+v color=%s isState=%+v state=%+v", Self.Title, spriteDefault, spriteDisabled, color, isStateDoor, state); + + // Subscribe to the global state-change if we are a state door. + if (isStateDoor) { + Message.Subscribe("broadcast:state-change", function(newState) { + console.log("Warp %s: received state to %+v", Self.Title, newState); + state = color === 'blue' ? !newState : newState; + + // Activate or deactivate the door. + Self.ShowLayerNamed(state ? spriteDefault : spriteDisabled); + }); + } + + // TODO: respond to a "Use" button instead of a Collide to open the door. + Events.OnCollide(function(e) { + if (!e.Settled) { + return; + } + + if (animating || collide) { + return; + } + + // Only players can use doors for now. + if (e.Actor.IsPlayer() && e.InHitbox) { + if (isStateDoor && !state) { + // The state door is inactive (dotted outline). + return; + } + + // Play the open and close animation. + animating = true; + collide = true; + Self.PlayAnimation("open", function() { + e.Actor.Hide() + Self.PlayAnimation("close", function() { + Self.ShowLayerNamed(isStateDoor && !state ? spriteDisabled : spriteDefault); + e.Actor.Show() + animating = false; + }); + }); + } + }); + + Events.OnLeave(function(e) { + collide = false; + }); +} diff --git a/pkg/uix/actor.go b/pkg/uix/actor.go index cc16527..72ef702 100644 --- a/pkg/uix/actor.go +++ b/pkg/uix/actor.go @@ -37,6 +37,7 @@ type Actor struct { hasGravity bool isMobile bool // Mobile character, such as the player or an enemy noclip bool // Disable collision detection + hidden bool // invisible, via Hide() and Show() hitbox render.Rect inventory map[string]int // item inventory. doodad name -> quantity, 0 for key item. data map[string]string // arbitrary key/value store. DEPRECATED ?? @@ -117,6 +118,12 @@ func (a *Actor) IsMobile() bool { return a.isMobile } +// IsPlayer returns whether the actor is the player character. +// It's true when the Actor ID is "PLAYER" +func (a *Actor) IsPlayer() bool { + return a.Canvas.Name == "PLAYER" +} + // Size returns the size of the actor, from the underlying doodads.Drawing. func (a *Actor) Size() render.Rect { return a.Drawing.Size() @@ -157,6 +164,16 @@ func (a *Actor) SetGrounded(v bool) { a.grounded = v } +// Hide makes the actor invisible. +func (a *Actor) Hide() { + a.hidden = true +} + +// Show a hidden actor. +func (a *Actor) Show() { + a.hidden = false +} + // SetNoclip sets the noclip setting for an actor. If true, the actor can // clip through level geometry. func (a *Actor) SetNoclip(v bool) { diff --git a/pkg/uix/canvas_actors.go b/pkg/uix/canvas_actors.go index ce8f6ad..5bb02e3 100644 --- a/pkg/uix/canvas_actors.go +++ b/pkg/uix/canvas_actors.go @@ -113,6 +113,12 @@ func (w *Canvas) drawActors(e render.Engine, p render.Point) { log.Error("Canvas.drawActors: null actor at index %d (of %d actors)", i, len(w.actors)) continue } + + // Skip hidden actors. + if a.hidden { + continue + } + var ( can = a.Canvas // Canvas widget that draws the actor actorPoint = a.Position()