@biunow/agent-biuart 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/server.mjs +575 -0
- package/data/styles.json +533 -0
- package/engine/audit_clip.py +46 -0
- package/engine/clip.html +24 -0
- package/engine/clip.js +104 -0
- package/engine/clip_schema.json +19 -0
- package/engine/clips/t1_3b1b.js +203 -0
- package/engine/clips/t2_keynote_ui.js +347 -0
- package/engine/clips/t3_finance_chart.js +206 -0
- package/engine/clips/y1_kurzgesagt.js +183 -0
- package/engine/clips/y2_vox.js +150 -0
- package/engine/clips/y3_whiteboard.js +209 -0
- package/engine/clips/y4_storytime.js +194 -0
- package/engine/clips/y5_kinetic_type.js +134 -0
- package/engine/compare.py +19 -0
- package/engine/demos/_shared/hero/c1_0.png +0 -0
- package/engine/demos/_shared/hero/c1_1.png +0 -0
- package/engine/demos/_shared/hero/c1_2.png +0 -0
- package/engine/demos/_shared/hero/c3_line.png +0 -0
- package/engine/demos/_shared/hero.js +96 -0
- package/engine/demos/long_scroll/eras.js +23 -0
- package/engine/demos/long_scroll/frames/8bit_act/01.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/02.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/03.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/04.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/05.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/06.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/07.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/08.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/meta.json +69 -0
- package/engine/demos/long_scroll/frames/8bit_walk/01.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/02.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/03.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/04.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/05.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/06.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/07.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/08.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/meta.json +69 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/01.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/02.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/03.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/04.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/05.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/06.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/07.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/08.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/meta.json +69 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/01.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/02.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/03.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/04.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/05.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/06.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/07.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/08.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/meta.json +69 -0
- package/engine/demos/long_scroll/frames/monet_throw/01.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/02.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/03.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/04.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/05.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/06.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/07.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/08.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/meta.json +71 -0
- package/engine/demos/long_scroll/frames/monet_walk/01.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/02.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/03.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/04.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/05.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/06.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/07.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/08.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/meta.json +71 -0
- package/engine/demos/long_scroll/lib/acts.js +87 -0
- package/engine/demos/long_scroll/lib/crossing.js +463 -0
- package/engine/demos/long_scroll/lib/world.js +143 -0
- package/engine/demos/long_scroll/lib/xing2_ding.js +42 -0
- package/engine/demos/long_scroll/lib/xing2_jia.js +114 -0
- package/engine/demos/long_scroll/lib/xing2_yi.js +133 -0
- package/engine/demos/long_scroll/segments/02_egypt.js +234 -0
- package/engine/demos/long_scroll/segments/14_8bit.js +118 -0
- package/engine/demos/long_scroll/segments/28_monet.js +86 -0
- package/engine/demos/t1_3b1b/eras.js +11 -0
- package/engine/demos/t1_3b1b/t1_s1.js +101 -0
- package/engine/demos/t1_3b1b/t1_s2.js +74 -0
- package/engine/demos/t1_3b1b/t1_s3.js +65 -0
- package/engine/demos/t2_keynote_ui/eras.js +10 -0
- package/engine/demos/t2_keynote_ui/t2_s1.js +57 -0
- package/engine/demos/t2_keynote_ui/t2_s2.js +70 -0
- package/engine/demos/t2_keynote_ui/t2_s3.js +61 -0
- package/engine/demos/t3_finance_chart/eras.js +11 -0
- package/engine/demos/t3_finance_chart/t3_s1.js +48 -0
- package/engine/demos/t3_finance_chart/t3_s2.js +42 -0
- package/engine/demos/t3_finance_chart/t3_s3.js +51 -0
- package/engine/demos/y1_kurzgesagt/eras.js +10 -0
- package/engine/demos/y1_kurzgesagt/kurzgesagt.js +347 -0
- package/engine/demos/y2_vox/eras.js +10 -0
- package/engine/demos/y2_vox/vox.js +240 -0
- package/engine/demos/y3_whiteboard/eras.js +10 -0
- package/engine/demos/y3_whiteboard/whiteboard.js +162 -0
- package/engine/demos/y4_storytime/eras.js +14 -0
- package/engine/demos/y4_storytime/s1_desk.js +18 -0
- package/engine/demos/y4_storytime/s2_screen.js +82 -0
- package/engine/demos/y4_storytime/s3_react.js +39 -0
- package/engine/demos/y4_storytime/s4_wide.js +16 -0
- package/engine/demos/y4_storytime/s5_close.js +18 -0
- package/engine/demos/y4_storytime/story.js +25 -0
- package/engine/demos/y4_storytime/vo_env.js +2 -0
- package/engine/demos/y4_storytime/world.js +73 -0
- package/engine/demos/y5_kinetic_type/eras.js +16 -0
- package/engine/demos/y5_kinetic_type/k1_title.js +38 -0
- package/engine/demos/y5_kinetic_type/k2_complete.js +55 -0
- package/engine/demos/y5_kinetic_type/k3_chat.js +47 -0
- package/engine/demos/y5_kinetic_type/k4_agent.js +49 -0
- package/engine/demos/y5_kinetic_type/kinetic.js +52 -0
- package/engine/engine.js +277 -0
- package/engine/eras.js +60 -0
- package/engine/eras_gallery.js +115 -0
- package/engine/eras_style_studies.js +20 -0
- package/engine/examples/assets/K/347/272/277/345/233/276_/346/250/252/345/261/217.png +0 -0
- package/engine/examples/assets//347/273/210/347/253/257_for/345/276/252/347/216/257/346/261/202/345/222/214.png +0 -0
- package/engine/examples/assets//347/273/210/347/253/257_sum/346/261/202/345/222/214.png +0 -0
- package/engine/examples/assets//350/220/245/346/224/266/345/233/276_/347/253/226/345/261/217.png +0 -0
- package/engine/examples/assets//350/264/242/347/273/217/345/233/276/350/241/250_/346/250/252/345/261/217.png +0 -0
- package/engine/examples/t1_3b1b.json +19 -0
- package/engine/examples/t2_fullbleed_pulse.json +15 -0
- package/engine/examples/t2_keynote_ui.json +15 -0
- package/engine/examples/t3_finance_chart.json +29 -0
- package/engine/examples/y1_kurzgesagt.json +16 -0
- package/engine/examples/y2_vox.json +14 -0
- package/engine/examples/y3_whiteboard.json +17 -0
- package/engine/examples/y4_storytime.json +52 -0
- package/engine/examples/y5_kinetic_type.json +14 -0
- package/engine/index.html +42 -0
- package/engine/lib/THREE_LICENSE.txt +21 -0
- package/engine/lib/brush.js +149 -0
- package/engine/lib/camera.js +99 -0
- package/engine/lib/chart.js +152 -0
- package/engine/lib/collage.js +97 -0
- package/engine/lib/diagram.js +264 -0
- package/engine/lib/finish.js +70 -0
- package/engine/lib/fonts/AlfaSlabOne-400.woff +0 -0
- package/engine/lib/fonts/Anton-400.woff +0 -0
- package/engine/lib/fonts/ArchivoBlack-400.woff +0 -0
- package/engine/lib/fonts/Bangers-400.woff +0 -0
- package/engine/lib/fonts/Caveat-600.woff +0 -0
- package/engine/lib/fonts/Cinzel-400.woff +0 -0
- package/engine/lib/fonts/Cinzel-700.woff +0 -0
- package/engine/lib/fonts/CormorantGaramond-500.woff +0 -0
- package/engine/lib/fonts/CormorantGaramond-500i.woff +0 -0
- package/engine/lib/fonts/CormorantGaramond-700.woff +0 -0
- package/engine/lib/fonts/EBGaramond-400.woff +0 -0
- package/engine/lib/fonts/EBGaramond-400i.woff +0 -0
- package/engine/lib/fonts/EBGaramond-600.woff +0 -0
- package/engine/lib/fonts/Exo2-800i.woff +0 -0
- package/engine/lib/fonts/GochiHand-400.woff +0 -0
- package/engine/lib/fonts/IMFellEnglish-400.woff +0 -0
- package/engine/lib/fonts/IMFellEnglish-400i.woff +0 -0
- package/engine/lib/fonts/Inter-var.woff +0 -0
- package/engine/lib/fonts/JosefinSans-700.woff +0 -0
- package/engine/lib/fonts/Kalam-700.woff +0 -0
- package/engine/lib/fonts/LICENSES.md +40 -0
- package/engine/lib/fonts/LXGWWenKai-500.woff +0 -0
- package/engine/lib/fonts/LibreBaskerville-400.woff +0 -0
- package/engine/lib/fonts/LibreBaskerville-700.woff +0 -0
- package/engine/lib/fonts/LilitaOne-400.woff +0 -0
- package/engine/lib/fonts/Marcellus-400.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-500.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-700.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-800.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-900.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-sub.woff +0 -0
- package/engine/lib/fonts/NotoSerifJP-600.woff +0 -0
- package/engine/lib/fonts/NotoSerifSC-sub.woff +0 -0
- package/engine/lib/fonts/OFL.txt +94 -0
- package/engine/lib/fonts/PlayfairDisplay-400i.woff +0 -0
- package/engine/lib/fonts/PlayfairDisplay-700.woff +0 -0
- package/engine/lib/fonts/PlayfairDisplay-700i.woff +0 -0
- package/engine/lib/fonts/Poppins-600.woff +0 -0
- package/engine/lib/fonts/Poppins-700.woff +0 -0
- package/engine/lib/fonts/Poppins-800.woff +0 -0
- package/engine/lib/fonts/PressStart2P-400.woff +0 -0
- package/engine/lib/fonts/Righteous-400.woff +0 -0
- package/engine/lib/fonts/RobotoCondensed-var.woff +0 -0
- package/engine/lib/fonts/Rye-400.woff +0 -0
- package/engine/lib/fonts/UnifrakturMaguntia-400.woff +0 -0
- package/engine/lib/fonts/cmunrm.woff +0 -0
- package/engine/lib/fonts/cmunti.woff +0 -0
- package/engine/lib/fonts/index.json +1 -0
- package/engine/lib/fonts.js +56 -0
- package/engine/lib/kit.js +91 -0
- package/engine/lib/media.js +118 -0
- package/engine/lib/medium.js +258 -0
- package/engine/lib/motion.js +111 -0
- package/engine/lib/paint.js +200 -0
- package/engine/lib/palettes.js +57 -0
- package/engine/lib/post.js +108 -0
- package/engine/lib/render.js +189 -0
- package/engine/lib/rig.js +390 -0
- package/engine/lib/rig_huashu.js +171 -0
- package/engine/lib/three.min.js +7 -0
- package/engine/lib/toon.js +186 -0
- package/engine/lib/typo.js +136 -0
- package/engine/lib/ui.js +141 -0
- package/engine/lib/util.js +92 -0
- package/engine/render.py +157 -0
- package/engine/scenes/01_cave.js +364 -0
- package/engine/scenes/02_egypt.js +524 -0
- package/engine/scenes/03_greek.js +448 -0
- package/engine/scenes/04_roman.js +555 -0
- package/engine/scenes/05_gothic.js +522 -0
- package/engine/scenes/06_renaissance.js +338 -0
- package/engine/scenes/08_impressionism.js +206 -0
- package/engine/scenes/09_postimp.js +183 -0
- package/engine/scenes/10_nouveau.js +334 -0
- package/engine/scenes/11_cubism.js +265 -0
- package/engine/scenes/12_bauhaus.js +214 -0
- package/engine/scenes/13_pop.js +269 -0
- package/engine/scenes/14_8bit.js +238 -0
- package/engine/scenes/15_raytrace.js +300 -0
- package/engine/scenes/16_2026.js +565 -0
- package/engine/scenes/17_ink.js +273 -0
- package/engine/scenes/18_klimt.js +227 -0
- package/engine/scenes/19_munch.js +153 -0
- package/engine/scenes/20_dunhuang.js +215 -0
- package/engine/scenes/21_kusama.js +124 -0
- package/engine/scenes/22_constructivism.js +205 -0
- package/engine/scenes/23_dali.js +221 -0
- package/engine/scenes/24_hopper.js +150 -0
- package/engine/scenes/25_ghibli.js +251 -0
- package/engine/scenes/26_vaporwave.js +191 -0
- package/engine/scenes/27_kirby.js +255 -0
- package/engine/scenes/28_monet.js +176 -0
- package/engine/scenes/29_seurat.js +104 -0
- package/engine/scenes/30_matisse.js +151 -0
- package/engine/scenes/31_haring.js +109 -0
- package/engine/scenes/32_rembrandt.js +217 -0
- package/engine/scenes/33_rubberhose.js +219 -0
- package/engine/scenes/34_shadowpuppet.js +195 -0
- package/engine/scenes/35_shinkai.js +197 -0
- package/engine/scenes/36_picasso_blue.js +123 -0
- package/engine/scenes/38_giotto.js +133 -0
- package/engine/scenes/39_piero.js +53 -0
- package/engine/scenes/40_raphael.js +96 -0
- package/engine/scenes/41_michelangelo.js +112 -0
- package/engine/scenes/42_guardi.js +70 -0
- package/engine/scenes/43_lorenzetti.js +145 -0
- package/engine/scenes/44_cortona.js +86 -0
- package/engine/scenes/45_renoir.js +86 -0
- package/engine/scenes/46_pissarro.js +82 -0
- package/engine/scenes/47_sisley.js +94 -0
- package/engine/scenes/48_gauguin.js +107 -0
- package/engine/scenes/49_chagall.js +60 -0
- package/engine/scenes/50_ma_yuan.js +131 -0
- package/engine/scenes/51_persian_miniature.js +149 -0
- package/engine/scenes/52_south_park.js +105 -0
- package/engine/scenes/53_pixar.js +60 -0
- package/engine/scenes/54_ghibli_lab.js +68 -0
- package/engine/scenes/55_dunhuang.js +161 -0
- package/engine/scenes/index.js +28 -0
- package/engine/spec_assets.py +76 -0
- package/engine/transitions.js +929 -0
- package/engine//346/227/266/344/273/243/344/275/234/350/200/205/350/247/204/350/214/203.md +49 -0
- package/lib/host.mjs +754 -0
- package/lib/render-bridge.mjs +543 -0
- package/lib/render-cli.mjs +98 -0
- package/lib/storyboard-lint.mjs +54 -0
- package/manifest.json +52 -0
- package/package.json +8 -4
- package/runtime/package.json +8 -0
- package/skills/biuart/SKILL.md +154 -0
- package/skills/biuart/references/01-/346/213/206/350/247/243.md +55 -0
- package/skills/biuart/references/02-/346/234/272/345/210/266.md +41 -0
- package/skills/biuart/references/03-/344/270/200/345/270/247/345/205/210/350/241/214/345/233/233/346/235/241/350/267/257/347/272/277.md +39 -0
- package/skills/biuart/references/04-/347/272/257/344/273/243/347/240/201/347/273/230/345/210/266.md +92 -0
- package/skills/biuart/references/05-/350/212/202/345/245/217/344/270/216/351/205/215/344/271/220.md +19 -0
- package/skills/biuart/references/06-/345/217/243/346/222/255/351/251/261/345/212/250/347/232/204/350/211/272/346/234/257/347/237/255/347/211/207.md +31 -0
- package/skills/biuart/references/07-/346/255/243/351/235/242/347/273/217/351/252/214.md +196 -0
- package/skills/biuart/references/08-/351/243/216/346/240/274/344/275/234/350/200/205/350/247/204/350/214/203.md +61 -0
- package/skills/biuart/references/09-/350/247/206/351/242/221/345/212/250/347/224/273/350/257/255/346/263/225.md +382 -0
- package/skills/biuart/references/10-/350/247/222/350/211/262.md +34 -0
- package/skills/biuart/references/11-/351/225/277/345/215/267/347/251/277/350/266/212/347/211/207.md +43 -0
- package/skills/biuart/references/12-/345/217/243/346/222/255/346/225/264/347/211/207/344/270/216/347/273/217/351/252/214/345/233/236/346/265/201.md +25 -0
- package/skills/biuart/references/13-/345/217/243/346/222/255/344/270/216/350/257/255/351/237/263/345/244/215/345/210/273.md +7 -0
- package/skills/biuart/references/15-/350/267/250/345/234/272/346/231/257/351/243/216/346/240/274/346/217/220/347/202/274.md +48 -0
- package/skills/biuart/references/16-/351/243/216/346/240/274/346/274/224/347/244/27295/345/210/206/345/215/217/350/256/256.md +103 -0
- package/skills/biuart/references/about-author.md +99 -0
- package/skills/biuart/references/capabilities.md +91 -0
- package/skills/biuart/references/compatibility.md +34 -0
- package/skills/biuart/references/images.md +97 -0
- package/skills/biuart/references/voice-model-review.md +18 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t1_3b1b.md +122 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t2_keynote_ui.md +117 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t3_finance_chart.md +116 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y1_kurzgesagt.md +193 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y2_vox.md +195 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y3_whiteboard.md +190 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y4_storytime.md +166 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y5_kinetic_type.md +158 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y6_presenter_explainer.md +24 -0
- package/skills/biuart/references//345/217/243/346/222/255API.md +125 -0
- package/skills/biuart/references//350/211/262/346/235/277.md +38 -0
- package/skills/biuart/references//350/247/222/350/211/262/347/262/276/347/273/206/345/272/246.md +61 -0
- package/skills/biuart/references//351/225/234/345/244/264/350/241/250/346/250/241/346/235/277.md +80 -0
- package/skills/biuart/references//351/225/234/345/244/264/350/257/255/350/250/200.md +73 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/01_cave.md +46 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/02_egypt.md +64 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/03_greek.md +50 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/04_roman.md +99 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/05_gothic.md +32 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/06_renaissance.md +41 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/08_impressionism.md +34 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/09_postimp.md +17 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/10_nouveau.md +31 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/11_cubism.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/12_bauhaus.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/13_pop.md +29 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/14_8bit.md +27 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/15_raytrace.md +32 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/16_2026.md +55 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/17_ink.md +50 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/18_klimt.md +37 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/19_munch.md +42 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/20_dunhuang.md +49 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/21_kusama.md +32 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/22_constructivism.md +35 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/23_dali.md +29 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/24_hopper.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/25_ghibli.md +55 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/26_vaporwave.md +27 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/27_kirby.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/28_monet.md +39 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/29_seurat.md +31 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/30_matisse.md +26 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/31_haring.md +22 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/32_rembrandt.md +29 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/33_rubberhose.md +31 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/34_shadowpuppet.md +40 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/35_shinkai.md +34 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/36_picasso_blue.md +25 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/37_rick_morty.md +48 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/38_giotto.md +67 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/39_piero.md +59 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/40_raphael.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/41_michelangelo.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/42_guardi.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/43_lorenzetti.md +69 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/44_cortona.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/45_renoir.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/46_pissarro.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/47_sisley.md +67 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/48_gauguin.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/49_chagall.md +59 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/50_ma_yuan.md +68 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/51_persian_miniature.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/52_south_park.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/53_pixar.md +61 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/55_dunhuang.md +41 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/INDEX.md +89 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/_/350/275/254/345/234/272_/350/277/201/347/247/273/346/265/213/350/257/225.md +53 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/_/351/207/215/345/201/232/350/277/233/345/272/246.md +37 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/_/351/237/263/350/275/250_/350/211/272/346/234/257/345/217/262/351/200/237/351/200/232.md +135 -0
- package/studio/app.js +380 -0
- package/studio/assert-panel-permit.mjs +67 -0
- package/studio/composer.css +465 -0
- package/studio/composer.js +480 -0
- package/studio/index.html +97 -0
- package/studio/optimize-prompt.mjs +84 -0
- package/studio/optimize-prompt.test.mjs +47 -0
- package/studio/recipes.mjs +87 -0
- package/studio/select-menu.js +450 -0
- package/studio/styles.css +71 -0
- package/studio/to-english-prompt.mjs +149 -0
- package/studio/to-english-prompt.test.mjs +72 -0
- package/README.md +0 -3
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// 1988 吉卜力式手绘水彩背景美术(宫崎骏/男鹿和雄的夏日房间)——纯代码。
|
|
2
|
+
// 管线:①缓存底版:纸 → 水彩洗染 wash(中点位移变形的多边形 × 多层低 α multiply 叠色 + 每层描一圈淡边 = 水痕边)
|
|
3
|
+
// → 窗外蓝天、积雨云(白色不透明+底部蓝灰透明叠色)、远山、草坡、大樟树;室内灰泥墙、木地板、扫帚、小架子
|
|
4
|
+
// → ②会动的母题(白纱窗帘被风鼓起、窗外草叶成片摆、云慢慢飘、树冠轻摇、墙上树影光斑闪、桌上雏菊点头、发丝与红蝴蝶结飘)
|
|
5
|
+
// → ③角色:赛璐璐两色(基色+「路径减去朝光平移的自身」得到的月牙阴影)+暖褐细线
|
|
6
|
+
SCENES['25_ghibli'] = (() => {
|
|
7
|
+
const W = 1920, H = 1080, { clamp, lerp, ease, rng } = U, P = PAINT, TAU = Math.PI * 2;
|
|
8
|
+
const FLOOR = 720, WIN = [370, 140, 420, 400];
|
|
9
|
+
const LINE = '#6a4a38';
|
|
10
|
+
|
|
11
|
+
// 水彩:P.watercolor(中点位移多边形 × 多层低 α multiply + 水痕边)、P.deform、P.rectPts / P.ellipsePts
|
|
12
|
+
const deform = P.deform, wash = P.watercolor, rect = P.rectPts, ellipsePts = P.ellipsePts;
|
|
13
|
+
const fillPts = (g, pts) => { g.beginPath(); pts.forEach((q, i) => i ? g.lineTo(q[0], q[1]) : g.moveTo(q[0], q[1])); g.closePath(); };
|
|
14
|
+
|
|
15
|
+
// ---------- 云(缓存精灵):白色不透明块 + 底部蓝灰透明叠 ----------
|
|
16
|
+
const cloud = (key, w, h, seed) => P.cached('gh_cloud_' + key, w, h, (g) => {
|
|
17
|
+
const r = rng(seed), puffs = [];
|
|
18
|
+
for (let i = 0; i < 16; i++) { const x = w * (0.15 + r() * 0.7), base = h * 0.78, yy = base - Math.sin((x / w) * Math.PI) * h * (0.35 + r() * 0.3); puffs.push([x, yy, 30 + r() * 46]); }
|
|
19
|
+
puffs.push([w * 0.5, h * 0.72, w * 0.36]);
|
|
20
|
+
puffs.forEach(([x, y, rr], i) => wash(g, ellipsePts(x, y, rr, rr * 0.82, 14), '#ffffff', { layers: 3, alpha: 0.9, amp: 6, seed: seed + i, edge: 0, blend: 'source-over' }));
|
|
21
|
+
g.save(); g.globalCompositeOperation = 'source-atop';
|
|
22
|
+
const sh = g.createLinearGradient(0, h * 0.35, 0, h); sh.addColorStop(0, 'rgba(150,175,205,0)'); sh.addColorStop(1, 'rgba(120,145,190,.75)'); g.fillStyle = sh; g.fillRect(0, 0, w, h);
|
|
23
|
+
g.restore();
|
|
24
|
+
});
|
|
25
|
+
// 大樟树(缓存精灵,轻摇时绕树根转)
|
|
26
|
+
const tree = () => P.cached('gh_tree', 300, 360, (g) => {
|
|
27
|
+
g.fillStyle = '#4a3a2a'; g.fillRect(140, 210, 22, 150);
|
|
28
|
+
const r = rng(77);
|
|
29
|
+
for (let i = 0; i < 22; i++) { const x = 150 + (r() - .5) * 220, y = 150 + (r() - .5) * 170, rr = 34 + r() * 40;
|
|
30
|
+
wash(g, ellipsePts(x, y, rr, rr * 0.8, 12), i % 3 ? '#3f7a3a' : '#2a5a32', { layers: 3, alpha: 0.6, amp: 10, seed: i + 5, edge: 0.15, blend: 'source-over' }); }
|
|
31
|
+
for (let i = 0; i < 14; i++) { const x = 120 + (r() - .5) * 180, y = 110 + (r() - .5) * 120, rr = 18 + r() * 22;
|
|
32
|
+
wash(g, ellipsePts(x, y, rr, rr * 0.7, 10), '#8cc65a', { layers: 2, alpha: 0.45, amp: 6, seed: i + 50, edge: 0, blend: 'source-over' }); }
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// ---------- ① 底版 ----------
|
|
36
|
+
const bg = () => P.cached('gh_bg', W, H, (g) => {
|
|
37
|
+
g.drawImage(P.texture('gh_paper', '#fbf6ea', { scale: 0.02, amt: 6, grain: 10, seed: 3 }), 0, 0);
|
|
38
|
+
// 室内:暖灰泥墙——窗边亮、角落暗的渐变洗染 → 再叠 28 块大幅变形的透明色晕(暖黄/粉/蓝灰交替 = 透明叠色)
|
|
39
|
+
const wl = g.createRadialGradient(580, 340, 100, 700, 420, 1500); wl.addColorStop(0, '#fbf3e0'); wl.addColorStop(0.6, '#f1e1bf'); wl.addColorStop(1, '#dcc49a');
|
|
40
|
+
wash(g, rect(-20, -20, W + 40, FLOOR + 30), '#efdcb4', { layers: 5, alpha: 0.4, amp: 12, seed: 2, edge: 0, fill: wl });
|
|
41
|
+
{ const r = rng(404), tints = ['#f2c48a', '#e9b4a2', '#b9c9d8', '#f3dca0', '#d6ae80', '#c8d4b0'];
|
|
42
|
+
for (let i = 0; i < 28; i++) { const x = r() * W, y = r() * 600, rx = 90 + r() * 220, ry = 60 + r() * 160;
|
|
43
|
+
if (x > 340 && x < 820 && y > 110 && y < 560) continue;
|
|
44
|
+
wash(g, ellipsePts(x, y, rx, ry, 10), tints[i % tints.length], { layers: 3, alpha: 0.045, amp: 40, seed: 100 + i, edge: 0.04 }); } }
|
|
45
|
+
wash(g, [[1700, -20], [1940, -20], [1940, 740], [1620, 740], [1680, 400]], '#b89a6c', { layers: 4, alpha: 0.06, amp: 60, seed: 3, edge: 0.03 }); // 右角落暗
|
|
46
|
+
wash(g, [[-20, -20], [200, -20], [140, 400], [220, 740], [-20, 740]], '#b89a6c', { layers: 4, alpha: 0.06, amp: 60, seed: 4, edge: 0.03 });
|
|
47
|
+
// 木护墙板(腰线以下竖板,逐块不同色调)
|
|
48
|
+
{ const r = rng(505); for (let x = -10; x < W; x += 64) wash(g, rect(x, 588, 62, FLOOR - 588), ['#c08a56', '#b47e4c', '#c99460', '#ad7848'][(r() * 4) | 0], { layers: 3, alpha: 0.32, amp: 3, seed: 200 + x, edge: 0.12 }); }
|
|
49
|
+
wash(g, rect(-20, 576, W + 40, 16), '#8a5a34', { layers: 3, alpha: 0.4, amp: 2, seed: 7, edge: 0.15 });
|
|
50
|
+
// 地板:逐条木板洗染
|
|
51
|
+
{ const r = rng(606); let y = FLOOR; for (let k = 0; k < 8; k++) { const h = 26 + k * 12; wash(g, rect(-20, y, W + 40, h), ['#a86e3a', '#9a6232', '#b07a44', '#a06836'][(r() * 4) | 0], { layers: 3, alpha: 0.5, amp: 3, seed: 300 + k, edge: 0.14 }); y += h; } }
|
|
52
|
+
// 窗投到地上的暖光斑(软边、带窗棂十字影)
|
|
53
|
+
g.save(); g.globalCompositeOperation = 'screen'; g.filter = 'blur(10px)'; g.fillStyle = 'rgba(255,236,180,.55)';
|
|
54
|
+
g.beginPath(); g.moveTo(400, 740); g.lineTo(800, 740); g.lineTo(930, 1040); g.lineTo(450, 1040); g.closePath(); g.fill(); g.restore();
|
|
55
|
+
g.save(); g.globalCompositeOperation = 'multiply'; g.filter = 'blur(6px)'; g.fillStyle = 'rgba(190,150,110,.5)';
|
|
56
|
+
g.beginPath(); g.moveTo(596, 740); g.lineTo(606, 740); g.lineTo(700, 1040); g.lineTo(684, 1040); g.closePath(); g.fill(); g.fillRect(420, 880, 470, 10); g.restore();
|
|
57
|
+
wash(g, rect(-20, FLOOR - 26, W + 40, 26), '#9a6a40', { layers: 4, alpha: 0.25, amp: 4, seed: 6, edge: 0.1 }); // 踢脚板
|
|
58
|
+
// 窗外:蓝天(渐变洗染)
|
|
59
|
+
g.save(); g.beginPath(); g.rect(...WIN); g.clip();
|
|
60
|
+
const sky = g.createLinearGradient(0, 140, 0, 440); sky.addColorStop(0, '#3a86d4'); sky.addColorStop(1, '#bfe2f4');
|
|
61
|
+
wash(g, rect(360, 130, 440, 330), '#5a9ad8', { layers: 5, alpha: 0.5, amp: 6, seed: 7, edge: 0, blend: 'source-over', fill: sky });
|
|
62
|
+
// 远山(蓝绿)
|
|
63
|
+
wash(g, [[360, 430], [420, 400], [500, 410], [560, 385], [640, 402], [720, 380], [800, 400], [800, 470], [360, 470]], '#7aa6a0', { layers: 5, alpha: 0.35, amp: 6, seed: 8, edge: 0.12 });
|
|
64
|
+
// 草坡(亮绿 → 深绿)
|
|
65
|
+
const gr = g.createLinearGradient(0, 430, 0, 540); gr.addColorStop(0, '#9ccc5a'); gr.addColorStop(1, '#4c8a3a');
|
|
66
|
+
wash(g, [[360, 450], [480, 432], [620, 446], [800, 428], [800, 560], [360, 560]], '#6aa848', { layers: 6, alpha: 0.5, amp: 6, seed: 9, edge: 0.1, blend: 'source-over', fill: gr });
|
|
67
|
+
g.restore();
|
|
68
|
+
// 窗框(白漆木,蓝绿阴影)+窗台
|
|
69
|
+
const frame = [[346, 116, 468, 24], [346, 116, 24, 446], [790, 116, 24, 446], [575, 140, 10, 400], [370, 330, 420, 9]];
|
|
70
|
+
frame.forEach(([x, y, w, h], i) => wash(g, rect(x, y, w, h), '#f6f1e2', { layers: 3, alpha: 0.95, amp: 2, seed: 20 + i, edge: 0.2, blend: 'source-over' }));
|
|
71
|
+
frame.forEach(([x, y, w, h], i) => wash(g, rect(x + w * 0.55, y, w * 0.45, h), '#9fb8c0', { layers: 2, alpha: 0.25, amp: 2, seed: 30 + i, edge: 0 }));
|
|
72
|
+
wash(g, rect(326, 540, 508, 28), '#f3ecd8', { layers: 3, alpha: 0.95, amp: 2, seed: 40, edge: 0.2, blend: 'source-over' });
|
|
73
|
+
wash(g, rect(326, 556, 508, 12), '#a8b7b8', { layers: 2, alpha: 0.35, amp: 2, seed: 41, edge: 0 });
|
|
74
|
+
// 窗帘杆
|
|
75
|
+
g.strokeStyle = '#6a4a30'; g.lineWidth = 7; g.lineCap = 'round'; g.beginPath(); g.moveTo(300, 98); g.lineTo(860, 98); g.stroke();
|
|
76
|
+
// 墙上小木架+瓶罐、挂着的干花束
|
|
77
|
+
wash(g, rect(1540, 300, 260, 14), '#8a5a34', { layers: 3, alpha: 0.6, amp: 2, seed: 50, edge: 0.15 });
|
|
78
|
+
[[1560, 240, 34, 60, '#6a9ac0'], [1610, 262, 40, 38, '#d8a050'], [1670, 236, 28, 64, '#9ab86a'], [1720, 254, 46, 46, '#c86a50']].forEach(([x, y, w, h, col], i) => wash(g, rect(x, y, w, h), col, { layers: 4, alpha: 0.3, amp: 4, seed: 60 + i, edge: 0.15 }));
|
|
79
|
+
// 靠墙的扫帚(致敬魔女宅急便)
|
|
80
|
+
g.save(); g.translate(1760, 330); g.rotate(0.12);
|
|
81
|
+
wash(g, rect(-7, 0, 14, 470), '#7a5030', { layers: 3, alpha: 0.5, amp: 2, seed: 70, edge: 0.2 });
|
|
82
|
+
wash(g, [[-10, 460], [10, 460], [46, 620], [-46, 620]], '#c89a4a', { layers: 4, alpha: 0.45, amp: 5, seed: 71, edge: 0.2 });
|
|
83
|
+
g.strokeStyle = 'rgba(120,80,30,.6)'; g.lineWidth = 1.5; for (let k = -5; k <= 5; k++) { g.beginPath(); g.moveTo(k * 2, 470); g.lineTo(k * 8.5, 616); g.stroke(); }
|
|
84
|
+
g.fillStyle = '#c84a3a'; g.fillRect(-12, 452, 24, 10); g.restore();
|
|
85
|
+
// 桌(木)+白桌布,椅子
|
|
86
|
+
wash(g, rect(842, 640, 22, 265), '#8a5a34', { layers: 3, alpha: 0.6, amp: 3, seed: 80, edge: 0.15 });
|
|
87
|
+
wash(g, rect(1160, 640, 22, 265), '#8a5a34', { layers: 3, alpha: 0.6, amp: 3, seed: 81, edge: 0.15 });
|
|
88
|
+
wash(g, rect(1436, 470, 18, 440), '#7a4c2a', { layers: 3, alpha: 0.6, amp: 3, seed: 82, edge: 0.15 });
|
|
89
|
+
wash(g, rect(1474, 478, 18, 430), '#7a4c2a', { layers: 3, alpha: 0.6, amp: 3, seed: 83, edge: 0.15 });
|
|
90
|
+
wash(g, rect(1290, 744, 210, 16), '#8a5a34', { layers: 3, alpha: 0.6, amp: 3, seed: 84, edge: 0.15 });
|
|
91
|
+
// 整体:纸纹颗粒(颜料在纸凹处沉积)
|
|
92
|
+
g.save(); g.globalCompositeOperation = 'multiply'; g.globalAlpha = 0.3; g.drawImage(P.texture('gh_gran', '#f4efe2', { scale: 0.06, amt: 18, grain: 26, seed: 9 }), 0, 0); g.restore();
|
|
93
|
+
});
|
|
94
|
+
// 桌布(垂边随风轻摆,每帧画)
|
|
95
|
+
function tablecloth(c, lt) {
|
|
96
|
+
const sw = Math.sin(lt * 5) * 5;
|
|
97
|
+
const pts = [[800, 612], [1214, 612], [1222, 700 + sw], [1150, 712 - sw], [1060, 704 + sw], [980, 714 - sw], [890, 704 + sw], [804, 712 - sw]];
|
|
98
|
+
wash(c, pts, '#fffdf6', { layers: 2, alpha: 0.95, amp: 3, seed: 90, edge: 0.25, blend: 'source-over' });
|
|
99
|
+
wash(c, pts.map(([x, y]) => [x, y + (y > 640 ? 0 : 30)]), '#b8c8d8', { layers: 2, alpha: 0.18, amp: 3, seed: 91, edge: 0 });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ---------- ② 窗帘:白纱两幅,下摆被风往屋里鼓 ----------
|
|
103
|
+
function curtain(c, side, lt) {
|
|
104
|
+
const x0 = side < 0 ? 300 : 860, inner = side < 0 ? 420 : 740;
|
|
105
|
+
const gust = 0.5 + 0.5 * Math.sin(lt * 5.4 + (side < 0 ? 0 : 1.3));
|
|
106
|
+
const pts = [], N = 14;
|
|
107
|
+
for (let i = 0; i <= N; i++) { const q = i / N, y = 100 + q * 500, bulge = q * q * (60 + 150 * gust), w = Math.sin(lt * 9 + q * 6 + side) * 16 * q;
|
|
108
|
+
pts.push([inner + side * 0 - side * (bulge * 0.15) + w + (side < 0 ? 1 : -1) * bulge * 0.9, y]); }
|
|
109
|
+
for (let i = N; i >= 0; i--) { const q = i / N, y = 100 + q * 500 + (i === N ? 0 : 0); pts.push([x0 + (side < 0 ? -1 : 1) * q * 30 * gust, y + Math.sin(lt * 6 + q * 4) * 4]); }
|
|
110
|
+
c.save(); c.globalAlpha = 0.85;
|
|
111
|
+
wash(c, pts, '#ffffff', { layers: 3, alpha: 0.42, amp: 4, seed: side < 0 ? 101 : 102, edge: 0, blend: 'source-over' });
|
|
112
|
+
c.restore();
|
|
113
|
+
// 褶线(蓝灰透明,跟随鼓起)
|
|
114
|
+
c.save(); c.globalCompositeOperation = 'multiply'; c.strokeStyle = 'rgba(150,175,200,.45)'; c.lineWidth = 3; c.lineCap = 'round';
|
|
115
|
+
for (let k = 1; k < 4; k++) { const f = k / 4; c.beginPath(); for (let i = 0; i <= 10; i++) { const q = i / 10; const a = pts[Math.round(q * N)], b = pts[2 * N + 1 - Math.round(q * N)]; const x = lerp(b[0], a[0], f), y = lerp(b[1], a[1], f); i ? c.lineTo(x, y) : c.moveTo(x, y); } c.stroke(); }
|
|
116
|
+
c.restore();
|
|
117
|
+
}
|
|
118
|
+
// 窗外草叶:成片同向摆(风是一阵一阵的)
|
|
119
|
+
function grass(c, t) {
|
|
120
|
+
c.save(); c.beginPath(); c.rect(...WIN); c.clip(); c.lineCap = 'round';
|
|
121
|
+
const r = rng(5), cols = ['#5c9a3e', '#7fb84a', '#3f7a32', '#9ccc5a', '#4a8a3a'];
|
|
122
|
+
for (let i = 0; i < 360; i++) {
|
|
123
|
+
const x = 360 + r() * 440, y = 470 + r() * 75, h = 16 + r() * 26 + (y - 470) * 0.35, ph = r() * TAU;
|
|
124
|
+
const wind = Math.sin(t * 3.1 - x * 0.018) * 0.5 + 0.5, sway = (0.25 + wind * 0.75) * h * 0.55 + Math.sin(t * 9 + ph) * 2;
|
|
125
|
+
c.strokeStyle = cols[i % 5]; c.lineWidth = 2 + r() * 2;
|
|
126
|
+
c.beginPath(); c.moveTo(x, y); c.quadraticCurveTo(x + sway * 0.3, y - h * 0.6, x + sway, y - h); c.stroke();
|
|
127
|
+
}
|
|
128
|
+
c.restore();
|
|
129
|
+
}
|
|
130
|
+
// 墙上的树影光斑(komorebi):暖黄亮斑用 screen 叠,位置随噪声慢漂、亮度闪
|
|
131
|
+
function komorebi(c, t) {
|
|
132
|
+
c.save(); c.globalCompositeOperation = 'screen';
|
|
133
|
+
const r = rng(33);
|
|
134
|
+
for (let i = 0; i < 34; i++) {
|
|
135
|
+
const bx = 830 + r() * 380, by = 160 + r() * 420, rr = 10 + r() * 26;
|
|
136
|
+
const x = bx + P.noise(i * 1.3, t * 0.9) * 26, y = by + P.noise(i * 2.1 + 5, t * 0.9) * 18, a = 0.18 + 0.22 * (0.5 + 0.5 * Math.sin(t * 5 + i * 1.7));
|
|
137
|
+
const gg = c.createRadialGradient(x, y, 0, x, y, rr); gg.addColorStop(0, `rgba(255,236,170,${a})`); gg.addColorStop(1, 'rgba(255,236,170,0)'); c.fillStyle = gg; c.beginPath(); c.ellipse(x, y, rr * 1.3, rr, 0.4, 0, TAU); c.fill();
|
|
138
|
+
}
|
|
139
|
+
c.restore();
|
|
140
|
+
}
|
|
141
|
+
// 桌上雏菊(玻璃瓶),花头点头
|
|
142
|
+
function daisies(c, t) {
|
|
143
|
+
const vx = 900, vy = 612;
|
|
144
|
+
c.save(); c.fillStyle = 'rgba(190,220,230,.55)'; c.beginPath(); c.moveTo(vx - 16, vy); c.quadraticCurveTo(vx - 22, vy - 30, vx - 10, vy - 46); c.lineTo(vx + 10, vy - 46); c.quadraticCurveTo(vx + 22, vy - 30, vx + 16, vy); c.closePath(); c.fill();
|
|
145
|
+
c.strokeStyle = 'rgba(90,120,140,.6)'; c.lineWidth = 1.5; c.stroke();
|
|
146
|
+
[[-30, -120, 0], [6, -140, 1.3], [34, -112, 2.1], [-8, -100, 3.2]].forEach(([dx, dy, ph]) => {
|
|
147
|
+
const sw = Math.sin(t * 3.2 + ph) * 7, hx = vx + dx + sw, hy = vy + dy + Math.abs(sw) * 0.2;
|
|
148
|
+
c.strokeStyle = '#5a8a3a'; c.lineWidth = 3; c.beginPath(); c.moveTo(vx + dx * 0.2, vy - 40); c.quadraticCurveTo(vx + dx * 0.6, vy + dy * 0.5, hx, hy); c.stroke();
|
|
149
|
+
c.fillStyle = '#fffdf4'; for (let k = 0; k < 10; k++) { const a = k / 10 * TAU + ph; c.beginPath(); c.ellipse(hx + Math.cos(a) * 9, hy + Math.sin(a) * 6, 7, 3, a, 0, TAU); c.fill(); }
|
|
150
|
+
c.fillStyle = '#f2b830'; c.beginPath(); c.arc(hx, hy, 5, 0, TAU); c.fill();
|
|
151
|
+
});
|
|
152
|
+
c.restore();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ---------- ③ 赛璐璐角色 ----------
|
|
156
|
+
// 赛璐珞两色:P.cel——背光侧(光从左上来,阴影带宽 (dx,dy))一道月牙阴影+暖褐细线
|
|
157
|
+
const cel = (c, p, base, shade, dx = 9, dy = 6, line = true) => P.cel(c, p, base, shade, null, { sd: 1, lx: -dx, ly: -dy, line: LINE, lw: line ? 2.4 : 0 });
|
|
158
|
+
const GP = { skin: '#fde6d2', skinS: '#efbfa4', hair: '#f8dc8c', hairS: '#d9a95a', dress: '#3f8590', dressS: '#2b6470', white: '#fffaf0', whiteS: '#d8dde4', bow: '#d93a30', bowS: '#a0261f' };
|
|
159
|
+
function girl(c, G, ch, lt, t) {
|
|
160
|
+
c.save(); c.lineJoin = 'round'; c.lineCap = 'round';
|
|
161
|
+
cel(c, G.farSleeve, GP.dress, GP.dressS); cel(c, G.farCuff, GP.white, GP.whiteS); cel(c, G.farHand, GP.skin, GP.skinS, 4, 3);
|
|
162
|
+
// 长发(被风吹向右后方)
|
|
163
|
+
const wind = Math.sin(lt * 3.2) * 0.5 + 0.5;
|
|
164
|
+
const nape = G.A.nape, hd = G.A.headC;
|
|
165
|
+
const flow = new Path2D(); const fp = [[hd[0] + 30, hd[1] - 40], [nape[0] + 50 + wind * 14, nape[1] - 30], [nape[0] + 78 + wind * 30, nape[1] + 40 + Math.sin(t * 6) * 6], [nape[0] + 60 + wind * 26, nape[1] + 120 + Math.sin(t * 5 + 1) * 8], [nape[0] + 20, nape[1] + 130], [nape[0] - 6, nape[1] + 40], [hd[0] + 4, hd[1] + 10]];
|
|
166
|
+
const fpath = RIG.smooth(fp); cel(c, fpath, GP.hair, GP.hairS, 10, 4);
|
|
167
|
+
cel(c, G.skirt, GP.dress, GP.dressS, 16, 8);
|
|
168
|
+
c.strokeStyle = GP.dressS; c.lineWidth = 3; G.folds.forEach(f => c.stroke(f));
|
|
169
|
+
cel(c, G.apronSkirt, GP.white, GP.whiteS, 10, 6);
|
|
170
|
+
cel(c, G.shoe, '#6a3a24', '#4a2414', 4, 2);
|
|
171
|
+
cel(c, G.torso, GP.dress, GP.dressS, 14, 6); cel(c, G.bib, GP.white, GP.whiteS, 6, 4);
|
|
172
|
+
cel(c, G.neck, GP.skin, GP.skinS, 6, 2);
|
|
173
|
+
cel(c, G.hairBack, GP.hair, GP.hairS, 10, 6);
|
|
174
|
+
cel(c, G.face, GP.skin, GP.skinS, 10, 4);
|
|
175
|
+
c.save(); c.clip(G.face); c.fillStyle = 'rgba(240,140,130,.35)'; c.beginPath(); c.ellipse(G.cheek[0], G.cheek[1], 12, 7, 0, 0, TAU); c.fill(); c.restore();
|
|
176
|
+
cel(c, G.bangs, GP.hair, GP.hairS, 6, 6);
|
|
177
|
+
c.strokeStyle = GP.hairS; c.lineWidth = 2; G.hairLines.forEach(h => c.stroke(h));
|
|
178
|
+
// 红蝴蝶结(后脑上方),飘带随风
|
|
179
|
+
const bc = [G.A.headTop[0] + 46, G.A.headTop[1] + 14];
|
|
180
|
+
const tails = [[bc[0] + 6, bc[1] + 8], [bc[0] + 40 + wind * 18, bc[1] + 44 + Math.sin(t * 8) * 6], [bc[0] + 26 + wind * 10, bc[1] + 54], [bc[0] + 2, bc[1] + 14]];
|
|
181
|
+
cel(c, RIG.smooth(tails), GP.bow, GP.bowS, 4, 3);
|
|
182
|
+
[[-1, -0.5], [1, 0.4]].forEach(([s, rot]) => { const p = new Path2D(); p.ellipse(bc[0] + s * 24, bc[1] - 4, 26, 15, rot, 0, TAU); cel(c, p, GP.bow, GP.bowS, 5, 4); });
|
|
183
|
+
{ const p = new Path2D(); p.arc(bc[0], bc[1], 9, 0, TAU); cel(c, p, GP.bow, GP.bowS, 2, 2); }
|
|
184
|
+
// 五官(吉卜力式:大而简单的眼)
|
|
185
|
+
if (ch.blink) { c.strokeStyle = LINE; c.lineWidth = 3; c.beginPath(); c.arc(G.eye.x, G.eye.y - 2, 7, 0.2, Math.PI - 0.2); c.stroke(); }
|
|
186
|
+
else { c.fillStyle = '#3a2a24'; c.beginPath(); c.ellipse(G.eye.x - 1, G.eye.y + 1, 5, 7.5, 0, 0, TAU); c.fill(); c.fillStyle = '#5a8ac8'; c.beginPath(); c.ellipse(G.eye.x - 1, G.eye.y + 3, 3.5, 4, 0, 0, TAU); c.fill(); c.fillStyle = '#fff'; c.beginPath(); c.arc(G.eye.x - 2.5, G.eye.y - 2, 2, 0, TAU); c.fill();
|
|
187
|
+
c.strokeStyle = LINE; c.lineWidth = 2.8; c.stroke(G.lid); }
|
|
188
|
+
c.strokeStyle = '#c08a40'; c.lineWidth = 2.4; c.stroke(G.brow);
|
|
189
|
+
c.strokeStyle = '#a8443a'; c.lineWidth = 2.2; c.beginPath(); c.moveTo(...G.lips[0]); c.lineTo(G.lips[1][0] - 1, G.lips[1][1] + 2); c.stroke();
|
|
190
|
+
cel(c, G.upperArm, GP.dress, GP.dressS, 8, 6); cel(c, G.foreArm, GP.dress, GP.dressS, 8, 6); cel(c, G.cuff, GP.white, GP.whiteS, 4, 3);
|
|
191
|
+
cel(c, G.hand, GP.skin, GP.skinS, 4, 3);
|
|
192
|
+
RIG.drawCup(c, G.cup, { body: '#fdf8ee', rim: '#7a4a2a', line: LINE, lw: 2.2, hw: 6 });
|
|
193
|
+
c.save(); c.translate(G.cup.x, G.cup.y); c.rotate(G.cup.tilt); c.strokeStyle = '#5a8ac8'; c.lineWidth = 3; c.beginPath(); c.moveTo(-G.cup.w * 0.45, G.cup.h * 0.35); c.lineTo(G.cup.w * 0.45, G.cup.h * 0.35); c.stroke(); c.restore();
|
|
194
|
+
c.fillStyle = GP.skin; c.beginPath(); c.arc(G.thumb[0], G.thumb[1], 7, 0, TAU); c.fill(); c.strokeStyle = LINE; c.lineWidth = 2; c.stroke();
|
|
195
|
+
c.restore();
|
|
196
|
+
}
|
|
197
|
+
function cat(c, K) {
|
|
198
|
+
const O = '#f3a24c', OS = '#d27a2c', Wt = '#fffaf2', WS = '#e2d8ca';
|
|
199
|
+
c.save(); c.lineJoin = 'round'; c.lineCap = 'round';
|
|
200
|
+
c.strokeStyle = LINE; c.lineWidth = K.tailW + 5; c.stroke(K.tail); c.strokeStyle = O; c.lineWidth = K.tailW; c.stroke(K.tail);
|
|
201
|
+
const tip = K.tailPts[K.tailPts.length - 1]; c.fillStyle = Wt; c.beginPath(); c.arc(tip[0], tip[1], K.tailW / 2, 0, TAU); c.fill();
|
|
202
|
+
cel(c, K.body, O, OS, 18, 10);
|
|
203
|
+
c.save(); c.clip(K.body); c.strokeStyle = '#c8682a'; c.lineWidth = 8; K.stripes.slice(3).forEach(s => { c.beginPath(); c.moveTo(...s[0]); c.lineTo(...s[1]); c.stroke(); }); c.restore();
|
|
204
|
+
K.legs.forEach(l => cel(c, l, Wt, WS, 6, 3));
|
|
205
|
+
c.save(); c.clip(K.body); cel(c, K.white, Wt, WS, 10, 6, false); c.restore();
|
|
206
|
+
cel(c, K.head, O, OS, 12, 8);
|
|
207
|
+
c.save(); c.clip(K.head); c.fillStyle = Wt; c.beginPath(); c.ellipse(K.nose[0] - 22, K.nose[1] + 12, 36, 26, 0, 0, TAU); c.fill(); c.restore();
|
|
208
|
+
c.strokeStyle = LINE; c.lineWidth = 2.4; c.stroke(K.head);
|
|
209
|
+
c.fillStyle = '#f2a8a0'; K.earInner.forEach(e => { c.beginPath(); e.forEach((p, i) => i ? c.lineTo(...p) : c.moveTo(...p)); c.fill(); });
|
|
210
|
+
c.strokeStyle = '#c8682a'; c.lineWidth = 6; K.stripes.slice(0, 3).forEach(s => { c.beginPath(); c.moveTo(...s[0]); c.lineTo(...s[1]); c.stroke(); });
|
|
211
|
+
K.eyes.forEach(e => { if (K.blink) { c.strokeStyle = LINE; c.lineWidth = 3; c.beginPath(); c.arc(e.x, e.y - 2, 8, 0.2, Math.PI - 0.2); c.stroke(); }
|
|
212
|
+
else { c.fillStyle = '#2a1a12'; c.beginPath(); c.ellipse(e.x, e.y, 6, 8, 0, 0, TAU); c.fill(); c.fillStyle = '#fff'; c.beginPath(); c.arc(e.x - 2, e.y - 3, 2.4, 0, TAU); c.fill(); } });
|
|
213
|
+
c.fillStyle = '#d8746a'; c.beginPath(); c.arc(K.nose[0], K.nose[1], 5, 0, TAU); c.fill();
|
|
214
|
+
c.strokeStyle = LINE; c.lineWidth = 2; c.beginPath(); c.moveTo(...K.mouth[0]); c.quadraticCurveTo(...K.mouth[1], ...K.mouth[2]); c.stroke();
|
|
215
|
+
c.lineWidth = 1.4; K.whiskers.forEach(w => { c.beginPath(); c.moveTo(...w[0]); c.lineTo(...w[1]); c.stroke(); });
|
|
216
|
+
c.restore();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 角色用的透明色晕层(multiply 叠在角色上,做出水彩填色的深浅不匀)
|
|
220
|
+
const charBloom = () => P.cached('gh_charBloom', W, H, (g) => { const r = rng(808); for (let i = 0; i < 40; i++) { const x = 380 + r() * 1120, y = 280 + r() * 660; wash(g, ellipsePts(x, y, 30 + r() * 70, 24 + r() * 50, 9), ['#e8b890', '#a8c0d8', '#f0d0a0', '#c8a8c0'][i % 4], { layers: 2, alpha: 0.1, amp: 16, seed: 900 + i, edge: 0.08 }); } });
|
|
221
|
+
return {
|
|
222
|
+
draw(c, lt, t) {
|
|
223
|
+
const ch = P.choreo(lt, t);
|
|
224
|
+
c.drawImage(bg(), 0, 0);
|
|
225
|
+
// 窗外:云飘、树摇、草摆(都在窗洞里)
|
|
226
|
+
c.save(); c.beginPath(); c.rect(...WIN); c.clip();
|
|
227
|
+
c.drawImage(cloud('a', 380, 230, 11), 300 + t * 22, 150); c.drawImage(cloud('b', 260, 160, 23), 590 + t * 30, 210);
|
|
228
|
+
c.save(); c.translate(700, 540); c.rotate(Math.sin(t * 2.4) * 0.025); c.drawImage(tree(), -150, -360); c.restore();
|
|
229
|
+
c.restore();
|
|
230
|
+
grass(c, t);
|
|
231
|
+
// 窗框中梃压在外景上(从底版里再取一次窗框条,保证树和云在框后)
|
|
232
|
+
c.save(); c.beginPath(); [[575, 140, 10, 400], [370, 330, 420, 9]].forEach(r => c.rect(...r)); c.clip(); c.drawImage(bg(), 0, 0); c.restore();
|
|
233
|
+
komorebi(c, t);
|
|
234
|
+
curtain(c, -1, lt); curtain(c, 1, lt);
|
|
235
|
+
tablecloth(c, lt);
|
|
236
|
+
daisies(c, t);
|
|
237
|
+
// 角色先画进离屏,再把水彩颗粒+透明色晕按角色剪影 multiply 上去:赛璐璐平涂变成「水彩填色」
|
|
238
|
+
const L = P.scratch('ghChars'), cl = L.getContext('2d'); cl.reset(); cl.clearRect(0, 0, W, H);
|
|
239
|
+
const K = RIG.cat({ tail: ch.tail, blink: ch.blink, breathe: ch.breathe });
|
|
240
|
+
cat(cl, K);
|
|
241
|
+
const G = RIG.girl({ cup: ch.cup, sip: ch.sip, breathe: ch.breathe, hair: 'long' });
|
|
242
|
+
girl(cl, G, ch, lt, t);
|
|
243
|
+
c.drawImage(L, 0, 0);
|
|
244
|
+
// 水彩肌理只「乘」在角色上:纹理层 destination-in 角色剪影 → multiply 叠回(source-atop 会把纸色盖上去,人物整体发白,第一版踩到)
|
|
245
|
+
P.textureInside(c, L, mg => { mg.globalAlpha = 0.8; mg.drawImage(P.texture('gh_gran', '#f4efe2', { scale: 0.06, amt: 18, grain: 26, seed: 9 }), 0, 0); mg.globalAlpha = 1; mg.drawImage(charBloom(), 0, 0); }, { key: 'ghCharTex' });
|
|
246
|
+
P.steam(c, t, G.cup.x, G.cup.y - 8, { h: 60, n: 2, color: 'rgba(255,255,255,.75)', width: 3.5, spread: 12, wobble: 8 });
|
|
247
|
+
// 柔光:窗口方向一层暖色 screen 光晕
|
|
248
|
+
c.save(); c.globalCompositeOperation = 'screen'; const lg = c.createRadialGradient(580, 340, 60, 580, 340, 900); lg.addColorStop(0, 'rgba(255,240,200,.28)'); lg.addColorStop(1, 'rgba(255,240,200,0)'); c.fillStyle = lg; c.fillRect(0, 0, W, H); c.restore();
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
})();
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// 2011 蒸汽波 / 赛博霓虹——纯代码。
|
|
2
|
+
// 管线:①先把整幅画进离屏 S:深紫渐变墙+洋红透视网格地面(滚动)+窗里落日(横条切口上移)与青色网格、棕榈剪影摇
|
|
3
|
+
// +自绘灯管字「カフェ」霓虹招牌(按帧哈希闪)+Win95 对话框 TEA.EXE 进度条+大理石胸像 +角色(深色平涂+粉/青双色轮廓辉光)
|
|
4
|
+
// → ②VHS 后期:RGB 三通道分离错位(multiply 取单通道 → lighter 合成)+跟踪噪声带下滚(带内横向撕裂)+扫描线 + OSD(PLAY ▶、时间码)
|
|
5
|
+
SCENES['26_vaporwave'] = (() => {
|
|
6
|
+
const W = 1920, H = 1080, { clamp, lerp, ease, rng } = U, P = PAINT, TAU = Math.PI * 2;
|
|
7
|
+
const FLOOR = 720;
|
|
8
|
+
const C = { pink: '#ff4fd8', hot: '#ff2f8f', cyan: '#3ff6ff', purple: '#2a0b4a', deep: '#12052a', violet: '#7a2ae0', yellow: '#ffd84a', orange: '#ff8a3a' };
|
|
9
|
+
const glowLine = P.glowStroke; // 霓虹灯管:shadowBlur 辉光+近白芯线
|
|
10
|
+
|
|
11
|
+
// ---------- 静态底版:墙、窗框灯管、胸像底座 ----------
|
|
12
|
+
const bg = () => P.cached('vw_bg', W, H, (g) => {
|
|
13
|
+
const wg = g.createLinearGradient(0, 0, 0, FLOOR); wg.addColorStop(0, '#0d0322'); wg.addColorStop(0.7, '#2c0b52'); wg.addColorStop(1, '#4a0f6a'); g.fillStyle = wg; g.fillRect(0, 0, W, FLOOR);
|
|
14
|
+
// 墙上淡淡的竖向渐变色带(粉→青),像霓虹打在墙上
|
|
15
|
+
const bl = g.createRadialGradient(580, 340, 60, 580, 340, 760); bl.addColorStop(0, 'rgba(255,79,216,.35)'); bl.addColorStop(1, 'rgba(255,79,216,0)'); g.fillStyle = bl; g.fillRect(0, 0, W, FLOOR);
|
|
16
|
+
const br = g.createRadialGradient(1000, 220, 20, 1000, 220, 520); br.addColorStop(0, 'rgba(63,246,255,.22)'); br.addColorStop(1, 'rgba(63,246,255,0)'); g.fillStyle = br; g.fillRect(0, 0, W, FLOOR);
|
|
17
|
+
g.fillStyle = '#08020f'; g.fillRect(0, FLOOR, W, H - FLOOR);
|
|
18
|
+
// 墙脚灯带
|
|
19
|
+
g.beginPath(); g.moveTo(0, FLOOR); g.lineTo(W, FLOOR); glowLine(g, C.cyan, 4, 18);
|
|
20
|
+
// 椅子:黑色亚克力+粉色边灯
|
|
21
|
+
g.fillStyle = '#1a0830'; g.fillRect(1436, 470, 18, 440); g.fillRect(1474, 478, 18, 430); g.fillRect(1290, 744, 210, 16);
|
|
22
|
+
g.beginPath(); g.rect(1436, 470, 18, 440); g.rect(1474, 478, 18, 430); glowLine(g, C.pink, 2, 10);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// ---------- 窗里的落日 ----------
|
|
26
|
+
function sunset(c, t) {
|
|
27
|
+
c.save(); c.beginPath(); c.rect(370, 140, 420, 400); c.clip();
|
|
28
|
+
const sk = c.createLinearGradient(0, 140, 0, 470); sk.addColorStop(0, '#1a0640'); sk.addColorStop(0.55, '#a0207a'); sk.addColorStop(1, '#ff7a5a'); c.fillStyle = sk; c.fillRect(370, 140, 420, 330);
|
|
29
|
+
// 太阳:黄→洋红渐变,横条切口随时间上移(越往下切口越宽)
|
|
30
|
+
const sx = 580, sy = 400, sr = 118;
|
|
31
|
+
c.save(); c.beginPath(); c.arc(sx, sy, sr, 0, TAU); c.clip();
|
|
32
|
+
const sg = c.createLinearGradient(0, sy - sr, 0, sy + sr); sg.addColorStop(0, C.yellow); sg.addColorStop(0.5, C.orange); sg.addColorStop(1, C.hot); c.fillStyle = sg; c.fillRect(sx - sr, sy - sr, sr * 2, sr * 2);
|
|
33
|
+
c.globalCompositeOperation = 'destination-out';
|
|
34
|
+
const ph = (t * 0.9) % 1;
|
|
35
|
+
for (let k = 0; k < 7; k++) { const q = (k + ph) / 7, y = sy + sr * (q * 1.1 - 0.05), h = 2 + q * q * 16; c.fillRect(sx - sr, y, sr * 2, h); }
|
|
36
|
+
c.restore();
|
|
37
|
+
// 地平线上的线框山
|
|
38
|
+
c.beginPath(); c.moveTo(370, 470); [[420, 430], [470, 452], [520, 410], [560, 460], [640, 420], [700, 448], [760, 418], [790, 440]].forEach(p => c.lineTo(...p)); c.lineTo(790, 470);
|
|
39
|
+
c.fillStyle = '#1a0636'; c.fill(); glowLine(c, C.pink, 2.5, 10);
|
|
40
|
+
// 地面网格(青)往观众方向滚动
|
|
41
|
+
c.fillStyle = '#0b0220'; c.fillRect(370, 470, 420, 70);
|
|
42
|
+
c.save(); c.beginPath(); c.rect(370, 470, 420, 70); c.clip(); c.strokeStyle = C.cyan; c.lineWidth = 1.6; c.shadowColor = C.cyan; c.shadowBlur = 8;
|
|
43
|
+
for (let i = -10; i <= 10; i++) { c.beginPath(); c.moveTo(580 + i * 12, 470); c.lineTo(580 + i * 70, 540); c.stroke(); }
|
|
44
|
+
const sc = (t * 1.6) % 1; for (let k = 0; k < 8; k++) { const d = k + 1 - sc, y = 470 + 70 * (1 / (1 + 6 / (d * d + 0.01))) ; c.beginPath(); c.moveTo(370, y); c.lineTo(790, y); c.stroke(); }
|
|
45
|
+
c.restore();
|
|
46
|
+
// 棕榈剪影(左右各一,摇)
|
|
47
|
+
[[400, 540, 1], [770, 540, -1]].forEach(([x, y, s], k) => {
|
|
48
|
+
const sw = Math.sin(t * 2.2 + k * 1.4) * 0.06;
|
|
49
|
+
c.save(); c.translate(x, y); c.rotate(sw * s); c.fillStyle = '#0a0216'; c.strokeStyle = '#0a0216';
|
|
50
|
+
c.lineWidth = 10; c.lineCap = 'round'; c.beginPath(); c.moveTo(0, 0); c.quadraticCurveTo(s * 18, -120, s * 6, -230); c.stroke();
|
|
51
|
+
for (let f = 0; f < 7; f++) { const a = -Math.PI / 2 + (f - 3) * 0.45 + Math.sin(t * 3 + f) * 0.05, L = 70 + (f % 3) * 16; c.save(); c.translate(s * 6, -230); c.rotate(a); c.beginPath(); c.moveTo(0, 0); c.quadraticCurveTo(L * 0.5, -14, L, 12); c.quadraticCurveTo(L * 0.5, 4, 0, 4); c.fill(); c.restore(); }
|
|
52
|
+
c.restore(); });
|
|
53
|
+
c.restore();
|
|
54
|
+
// 窗框:青色灯管
|
|
55
|
+
c.beginPath(); c.rect(360, 130, 440, 420); glowLine(c, C.cyan, 6, 26); c.beginPath(); c.rect(360, 130, 440, 420); c.strokeStyle = '#e8ffff'; c.lineWidth = 2; c.stroke();
|
|
56
|
+
c.fillStyle = '#1a0830'; c.fillRect(330, 550, 500, 22); c.beginPath(); c.moveTo(330, 550); c.lineTo(830, 550); glowLine(c, C.pink, 3, 14);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ---------- 地面:洋红透视网格(滚动) ----------
|
|
60
|
+
function floorGrid(c, t) {
|
|
61
|
+
c.save(); c.beginPath(); c.rect(0, FLOOR, W, H - FLOOR); c.clip();
|
|
62
|
+
const VX = 960, VY = 600; c.strokeStyle = C.pink; c.shadowColor = C.pink; c.shadowBlur = 12; c.lineWidth = 2.5;
|
|
63
|
+
for (let i = -16; i <= 16; i++) { c.beginPath(); c.moveTo(VX + i * 160 * (FLOOR - VY) / (H - VY), FLOOR); c.lineTo(VX + i * 160, H); c.stroke(); }
|
|
64
|
+
const ph = (t * 1.3) % 1;
|
|
65
|
+
for (let k = 0; k < 14; k++) { const d = k + 1 - ph, y = VY + 520 / d; if (y < FLOOR || y > H + 4) continue; c.lineWidth = 1.2 + 2.4 * (y - FLOOR) / (H - FLOOR); c.beginPath(); c.moveTo(0, y); c.lineTo(W, y); c.stroke(); }
|
|
66
|
+
c.restore();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ---------- 霓虹灯管字「カフェ」(自绘折线,不依赖字体) ----------
|
|
70
|
+
const KANA = {
|
|
71
|
+
'カ': [[[0.12, 0.34], [0.86, 0.34], [0.84, 0.62], [0.74, 0.94], [0.6, 0.86]], [[0.46, 0.08], [0.42, 0.5], [0.3, 0.78], [0.12, 0.96]]],
|
|
72
|
+
'フ': [[[0.12, 0.24], [0.86, 0.24], [0.8, 0.56], [0.62, 0.82], [0.34, 0.96]]],
|
|
73
|
+
'ェ': [[[0.28, 0.46], [0.72, 0.46]], [[0.5, 0.46], [0.5, 0.86]], [[0.18, 0.86], [0.82, 0.86]]],
|
|
74
|
+
};
|
|
75
|
+
function neonSign(c, t) {
|
|
76
|
+
const f = Math.floor(t * 30), on = (k) => { const h = U.hash(f, k); return !(h < 0.07 || (k === 1 && h < 0.22 && (f % 17) < 5)); };
|
|
77
|
+
const x0 = 868, y0 = 150, s = 104;
|
|
78
|
+
// 灯管底板
|
|
79
|
+
c.fillStyle = 'rgba(10,2,20,.55)'; c.fillRect(x0 - 18, y0 - 18, s * 3 + 24, s + 70);
|
|
80
|
+
[...'カフェ'].forEach((ch, k) => {
|
|
81
|
+
const lit = on(k), col = k === 1 ? C.cyan : C.pink;
|
|
82
|
+
KANA[ch].forEach(st => { c.beginPath(); st.forEach(([u, v], i) => { const x = x0 + k * s + u * (s - 14), y = y0 + v * s; i ? c.lineTo(x, y) : c.moveTo(x, y); });
|
|
83
|
+
c.lineJoin = 'round'; c.lineCap = 'round';
|
|
84
|
+
if (lit) { glowLine(c, col, 9, 30); c.strokeStyle = '#fff4fd'; c.lineWidth = 3; c.stroke(); } else { c.strokeStyle = 'rgba(120,60,120,.6)'; c.lineWidth = 6; c.stroke(); } });
|
|
85
|
+
});
|
|
86
|
+
// 小字 TEA ROOM(字体霓虹)
|
|
87
|
+
c.save(); c.font = '34px "Righteous-400"'; c.letterSpacing = '10px'; c.textBaseline = 'alphabetic';
|
|
88
|
+
c.shadowColor = C.yellow; c.shadowBlur = on(5) ? 18 : 0; c.fillStyle = on(5) ? '#fff2b0' : 'rgba(140,110,60,.6)'; c.fillText('TEA ROOM', x0 + 34, y0 + s + 44); c.restore();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------- Win95 对话框 TEA.EXE ----------
|
|
92
|
+
function dialog(c, lt) {
|
|
93
|
+
const x = 26, y = 330, w = 300, h = 168;
|
|
94
|
+
c.save(); c.fillStyle = '#c0c0c0'; c.fillRect(x, y, w, h);
|
|
95
|
+
c.fillStyle = '#ffffff'; c.fillRect(x, y, w, 3); c.fillRect(x, y, 3, h); c.fillStyle = '#404040'; c.fillRect(x, y + h - 3, w, 3); c.fillRect(x + w - 3, y, 3, h);
|
|
96
|
+
const tg = c.createLinearGradient(x, 0, x + w, 0); tg.addColorStop(0, '#000080'); tg.addColorStop(1, '#1084d0'); c.fillStyle = tg; c.fillRect(x + 6, y + 6, w - 12, 30);
|
|
97
|
+
c.font = '18px "Poppins-700"'; c.fillStyle = '#fff'; c.textBaseline = 'middle'; c.fillText('TEA.EXE', x + 14, y + 22);
|
|
98
|
+
c.fillStyle = '#c0c0c0'; c.fillRect(x + w - 32, y + 10, 22, 20); c.fillStyle = '#000'; c.font = '16px "Poppins-700"'; c.fillText('×', x + w - 26, y + 20);
|
|
99
|
+
c.font = '17px "Poppins-600"'; c.fillStyle = '#000'; c.fillText('Brewing tea... ' + Math.min(99, Math.floor(18 + lt * 70)) + '%', x + 16, y + 64);
|
|
100
|
+
c.fillStyle = '#fff'; c.fillRect(x + 16, y + 86, w - 32, 26); c.fillStyle = '#808080'; c.fillRect(x + 16, y + 86, w - 32, 2);
|
|
101
|
+
const n = Math.min(17, Math.floor(3 + lt * 14)); c.fillStyle = '#000080'; for (let i = 0; i < n; i++) c.fillRect(x + 20 + i * 15.5, y + 90, 12, 18);
|
|
102
|
+
c.fillStyle = '#c0c0c0'; c.fillRect(x + w / 2 - 44, y + 124, 88, 30); c.fillStyle = '#fff'; c.fillRect(x + w / 2 - 44, y + 124, 88, 2); c.fillStyle = '#404040'; c.fillRect(x + w / 2 - 44, y + 152, 88, 2);
|
|
103
|
+
c.fillStyle = '#000'; c.font = '16px "Poppins-600"'; c.fillText('OK', x + w / 2 - 12, y + 140);
|
|
104
|
+
c.restore();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ---------- 桌+大理石胸像 ----------
|
|
108
|
+
function table(c, t) {
|
|
109
|
+
c.fillStyle = '#0e0420'; c.fillRect(810, 618, 400, 28); c.fillRect(842, 646, 20, 259); c.fillRect(1160, 646, 20, 259);
|
|
110
|
+
c.beginPath(); c.moveTo(810, 618); c.lineTo(1210, 618); glowLine(c, C.cyan, 3, 16);
|
|
111
|
+
c.beginPath(); c.moveTo(810, 646); c.lineTo(1210, 646); glowLine(c, C.pink, 2, 10);
|
|
112
|
+
// 胸像(朝右的侧脸剪影+大理石渐变+粉青轮廓光)
|
|
113
|
+
const bust = new Path2D(); const bx = 900, by = 618;
|
|
114
|
+
[[-48, 0], [-50, -22], [-30, -38], [-18, -44], [-16, -62], [-24, -76], [-26, -100], [-18, -122], [0, -132], [20, -128], [30, -112], [36, -100], [44, -92], [38, -86], [42, -78], [36, -72], [36, -62], [24, -58], [20, -46], [34, -38], [52, -22], [50, 0]].forEach(([x, y], i) => i ? bust.lineTo(bx + x, by + y) : bust.moveTo(bx + x, by + y)); bust.closePath();
|
|
115
|
+
const mg = c.createLinearGradient(bx - 50, by - 130, bx + 50, by); mg.addColorStop(0, '#f6eefa'); mg.addColorStop(0.6, '#c9b8d8'); mg.addColorStop(1, '#8a6aa8'); c.fillStyle = mg; c.fill(bust);
|
|
116
|
+
c.save(); c.clip(bust); c.strokeStyle = 'rgba(140,110,160,.5)'; c.lineWidth = 1.2; [[[-40, -10], [-10, -40], [10, -70]], [[20, -20], [30, -50]], [[-20, -90], [0, -110]]].forEach(v => { c.beginPath(); v.forEach(([x, y], i) => i ? c.lineTo(bx + x, by + y) : c.moveTo(bx + x, by + y)); c.stroke(); }); c.restore();
|
|
117
|
+
c.strokeStyle = 'rgba(255,79,216,.9)'; c.lineWidth = 2.5; c.shadowColor = C.pink; c.shadowBlur = 14; c.stroke(bust); c.shadowBlur = 0;
|
|
118
|
+
c.fillStyle = '#5a3a7a'; c.beginPath(); c.arc(bx + 22, by - 98, 3, 0, TAU); c.fill();
|
|
119
|
+
// 胸像戴的复古太阳镜(梗)
|
|
120
|
+
c.fillStyle = '#111'; c.fillRect(bx + 8, by - 104, 34, 9); c.fillStyle = C.cyan; c.fillRect(bx + 12, by - 102, 26, 2);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ---------- 角色:深色平涂 → 双色轮廓辉光 ----------
|
|
124
|
+
function girl(c, G, ch, t) {
|
|
125
|
+
const pal = { skin: '#f4c4d8', skinS: '#b8789e', hair: '#ffe08a', hairS: '#d89a5a', top: '#8f7cf6', topS: '#5a44c8', skirt: '#4fd0e0', skirtS: '#2a7a9a' };
|
|
126
|
+
c.save(); c.lineJoin = 'round'; c.lineCap = 'round';
|
|
127
|
+
const fill = (p, a, b, x0 = 1100, x1 = 1460) => { if (!p) return; const g = c.createLinearGradient(x0, 0, x1, 0); g.addColorStop(0, a); g.addColorStop(1, b); c.fillStyle = g; c.fill(p); };
|
|
128
|
+
fill(G.farSleeve, pal.topS, pal.topS); fill(G.farHand, pal.skinS, pal.skinS);
|
|
129
|
+
fill(G.skirt, pal.skirt, pal.skirtS);
|
|
130
|
+
c.save(); c.clip(G.skirt); c.strokeStyle = 'rgba(20,40,80,.35)'; c.lineWidth = 3; for (let x = 1100; x < 1460; x += 22) { c.beginPath(); c.moveTo(x, 640); c.lineTo(x - 30, 940); c.stroke(); } c.restore(); // 百褶
|
|
131
|
+
fill(G.shoe, '#fff', '#c8c8ff');
|
|
132
|
+
fill(G.torso, pal.top, pal.topS, 1290, 1420);
|
|
133
|
+
fill(G.neck, pal.skin, pal.skinS, 1286, 1324);
|
|
134
|
+
{ const nk = G.A.neck; c.fillStyle = '#ffffff'; c.beginPath(); c.moveTo(nk[0] - 22, nk[1] - 4); c.lineTo(nk[0] + 26, nk[1]); c.lineTo(nk[0] + 4, nk[1] + 34); c.closePath(); c.fill(); c.fillStyle = C.cyan; c.fillRect(nk[0] - 4, nk[1] + 40, 6, 120); } // 白领口+青色拉链线
|
|
135
|
+
fill(G.hairBack, pal.hair, pal.hairS, 1260, 1410); fill(G.bun, pal.hair, pal.hairS);
|
|
136
|
+
// 发圈(粉)
|
|
137
|
+
c.strokeStyle = C.hot; c.lineWidth = 8; c.beginPath(); c.arc(G.bunSpiral[0] - 18, G.bunSpiral[1] + 6, 14, -1.2, 1.6); c.stroke();
|
|
138
|
+
fill(G.face, pal.skin, pal.skinS, 1250, 1330); fill(G.bangs, pal.hair, pal.hairS, 1250, 1335);
|
|
139
|
+
c.strokeStyle = 'rgba(200,120,60,.6)'; c.lineWidth = 2; G.hairLines.forEach(h => c.stroke(h));
|
|
140
|
+
if (ch.blink) { c.strokeStyle = '#2a0a3a'; c.lineWidth = 2.6; c.stroke(G.lid); }
|
|
141
|
+
else { c.fillStyle = '#2a0a3a'; c.beginPath(); c.ellipse(G.eye.x - 1, G.eye.y + 1, 4, 5.5, 0, 0, TAU); c.fill(); c.fillStyle = C.cyan; c.beginPath(); c.arc(G.eye.x - 2, G.eye.y - 1, 1.6, 0, TAU); c.fill(); c.strokeStyle = '#2a0a3a'; c.lineWidth = 2.4; c.stroke(G.lid); }
|
|
142
|
+
c.fillStyle = C.hot; c.beginPath(); c.moveTo(...G.lips[0]); c.lineTo(...G.lips[1]); c.lineTo(...G.lips[2]); c.closePath(); c.fill();
|
|
143
|
+
fill(G.upperArm, pal.top, pal.topS, 1200, 1380); fill(G.foreArm, pal.top, pal.topS, 1200, 1380); fill(G.cuff, '#fff', '#d8c8ff', 1200, 1300); fill(G.hand, pal.skin, pal.skinS, 1180, 1260);
|
|
144
|
+
RIG.drawCup(c, G.cup, { body: '#1a0830', rim: '#ff9ad6', hw: 6 });
|
|
145
|
+
c.save(); c.translate(G.cup.x, G.cup.y); c.rotate(G.cup.tilt); c.beginPath(); c.moveTo(-G.cup.w / 2, 0); c.lineTo(-G.cup.w * 0.42, G.cup.h); c.lineTo(G.cup.w * 0.42, G.cup.h); c.lineTo(G.cup.w / 2, 0); glowLine(c, C.cyan, 2, 10); c.restore();
|
|
146
|
+
c.fillStyle = pal.skin; c.beginPath(); c.arc(G.thumb[0], G.thumb[1], 7, 0, TAU); c.fill();
|
|
147
|
+
// 轮廓辉光:朝窗(左)的一侧粉、背面青——同一条路径描两次,用 clip 半屏分色
|
|
148
|
+
const outline = [G.skirt, G.torso, G.face, G.hairBack, G.bun, G.upperArm, G.foreArm];
|
|
149
|
+
[[C.pink, 0, 1290], [C.cyan, 1290, W]].forEach(([col, a, b]) => { c.save(); c.beginPath(); c.rect(a, 0, b - a, H); c.clip(); c.shadowColor = col; c.shadowBlur = 16; c.strokeStyle = col; c.lineWidth = 3; outline.forEach(p => p && c.stroke(p)); c.restore(); });
|
|
150
|
+
c.restore();
|
|
151
|
+
}
|
|
152
|
+
function cat(c, K) {
|
|
153
|
+
c.save(); c.lineCap = 'round'; c.lineJoin = 'round';
|
|
154
|
+
c.strokeStyle = '#ff9a4a'; c.lineWidth = K.tailW; c.stroke(K.tail);
|
|
155
|
+
const tip = K.tailPts[K.tailPts.length - 1]; c.fillStyle = '#fff0fa'; c.beginPath(); c.arc(tip[0], tip[1], K.tailW / 2, 0, TAU); c.fill();
|
|
156
|
+
const og = c.createLinearGradient(420, 0, 660, 0); og.addColorStop(0, '#ffb070'); og.addColorStop(1, '#c0502a'); c.fillStyle = og; c.fill(K.body);
|
|
157
|
+
K.legs.forEach(l => { c.fillStyle = '#fff0fa'; c.fill(l); }); c.fillStyle = '#fff0fa'; c.fill(K.white);
|
|
158
|
+
c.fillStyle = og; c.fill(K.head);
|
|
159
|
+
c.save(); c.clip(K.head); c.fillStyle = '#fff0fa'; c.beginPath(); c.ellipse(K.nose[0] - 22, K.nose[1] + 12, 36, 26, 0, 0, TAU); c.fill(); c.restore();
|
|
160
|
+
c.strokeStyle = '#a03a1a'; c.lineWidth = 7; K.stripes.forEach(s => { c.beginPath(); c.moveTo(...s[0]); c.lineTo(...s[1]); c.stroke(); });
|
|
161
|
+
c.fillStyle = '#ff9ad6'; K.earInner.forEach(e => { c.beginPath(); e.forEach((p, i) => i ? c.lineTo(...p) : c.moveTo(...p)); c.fill(); });
|
|
162
|
+
K.eyes.forEach(e => { if (K.blink) { c.strokeStyle = '#2a0a3a'; c.lineWidth = 3; c.beginPath(); c.moveTo(e.x - 8, e.y); c.lineTo(e.x + 8, e.y); c.stroke(); }
|
|
163
|
+
else { c.shadowColor = C.cyan; c.shadowBlur = 10; c.fillStyle = C.cyan; c.beginPath(); c.arc(e.x, e.y, 8, 0, TAU); c.fill(); c.shadowBlur = 0; c.fillStyle = '#12052a'; c.beginPath(); c.ellipse(e.x + 2, e.y, 2.4, 6.5, 0, 0, TAU); c.fill(); } });
|
|
164
|
+
c.fillStyle = C.hot; c.beginPath(); c.arc(K.nose[0], K.nose[1], 5, 0, TAU); c.fill();
|
|
165
|
+
c.strokeStyle = '#ffe8ff'; c.lineWidth = 1.4; K.whiskers.forEach(w => { c.beginPath(); c.moveTo(...w[0]); c.lineTo(...w[1]); c.stroke(); });
|
|
166
|
+
[[C.pink, 0, 560], [C.cyan, 560, 900]].forEach(([col, a, b]) => { c.save(); c.beginPath(); c.rect(a, 0, b - a, H); c.clip(); c.shadowColor = col; c.shadowBlur = 14; c.strokeStyle = col; c.lineWidth = 3; [K.body, K.head].forEach(p => c.stroke(p)); c.restore(); });
|
|
167
|
+
c.restore();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ---------- ② VHS 后期:P.vhs(RGB 通道分离+跟踪噪声带撕裂+扫描线+OSD+暗角) ----------
|
|
171
|
+
const vhs = (c, S, t, lt) => P.vhs(c, S, t, lt, { osd: { label: 'PLAY', date: 'SEP. 04 2011', clock: '23:59' } });
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
draw(c, lt, t) {
|
|
175
|
+
const ch = P.choreo(lt, t);
|
|
176
|
+
const S = P.scratch('vwS'), g = S.getContext('2d'); g.reset();
|
|
177
|
+
g.drawImage(bg(), 0, 0);
|
|
178
|
+
floorGrid(g, t);
|
|
179
|
+
sunset(g, t);
|
|
180
|
+
neonSign(g, t);
|
|
181
|
+
dialog(g, lt);
|
|
182
|
+
table(g, t);
|
|
183
|
+
const K = RIG.cat({ tail: ch.tail, blink: ch.blink, breathe: ch.breathe });
|
|
184
|
+
cat(g, K);
|
|
185
|
+
const G = RIG.girl({ cup: ch.cup, sip: ch.sip, breathe: ch.breathe });
|
|
186
|
+
girl(g, G, ch, t);
|
|
187
|
+
P.steam(g, t, G.cup.x, G.cup.y - 8, { h: 60, n: 2, color: 'rgba(63,246,255,.85)', width: 3, spread: 12, wobble: 8 });
|
|
188
|
+
vhs(c, S, t, lt);
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
})();
|