<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://androman.pro/wp-content/themes/androman/assets/feed.xsl?ver=0.9.4" type="text/xsl"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>creative-code &#8212; ANDROMAN.PRO</title>
	<atom:link href="https://androman.pro/tag/creative-code/feed/" rel="self" type="application/rss+xml" />
	<link>https://androman.pro</link>
	<description>Независимый 1С-архитектор и AI-автоматизация корпоративных процессов: аудит, PoC на реальных данных, проверка качества и внедрение. · build 0.9.4</description>
	<lastBuildDate>Tue, 05 May 2026 11:57:19 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>Cyberpunk reveal-анимации — полный тур по эффектам</title>
		<link>https://androman.pro/2026/04/30/cyberpunk-anim-demo/</link>
					<comments>https://androman.pro/2026/04/30/cyberpunk-anim-demo/#respond</comments>
		
		<dc:creator><![CDATA[Androman.pro]]></dc:creator>
		<pubDate>Wed, 29 Apr 2026 21:00:00 +0000</pubDate>
				<category><![CDATA[дев-лог]]></category>
		<category><![CDATA[лаборатория]]></category>
		<category><![CDATA[creative-code]]></category>
		<category><![CDATA[GSAP]]></category>
		<category><![CDATA[ScrollTrigger]]></category>
		<category><![CDATA[vibe-coding]]></category>
		<category><![CDATA[киберпанк]]></category>
		<guid isPermaLink="false">https://androman.pro/2026/04/30/cyberpunk-anim-demo/</guid>

					<description><![CDATA[Шесть scroll-анимаций для постов блога — decoder, glitch, scanline, CRT power-on, stutter, pin. Собрал всё в одном тест-посте чтобы посмотреть как живёт на реальном длинном контенте.]]></description>
										<content:encoded><![CDATA[<p>Пока делал блог, написал шесть анимаций для постов. Захотел посмотреть как они все вместе смотрятся на реальном длинном тексте — специально под это сделал этот пост. Ничего особенного, просто скролли вниз.</p>
<p>Шесть эффектов: символьный дешифратор на главном заголовке, цветовые помехи на подзаголовках, сканирующая линия на блоках кода, включение ЭЛТ-монитора на картинках, прерывистое появление параграфов и прилипающие заголовки при прокрутке. Почти каждый раздел ниже показывает что-то новое.</p>
<h2>01 / Установка соединения</h2>
<p><img decoding="async" alt="lava-orb WebGL preview" src="https://androman.pro/wp-content/themes/androman/assets/lab-previews/lava-orb.png"></p>
<p>Когда страница загружается, главный заголовок делает ту же штуку что и на главной <code>androman.pro</code> — символы из мусорной кучи (<code>█▓▒░#@$%&amp;*+=!?&gt;</code>) по одному встают на свои места, и каждый зафиксированный символ на мгновение вспыхивает голубым. Через ~1.5 секунды заголовок устаканивается с лёгким свечением.</p>
<p>Мета-строка сверху (дата, тег, время чтения) при загрузке расширяется по расстоянию между буквами — как на печатной машинке, не плавное появление. Потом обложка (если есть) делает включение старого ЭЛТ-монитора: сжатая в полоску картинка за 1.6 секунды разворачивается в полный размер с вспышкой яркости.</p>
<h3>1.1 Что под капотом</h3>
<p>Сами эффекты — связка из двух частей: GSAP ScrollTrigger (библиотека анимаций + модуль отслеживания прокрутки) следит когда элемент въезжает в видимую область страницы, и навешивает CSS-класс. А CSS-анимации с <code>steps()</code> делают саму картинку. Анимации выполняются на видеокарте и не подвисают при нагрузке на страницу.</p>
<pre class="highlight"><code class="language-javascript">// Helper: trigger CSS class on scroll-into-view
function triggerOnScroll(selector, className, opts){
  gsap.utils.toArray(selector).forEach(function(el){
    ScrollTrigger.create({
      trigger: el,
      start: opts.start || 'top 88%',
      once: opts.once !== false,
      onEnter: function(){
        el.classList.remove(className);
        void el.offsetWidth;  // reflow gimmick
        el.classList.add(className);
      }
    });
  });
}

// h2/h3 — RGB glitch shift
triggerOnScroll('.post-content &gt; h2, .post-content &gt; h3', 'cyber-glitch');

// Code blocks — scanline reveal
triggerOnScroll('.post-content &gt; pre', 'cyber-scan');
</code></pre>
<p>Ключевой трюк — <code>steps(N)</code> в CSS-анимации. Обычное плавное движение (<code>ease-out</code>) даёт современный мягкий переход, а <code>steps(5)</code> или <code>steps(10)</code> — прерывистое, покадровое. Как анимация в старом мультике, не как iOS.</p>
<h2>02 / Киберпанк-приёмы</h2>
<p>Если разобрать что отделяет «киберпанк» от «современная анимация в блоге», то приёмы вполне конкретные. Не один универсальный, а набор:</p>
<ul>
<li><strong>RGB shift</strong> — красный, зелёный и синий каналы текста чуть съезжают в разные стороны, как помехи на плохом сигнале</li>
<li><strong>Scanline</strong> — горизонтальная светящаяся линия проходит сверху вниз и «открывает» элемент</li>
<li><strong>Decoder</strong> — символы из мусорной кучи по одному встают на свои места, каждый вспыхивает при фиксации</li>
<li><strong>CRT power-on</strong> — как включается старый ЭЛТ-монитор: сначала тонкая полоска, потом резкое разворачивание с вспышкой яркости</li>
<li><strong>Stutter</strong> — покадровое, прерывистое движение вместо плавного</li>
<li><strong>Flicker</strong> — прозрачность дёргается 0 → 0.4 → 0 → 0.7 → 1, имитация плохого сигнала</li>
</ul>
<p>Те же приёмы я уже использовал в своих WebGL-экспериментах (<a href="https://andromanpro.github.io/lava-orb/">lava-orb</a>, <a href="https://andromanpro.github.io/orb-2048/">orb-2048</a>, <a href="https://andromanpro.github.io/fire-particle-editor/">fire-particle-editor</a>) — теперь перенёс в посты блога.</p>
<h3>2.1 Прилипающий заголовок раздела</h3>
<p>Самый полезный трюк для длинных постов — когда подзаголовок доезжает до верха страницы, он там «прилипает» и остаётся на виду пока читаешь раздел. Как только следующий подзаголовок подъезжает снизу — предыдущий отпускается. Всегда видно в каком разделе находишься.</p>
<pre class="highlight"><code class="language-javascript">gsap.utils.toArray('.post-content &gt; h2').forEach(function(h2, idx, arr){
  var nextH2 = arr[idx + 1] || null;
  ScrollTrigger.create({
    trigger: h2,
    start: 'top 60px',
    endTrigger: nextH2 || '.post-content',
    end: 'top 60px',
    pin: h2,
    pinSpacing: false,
    pinType: 'fixed'
  });
});
</code></pre>
<p>Работает только если подзаголовки идут один за другим — что норма для длинного поста. На короткой странице с одним подзаголовком просто ничего не происходит.</p>
<h2>03 / Анимации, привязанные к прокрутке</h2>
<p><img decoding="async" alt="fire-particle-editor preview" src="https://androman.pro/wp-content/themes/androman/assets/lab-previews/fire-particle-editor.png"></p>
<p>Помимо «запустить при появлении» есть второй режим — привязка к прокрутке. Эффект не запускается резко, а плавно следует за позицией скролла. Медленно скроллишь — медленный эффект. Быстро — быстрый.</p>
<p>Обложка поста на этом сайте работает в этом режиме: лёгкий параллакс (картинка движется чуть медленнее текста) и нарастающее свечение при уходе из видимой области. Едва заметно, но убирает ощущение статичной вставки.</p>
<blockquote>
<p>Чем сильнее привязка к прокрутке, тем тоньше должен быть эффект. Резкие изменения цвета или позиции при быстром скролле — укачивает. Лучше: прозрачность, тени, смещение на 5-15px. Большие движения — только для разовых эффектов при появлении.</p>
</blockquote>
<h3>3.1 Когда этот режим не подходит</h3>
<p>Привязка к прокрутке не работает для:</p>
<ol>
<li>Текстовых эффектов (дешифратор, печатная машинка) — дёргается когда скроллишь туда-сюда</li>
<li>Блоков кода с подсветкой синтаксиса — библиотека подсветки расставляет теги при инициализации и конфликтует с анимацией появления</li>
<li>Полей ввода — анимация смещения сбивает фокус</li>
</ol>
<p>Для всего этого — разовый запуск при появлении: <code>toggleActions: 'play none none reverse'</code> или <code>once: true</code>.</p>
<h2>04 / Производительность</h2>
<p>GSAP вместе с модулем прокрутки весит ~30 КБ в сжатом виде и загружается с внешнего CDN — сети серверов по всему миру, откуда файлы отдаются быстро и кэшируются в браузере. Для повторного посетителя загрузка нулевая: файл уже лежит в кэше с прошлого раза.</p>
<p>На остальных страницах (главная, архив, лаборатория) GSAP <strong>не подгружается вообще</strong> — в теме стоит проверка, что библиотека нужна только на страницах отдельных постов. Поэтому показатели скорости главной страницы не страдают.</p>
<pre class="highlight"><code class="language-php">if ( is_singular( 'post' ) ) {
    wp_enqueue_style( 'androman-single-cyber', /* ... */ );
    wp_enqueue_script( 'gsap-core',          /* CDN */ );
    wp_enqueue_script( 'gsap-scrolltrigger', /* CDN */ );
    wp_enqueue_script( 'androman-single-anim', /* local */ );
}
</code></pre>
<h3>4.1 Режим без анимаций</h3>
<p>В Windows, macOS и Android есть системная настройка «уменьшить анимации» — для людей, которым мигание и движение на экране некомфортно. В эффектах это учтено. В CSS прописан override для этого режима:</p>
<pre class="highlight"><code class="language-css">@media (prefers-reduced-motion: reduce) {
  .cyber-glitch, .cyber-scan, .cyber-crt,
  .cyber-stutter-p, .cyber-stutter-x,
  .cyber-meta-in, .cyber-flicker {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    filter: none !important;
  }
}
</code></pre>
<p>И в JavaScript: если включён этот режим, скрипт анимаций сразу завершает работу не запуская ничего. Все элементы которые должны были «появляться» — сразу видны. Контент доступен, анимаций нет.</p>
<h2>05 / Что дальше</h2>
<p>Тестовый пост — для разовой проверки. Пожил на длинном тексте, выглядит как надо.</p>
<p>Следующее что хочу попробовать — звук: короткий клик когда символ дешифратора встаёт на место, тихий гул при CRT-включении. Плюс пасхалка: <code>↑↑↓↓←→←→BA</code> включает «режим старого ЭЛТ» на всём сайте — полосы сканирования, насыщенность +40%, чуть больше контраста. Ещё есть идея с магнитным курсором (~30 строк) и 3D-наклоном карточек лаборатории при наведении. Каждое — на час. Пока в списке, не в расписании.</p>
<h2>06 / Сравнение CRT vs default</h2>
<p>Слева — картинка <strong>без эффекта</strong> (помечена <code>class="no-anim"</code>). Справа — <strong>с CRT power-on</strong>: scaleY 0.02→1 (как ЭЛТ-монитор включается из тонкой линии), brightness peak 2.2, saturate 0→1.2→1, hue-rotate 20°→0, blur 2px→0. Длительность <strong>1.6s</strong>.</p>
<p>Кликни <strong>«▷ REPLAY»</strong> чтобы пересмотреть эффект на правой картинке.</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin: 24px 0; align-items: start;">
<figure style="margin: 0;">
    <img decoding="async" class="no-anim" src="https://androman.pro/wp-content/themes/androman/assets/lab-previews/orb-2048.png" alt="Без эффекта" style="width:100%; height:auto; border-radius:8px; display:block;"><figcaption style="margin-top: 8px; font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--text-muted); letter-spacing: 0.1em; text-align: center;">// БЕЗ ЭФФЕКТА</figcaption></figure>
<figure style="margin: 0;">
    <img decoding="async" id="crt-demo-img" src="https://androman.pro/wp-content/themes/androman/assets/lab-previews/orb-2048.png" alt="С CRT power-on" style="width:100%; height:auto; border-radius:8px; display:block;"><figcaption style="margin-top: 8px; font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--cyan); letter-spacing: 0.1em; text-align: center;">// CRT POWER-ON</figcaption><div style="text-align: center; margin-top: 6px;">
      <button type="button" class="cyber-crt-replay" data-target="#crt-demo-img">▷ REPLAY</button>
    </div>
</figure>
</div>
<p><em>// END OF TRANSMISSION · скролл назад оставит тебя на текущей секции</em></p>
<p>Работает как надо — живёт в теме. Большую часть времени потратил не на написание, а на подбор тайминга: на коротком тексте эти вещи не видны, а на длинном сразу понятно где слишком резко, а где не хватает. Этот пост и был для этого.</p>


<p style="margin-top:1em;font-family:monospace;font-size:0.9em;">→ <a href="https://androman.pro/2026/04/30/cyberpunk-anim-demo/">открыть на androman.pro</a></p>]]></content:encoded>
					
					<wfw:commentRss>https://androman.pro/2026/04/30/cyberpunk-anim-demo/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Когда заниматься 1С становится скучно</title>
		<link>https://androman.pro/2026/04/28/1c-stalo-skuchno/</link>
					<comments>https://androman.pro/2026/04/28/1c-stalo-skuchno/#respond</comments>
		
		<dc:creator><![CDATA[Androman.pro]]></dc:creator>
		<pubDate>Sun, 26 Apr 2026 21:00:00 +0000</pubDate>
				<category><![CDATA[дев-лог]]></category>
		<category><![CDATA[лаборатория]]></category>
		<category><![CDATA[1С]]></category>
		<category><![CDATA[Canvas]]></category>
		<category><![CDATA[creative-code]]></category>
		<category><![CDATA[npm]]></category>
		<category><![CDATA[vibe-coding]]></category>
		<category><![CDATA[WebGL]]></category>
		<guid isPermaLink="false">https://androman.pro/2026/04/27/1c-stalo-skuchno/</guid>

					<description><![CDATA[1С-разработчик, не знающий что такое display:flex, выкатил 7 WebGL/Canvas проектов за 5 недель. Потому что заскучал на ползунке опросника.]]></description>
										<content:encoded><![CDATA[<style>
.lava-orb-demo input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  height: 12px;
  background: linear-gradient(to right, #3b82f6 0%, #06b6d4 25%, #fbbf24 60%, #ef4444 100%);
  border-radius: 6px;
  border: 1px solid rgba(0, 212, 255, 0.35);
  box-shadow: 0 0 12px rgba(0, 212, 255, 0.2);
  outline: none;
  cursor: pointer;
}
.lava-orb-demo input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: transparent;
  opacity: 0;
  cursor: grab;
}
.lava-orb-demo input[type="range"]::-moz-range-thumb {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: transparent;
  border: 0;
  opacity: 0;
  cursor: grab;
}
</style>
<div class="lava-orb-demo" style="text-align:center;padding:36px 24px;background:rgba(8,20,36,0.6);border:1px solid var(--border);border-radius:12px;margin:32px 0;">
<div style="font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--text-muted);letter-spacing:0.25em;margin-bottom:6px;">// LIVE DEMO · ДВА ОРБА</div>
<div style="font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--text-dim);letter-spacing:0.05em;margin-bottom:24px;">дёрни резко — оторвутся от ползунка → сведи вместе — взорвутся</div>
<div style="max-width:480px;margin:0 auto 48px;padding:0 40px;">
    <input type="range" min="0" max="10" value="3" step="1" id="lo-demo-slider-1" style="width:100%;"></p>
<div style="text-align:center;margin-top:14px;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:0.2em;"><span id="lo-demo-label-1">холодный</span> · <span id="lo-demo-val-1" style="font-size:18px;">3</span></div>
</p></div>
<div style="max-width:480px;margin:0 auto;padding:0 40px;">
    <input type="range" min="0" max="10" value="7" step="1" id="lo-demo-slider-2" style="width:100%;"></p>
<div style="text-align:center;margin-top:14px;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:0.2em;"><span id="lo-demo-label-2">тёплый</span> · <span id="lo-demo-val-2" style="font-size:18px;">7</span></div>
</p></div>
</div>
<script src="https://unpkg.com/@andromanpro/lava-orb@latest/dist/lava-orb.js"></script>
<script>
(function(){
  // value (0-10) → { label, color, glow }
  function temp(v){
    var n = +v;
    if (n <= 1)  return { label: 'мороз',       color: '#3b82f6', glow: 'rgba(59,130,246,0.5)' };
    if (n <= 3)  return { label: 'холодный',    color: '#06b6d4', glow: 'rgba(6,182,212,0.5)'  };
    if (n <= 5)  return { label: 'прохладный',  color: '#84cc16', glow: 'rgba(132,204,22,0.5)' };
    if (n <= 7)  return { label: 'тёплый',      color: '#fbbf24', glow: 'rgba(251,191,36,0.5)' };
    if (n <= 9)  return { label: 'горячий',     color: '#f97316', glow: 'rgba(249,115,22,0.5)' };
    return         { label: 'огонь',         color: '#ef4444', glow: 'rgba(239,68,68,0.5)'  };
  }
  function update(v, labelEl, valEl){
    var t = temp(v);
    valEl.textContent = v;
    labelEl.textContent = t.label;
    labelEl.style.color = t.color;
    valEl.style.color = t.color;
    valEl.style.textShadow = '0 0 12px ' + t.glow;
  }
  function init(){
    var i1 = document.getElementById('lo-demo-slider-1');
    var v1 = document.getElementById('lo-demo-val-1');
    var l1 = document.getElementById('lo-demo-label-1');
    var i2 = document.getElementById('lo-demo-slider-2');
    var v2 = document.getElementById('lo-demo-val-2');
    var l2 = document.getElementById('lo-demo-label-2');
    if (!i1 || !i2 || !window.LavaOrb) { setTimeout(init, 200); return; }
    var group = (typeof LavaOrb.createGroup === 'function')
      ? LavaOrb.createGroup({ name: 'demo' })
      : undefined;
    LavaOrb.attach(i1, { size: 60, group: group, detach: true, onChange: function(v){ update(v, l1, v1); } });
    LavaOrb.attach(i2, { size: 60, group: group, detach: true, onChange: function(v){ update(v, l2, v2); } });
    update(i1.value, l1, v1);
    update(i2.value, l2, v2);
  }
  init();
})();
</script>
<hr>
<p>В общем делаю автоматический воркфлоу по анализу бизнес-процессов в 1С для обследования предприятий. Добавил генерацию опросника — можно выбрать роль или должность, протыкать варианты ответов на вопросы, которые были выявлены ранее на основе анализа конфигурации и документации, и выгрузить всё в JSON. Не нужно тратить время на многочасовые интервью.</p>
<p>Но дело не в этом.</p>
<p>Посмотрел я, с какой скоростью с ИИ получится сделать опросник. Добавил тёмную тему на выбор, контроль неотвеченных вопросов, даже салют при завершении. Всё, можно закрывать.</p>
<p>А потом мой взгляд упал на скучные ползунки выбора приоритетов.</p>
<p>Тут-то всё и заверте…</p>
<hr>
<p>Наступили выходные, а ощущение незавершённости не отпускало. Обычный ползунок от 1 до 10 — это же просто цифра, не показательно.</p>
<p>Пришлось развивать — прототип, другой, третий. Покрутил настройки частиц. Узнал что есть Canvas 2D и WebGL 2 (ну как узнал — просто что они существуют). Добавил DOOM-fire (прям как из культовой игры, ну вы поняли) режим как альтернативный движок пламени. Попробовал сделать взрывы, физику воды, отрывающиеся от ползунка орбы, которые улетают по дуге.</p>
<p>Задача была в том числе — проверить, получится ли через ИИ сделать что-то в незнакомой области. Без глубокого погружения в шейдеры и прочие термины которые я впервые увидел на прошлой неделе.</p>
<p>Получилось.</p>
<p>Я думал — сделаю пару эффектов на ползунок и пойду обратно к опроснику.</p>
<p><strong>Что выросло за 5 недель параллельной работы:</strong></p>
<ul>
<li><strong>npm-библиотека <code>@andromanpro/lava-orb</code></strong> — привязывается к любому <code>&lt;input type="range"&gt;</code> одной строкой. От мороза до огня, взрывов и молний.</li>
<li><strong>2 одностраничные игры</strong> — ORB 2048 (жидкие сливающиеся сферы с процедурной музыкой) и ORB ARKANOID (арканоид где блоки — орбы с физикой волн). Оба работают офлайн одним HTML-файлом.</li>
<li><strong>2 интерактивных редактора</strong> — для тонкой настройки жидкости и огня в реальном времени. С экспортом пресетов.</li>
<li><strong>Библиотека из 7 WebGL2-фонов</strong> — drop-in для любой страницы.</li>
</ul>
<p>Всё это — MIT, на GitHub.</p>
<p><img decoding="async" alt="От холода к огню — один и тот же ползунок, разные значения" src="https://raw.githubusercontent.com/andromanpro/lava-orb/main/article/gifs/02-cold-to-hot.gif"></p>
<p>Ни одного профильного курса по веб-разработке я не проходил. Я вообще не знаю, что такое <code>box-sizing</code> и <code>display: flex</code>)))</p>
<hr>
<p>Помните 2048? Ту простую головоломку с плитками, которая в 2014-м разошлась по всем сторам за несколько недель. Сделал свою версию — с жидкими светящимися сферами вместо цифровых плиток. И залип.</p>
<p><strong>Геймплей:</strong><br />
&#8212; Классическая сетка 4×4, свайпы / стрелки / WASD<br />
&#8212; Ячейки — жидкие metaballs через marching squares, сливаются как капли ртути<br />
&#8212; На высоких значениях — процедурный огонь частицами с glow и затуханием<br />
&#8212; При 2048 — <strong>supernova</strong>: space warp, chromatic aberration, 250 частиц, тряска камеры<br />
&#8212; Игра продолжается — 4096, 8192, логотип подхватывает</p>
<p><strong>Звук:</strong><br />
8 процедурных треков через Web Audio API, никаких mp3. Oscillator + filter + reverb синтезируются в браузере. Адаптивный темп — чем больше ячеек, тем быстрее.</p>
<p><strong>Рендеринг:</strong><br />
WebGL2 с Canvas2D fallback. 4 фона на выбор (Cyberpunk / Space / Dark / Synthwave). RU/EN локализация.</p>
<p><strong>Бот / Autoplay</strong> — запускаешь, смотришь как играет сам. Максимум набирает <strong>65 536</strong> (16 слияний — дальше на сетке 4×4 места нет, но есть настройка для большей сетки!).</p>
<p>Для СДВГ-шников — идеальная сенсорная подкормка. Запускаешь на втором мониторе или в углу экрана, свернул — периферическое зрение ловит постоянное мельтешение жидких сфер, мозгу хорошо, на основной задаче сидишь ровнее.</p>
<p>Режим отладки оставил прямо в сборке — FPS, хитбоксы, статистика. Не стал прятать от прода, пусть смотрит кто хочет.</p>
<p>Один файл <code>Orb-2048.html</code> ~330 KB. Скачал на телефон в самолёт — играешь офлайн.</p>
<div class="game-embed" data-src="https://andromanpro.github.io/orb-2048/" data-label="ЗАПУСТИТЬ ORB 2048" style="position:relative;cursor:pointer;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:#030712;margin:24px 0;">
  <img decoding="async" src="https://raw.githubusercontent.com/andromanpro/orb-2048/main/media/gameplay1.gif" alt="ORB 2048 gameplay" style="display:block;width:100%;height:auto;"></p>
<div class="game-embed-overlay" style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(3,7,18,0.55);transition:background 0.2s;">
    <button type="button" style="background:var(--cyan);color:#030712;border:none;padding:14px 28px;font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:600;border-radius:4px;cursor:pointer;letter-spacing:0.15em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ЗАПУСТИТЬ ORB 2048</button>
  </div>
</div>
<p><strong>Live:</strong> <a href="https://andromanpro.github.io/orb-2048/">andromanpro.github.io/orb-2048</a></p>
<hr>
<p>Если 2048 — про «плавное слияние», то арканоид — про «разрушение». Идея: блоки — это не кубики, а светящиеся орбы-капсулы с жидкостью. Она реагирует на удар волной, а при разрушении выливается вниз, передавая волну соседям.</p>
<p>Так и сделал.</p>
<p><strong>Геймплей:</strong><br />
&#8212; 15 уровней, каждый со своей темой, музыкой и фоном<br />
&#8212; 9 типов орбов — Fire, Ice, Water, Earth, Lava, Steel, Gold, TNT, Rainbow (у каждого своя физика и звук удара)<br />
&#8212; 8 power-up — расширение/сужение платформы, огненный шар, мультишар, прилипание, лазерные турели, жизнь, замедление времени<br />
&#8212; Комбо-система и локальная таблица рекордов</p>
<p><strong>Технологии:</strong><br />
&#8212; WebGL2 SDF-шейдер для орбов — круглый SDF, 2 слоя жидкости с Catmull-Rom интерполяцией, спекулярный блик<br />
&#8212; Verlet 6-колоночная пружинная симуляция волн<br />
&#8212; Процедурная музыка на каждый уровень</p>
<p><strong>Тюнинг шарика:</strong><br />
Тип хвоста (FIRE / LAVA / PLASMA / ICE), длина S/M/L, размер S/M/L. Превью шарика в настройках — живая анимация на весь экран, клик для запуска.</p>
<p><strong>Бот</strong> со скоростью ×2.5. Прицеливается в конкретные орбы, проходит уровни сам. Можно включить и бесконечный режим — уровни продолжают генерироваться сверх 15 штук, бот разбивает бесконечно. Играет лучше меня.</p>
<p>Запустил бота в бесконечном режиме, свернул окно в угол — и пока работаешь в основном, боковым зрением ловишь как шарик дробит орбы, жидкость выливается, комбо растут.</p>
<p>Режим отладки тоже оставил в сборке — FPS, хитбоксы, прыжки между уровнями через <code>[</code> и <code>]</code>. Dev-инструменты не прятал.</p>
<p><strong>97 unit-тестов</strong> встроенных в <code>game.js</code>. Я сам не представлял, что в браузерной игре буду их писать. Но если разрабатывать <strong>с</strong> ИИ — приходится проверять каждый шаг.</p>
<p>Один файл ~225 KB, работает офлайн.</p>
<div class="game-embed" data-src="https://andromanpro.github.io/orb-arkanoid/" data-label="ЗАПУСТИТЬ ORB ARKANOID" style="position:relative;cursor:pointer;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:#030712;margin:24px 0;">
  <img decoding="async" src="https://raw.githubusercontent.com/andromanpro/orb-arkanoid/main/media/gameplay.gif" alt="ORB ARKANOID gameplay" style="display:block;width:100%;height:auto;"></p>
<div class="game-embed-overlay" style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(3,7,18,0.55);transition:background 0.2s;">
    <button type="button" style="background:var(--cyan);color:#030712;border:none;padding:14px 28px;font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:600;border-radius:4px;cursor:pointer;letter-spacing:0.15em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ЗАПУСТИТЬ ORB ARKANOID</button>
  </div>
</div>
<p><strong>Live:</strong> <a href="https://andromanpro.github.io/orb-arkanoid/">andromanpro.github.io/orb-arkanoid</a></p>
<p><strong>Важный юридический момент.</strong> Arkanoid — зарегистрированная торговая марка Taito с 1986 года (легендарная японская компания, сейчас в составе Square Enix). Моя игра называется ORB ARKANOID чисто как дань уважения жанру — пока это open-source прикол, никто не придёт.</p>
<p>Но если я начну рубить с этого капусту — Taito быстро найдёт меня через юристов. Код можно форкать (MIT разрешает), но имя «Arkanoid» — не моё чтобы его дарить. Для коммерческого форка придётся переименовать в что-то нейтральное вроде <strong>ORB BREAKOUT</strong> (слово «breakout» — общий жанр, не товарный знак), поменять логотип — и тогда можно идти в сторы.</p>
<p>Это к вопросу «а можно я возьму и продам» — в принципе можно, но с переименованием.</p>
<hr>
<p>Решил посчитать — сколько я реально на это потратил.</p>
<p>Прошёлся по логам сессий Claude Code — там у каждого сообщения timestamp. Если между сообщениями меньше 2 минут — это активная работа. Больше 2 минут — отошёл или задумался без ИИ.</p>
<p><strong>Итог: 41 час активного общения. На 7 артефактов, 40 981 строку кода.</strong></p>
<p>Для сравнения, 1С-разработчику без веб-опыта (это я) без ИИ на это ушло бы:<br />
&#8212; 3 месяца на изучение стека (HTML / CSS / JS / Canvas2D / WebGL2 / WebAudio)<br />
&#8212; Ещё ~6 месяцев на реализацию</p>
<p>Грубая оценка — около 8 месяцев full-time вместо 5 недель коротких периодических сессий. Не научная цифра, просто мой внутренний «сколько бы я на это убил, если бы шёл один».</p>
<p>Ускорение не в «ИИ пишет код за тебя». Оно в том, что ИИ убирает <strong>барьер незнания</strong>. Можешь формулировать задачу словами и сразу получать рабочий прототип — вместо того чтобы тонуть в документации к шейдерам, которая предполагает, что ты уже знаешь что такое SDF, metaballs и Verlet integration.</p>
<p>Для меня это самая сильная зона ИИ: незнакомые специализированные домены, где сначала нужно месяцами накапливать словарь, а только потом начинать делать.</p>
<script>
(function(){
  document.querySelectorAll('.game-embed').forEach(function(el){
    var overlay = el.querySelector('.game-embed-overlay');
    if (overlay) {
      el.addEventListener('mouseenter', function(){ overlay.style.background = 'rgba(3,7,18,0.25)'; });
      el.addEventListener('mouseleave', function(){ overlay.style.background = 'rgba(3,7,18,0.55)'; });
    }
    el.addEventListener('click', function(){
      var src = el.dataset.src;
      if (!src) return;
      var iframe = document.createElement('iframe');
      iframe.src = src;
      iframe.setAttribute('allow', 'autoplay; fullscreen');
      iframe.setAttribute('loading', 'lazy');
      iframe.style.cssText = 'display:block;width:100%;height:700px;border:none;';
      el.innerHTML = '';
      el.appendChild(iframe);
      el.style.cursor = 'default';
    });
  });
})();
</script>


<p style="margin-top:1em;font-family:monospace;font-size:0.9em;">→ <a href="https://androman.pro/2026/04/28/1c-stalo-skuchno/">открыть на androman.pro</a></p>]]></content:encoded>
					
					<wfw:commentRss>https://androman.pro/2026/04/28/1c-stalo-skuchno/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Я это сделал!</title>
		<link>https://androman.pro/2026/04/27/ya-eto-sdelal/</link>
					<comments>https://androman.pro/2026/04/27/ya-eto-sdelal/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Mon, 27 Apr 2026 06:17:15 +0000</pubDate>
				<category><![CDATA[дев-лог]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[creative-code]]></category>
		<category><![CDATA[vibe-coding]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://androman.pro/?p=249</guid>

					<description><![CDATA[Дев-лог о перезапуске сайта на собственной WordPress-теме. 15 итераций дизайна, парадокс растущего бэклога, открытия про безопасность CMS.]]></description>
										<content:encoded><![CDATA[<p>Кайфую от веб-разработки — точнее, от вайб-кодинга в ней. Это прямо наслаждение, когда от задумки до результата проходит минимальное количество времени.</p>
<h2>1С vs веб через ИИ — два разных мира</h2>
<p>В 1С не так. Там огромный контекст, галлюцинации модели и загрязнённый контекст: контекст одного проекта просачивается в выводы по другому, имена путаются, факты выдумываются. Платформа сопротивляется.</p>
<p>В вебе — свобода. Сформулировал хотелку, пусть даже криво, и через минуту уже есть что потрогать. Не нужно неделю входить во фреймворк, читать документацию к новому инструменту и вспоминать, почему CSS опять делает вид что всё нормально. ИИ быстро накидывает варианты, а я уже выбираю, что похоже на меня.</p>
<h2>Цифры одного дизайна</h2>
<p>На эту тему ушло 5 итераций по 3 варианта в каждой. Итого <strong>15 разных тем</strong>, каждая собиралась на основе того, что понравилось в предыдущих. В итоге получилась не «идеальная тема», а тема, которую я наконец не хочу немедленно снести.</p>
<p>Главное что вышло:</p>
<ul>
<li><strong>Декодер-заголовок</strong> — <code>androman.pro</code> на главной печатается через шумовые символы <code>█▓▒░</code>, потом «защёлкивается» в текст и морфит между <code>androman.pro → .1С → .ai → .dev</code>. Glitch — короткий RGB-бурст 2.5 секунды.</li>
<li><strong>HUD-углы</strong> — <code>agent ONLINE</code>, <code>build v0.6.x</code>, <code>mode roaming</code>, <code>focus hyperfocus</code>. Левый верхний кликается — открывается changelog проекта (RU/EN, версии с alpha до текущей).</li>
<li><strong>Страница <code>/сейчас</code></strong> — кроме обычного описания фокуса, terminal-блок со 150 случайными dev-фразами в киберпанк-стиле. Клик — мгновенный реролл.</li>
<li><strong>Команд-палитра</strong> — нажми <code>/</code> (на любой раскладке клавиатуры — работает на ЙЦУКЕН тоже), всплывает терминал команд.</li>
<li><strong>Визуальная лаборатория</strong> — 7 моих open-source WebGL/Canvas-проектов собраны в одной странице. У одной из карточек — hover-preview живой 3D-сцены через lazy-load.</li>
</ul>
<p>Шрифты — все 74 woff2 self-hosted. Никаких Google Fonts CDN, сайт работает без внешних соединений.</p>
<h2>Парадокс роста</h2>
<p>Заметил парадокс: <strong>чем больше разрабатываешь с ИИ, тем сильнее растёт бэклог задач</strong>. Раньше идея «было бы круто» оставалась идеей. Сейчас — становится таском в течение часа. Скорость реализации опережает способность приоритизировать.</p>
<p>И ещё — перфекционизм. Если уходишь в него, тратишь неимоверно больше времени, чем если довольствуешься средним вариантом. Но это везде так, <strong>принцип Парето</strong> — 80% результата за 20% времени, остальные 20% — за всю оставшуюся жизнь.</p>
<h2>Workflow получился взрослый</h2>
<p>Заодно собрался нормальный workflow разработки сайта: <strong>тестовый и прод-контуры</strong>, возможность обкатать фичи до выхода в прод. Всё через git, версионирование, автодеплой по rsync через SSH. Бэкап БД и файлов — до любого изменения.</p>
<p>В общем — я доволен. Так и должен выглядеть собственный сайт. Хотя в наше время это уже похоже на ретроградство — социальные сети поглотили личные блоги. Но мне так нравится.</p>
<h2>Открытие про безопасность</h2>
<p>ИИ заодно проаудировал сайт и подсветил то, чего я не знал: <strong>пароли от БД у CMS традиционно хранятся в открытом виде</strong> в конфиге. Это касается всех — WordPress, Joomla, Drupal, Magento, любого PHP-стека. Защита идёт не криптографией, а правами файла + правильной настройкой веб-сервера.</p>
<p>Закрыли всё что обычно светится: XMLRPC отключён, REST <code>/users</code> скрыт от анонимов (admin slug больше не виден), <code>?author=N</code> редиректит на главную, <code>readme.html</code> и <code>license.txt</code> удалены, security-headers через PHP + <code>.htaccess</code>.</p>
<h2>Что дальше</h2>
<p>Сайт работает. Версия <code>0.6.x</code> — pre-release, до публикации <code>1.0</code> хочу наполнить блог постами и быть уверенным в каждой странице.</p>
<p>Ближайшие планы — <strong>перенесу статьи с инфостарта</strong>, плюс буду публиковать <strong>эксклюзивы</strong> здесь. Радар на сайте уже ждёт blip’ов.</p>


<p style="margin-top:1em;font-family:monospace;font-size:0.9em;">→ <a href="https://androman.pro/2026/04/27/ya-eto-sdelal/">открыть на androman.pro</a></p>]]></content:encoded>
					
					<wfw:commentRss>https://androman.pro/2026/04/27/ya-eto-sdelal/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
