#[моё]

Это Гонконг, детка!

39
Читалка

Представьте себе самые злачные трущобы Гарлема. Добавьте туда толкучку в метро в час пик.

Представили?

Теперь представьте смесь ароматов деревенского сортира, химического завода и выхлопной трубы «КамАЗа».

И напоследок оберните всё это в упаковку низкопробного киберпанка — настолько гротескного и невразумительного, что читатель невольно кривится: да ну, так не бывает.

Если смешать все эти образы воедино, получится Гонконг.

Поездка в Гонконг — это не путешествие ради удовольствия. Это шоковая терапия ценой в 300 баксов за ночь в «лакшери квин отеле», где номер размером с гардеробную, а вместо постельного белья на старую шконку вам любезно набросят нетканый материал.

Вот так выглядят стены в лакшери отеле с рейтингом 4,8/5. Страшно представить отели с рейтингом 3...
Вот так выглядят стены в лакшери отеле с рейтингом 4,8/5. Страшно представить отели с рейтингом 3...
А это вид из окон на "тихий внутренний дворик в суете большого города". И ведь не обманули, гады
А это вид из окон на "тихий внутренний дворик в суете большого города". И ведь не обманули, гады
Постельное белье из укрывного материала, такое у нас стелят в кабинетах УЗИ. А тут на таком спят. И такие же полотенца в ванной.
Постельное белье из укрывного материала, такое у нас стелят в кабинетах УЗИ. А тут на таком спят. И такие же полотенца в ванной.

Наше путешествие по Гонконгу проходило под лозунгом «Сраные малины». Потому что здесь всё:

а) засрано,

б) пестрит малиновым безумием.

Неоновые вывески лезут со всех сторон, светятся так агрессивно, будто пытаются стереть вам память.

Это не «Бегущий по лезвию» и даже не «Киберпанк 2077». Это галлюцинации умирающего разума после инсульта: обрывистые, скомканные, яркие, грязные, перегруженные — без единого пикселя свободного пространства.

Благо мозг быстро отказывается обрабатывать этот визуальный спам и приходит к простому выводу: вы в аду.

---

А мы поселились в самом эпицентре этого ада.

По данным Книги рекордов Гиннеса, Монг Кок — официально самый густонаселённый район планеты. По сути это человеческий пресс: на одного проживающего приходится всего 2,2 м² (данные Жилищного фонда Гонконга). В средней квартире площадью 22 м² живут пять человек.

Это меньше, чем гараж в провинциальном городе. И дороже трёшки на Арбате.

В Гонконге большинство живёт в «кокхаусах» — бывших общежитиях, где комната по размеру равна кровати. Вы слышите, как сосед чавкает рисом. Слышите, как плачет его ребёнок. Слышите, как он срёт в туалет, расположенный в считанных сантиметрах от вашей подушки.

Это не бедность в романтическом понимании. Это системная давилка, где человеческое тело превращено в товар, а пространство для дыхания — в роскошь.

Семьи здесь — редкость. Около 30% населения живут в одиночестве, а средний возраст вступления в первый брак перевалил за 30. кто-то мечтает о детях — но где их растить? в одной комнате на пятерых?

Дети в Гонконге — самые загруженные в мире. Среднестатистический ребенок в Гонконге начиная с 6 лет учится по 16 часов в день: Школа, репетиторы, музыка, танцы, программирование, английский, китайский, французский... Родители этим гордятся: «Мой ребёнок спит всего пять часов» — это не жалоба, а достижение. Это гонка, в которой побеждает тот, кто раньше сломается.

И многие ломаются.

Уровень суицидов в Гонконге — один из самых высоких среди развитых стран. Особенно среди молодёжи. Когда твоё будущее — это 60-часовая рабочая неделя, ипотека на 50 лет и жизнь в клетке размером со шкаф, самоубийство начинает казаться рациональным выбором.


В отсутствие других простых радостей — нормальной квартиры, личного пространства, возможности просто побыть одному — люди гонятся за атрибутами гламурной жизни: самые дорогие часы, побольше золота и бриллиантов, больше подписчиков в тиктоке.

Это гиперкомпенсация. Когда у тебя ничего нет, ты покупаешь символы того, что у тебя есть всё.

Показательно, что официальный аудиогид по Гонконгу (встроенный в каждый автобус — подключай наушники и слушай) рассказывает не об истории города, не о мифах и легендах Китая. Вместо этого вы слышите:

— «В этом небоскрёбе расположен самый крупный в мире магазин Apple/Prada/Guchi».

— «В этом торговом центре арабскому шейху продали самую дорогую машину в мире».

— «В этом отеле останавливался Элтон Джон».

— «На этом стадионе выступала Бейонсе».

Складывается впечатление, что острову с двухтысячелетней историей (с момента основания первого поселения) нечем гордиться, кроме брендов и залетных знаменитостей.

Впечатления мужа от автобусного тура)
Впечатления мужа от автобусного тура)

И вот апогей капиталистического безумия: чтобы жить в таких условиях, люди платят по 30 000$ за квадратный метр. Или отдают 4000–5000 $ в месяц за аренду «шкафа с розеткой».

Хотя многие и не платят вовсе: ночью на тротуарах и в переходах ложатся бездомные. Прямо на бетон. Под малиновыми неоновыми иероглифами.


Почему Гонконг так контрастирует с остальным Китаем?

Гонконг — особый административный район, бывшая британская колония с середины XIX века до начала XXI. Лишь 29 лет назад территория перешла от Великобритании к КНР.

Вкорячить этого уродца в стройную китайскую систему с полоборота было невозможно. Тогда Дэн Сяопин, руководивший КНР на рубеже веков, предложил принцип «одна страна, две системы». Гонконгу дали 50 лет на постепенную интеграцию в правовое и социальное пространство материкового Китая (государства, формально социалистического и потому социального по идеологии). До 2047 года Гонконг де-юре и де-факто сохраняет автономию: свой суд, своё правительство, свои законы, свой образ жизни — плюс финансовые преференции и вливания из Пекина для интеграции.

На деле это превратилось в театр абсурда: на инвестиции строятся всё новые небоскрёбы с бесконечными банками, бутиками и институтами Тиктока. А социальное пространство для обычной жизни продолжает скукоживаться.

У Гонконга ещё есть 21 год «полной свободы» на дальнейший разгул идеологии потребления. Что будет дальше — неизвестно.

В отличие от жителей Тайваня, гонконгцы не ставят себя в антагонизм по отношению к материковому Китаю. Они ждут полного объединения со смесью надежды и тревоги.


Мы провели в Гонконге три доооолгих и тяжёлых дня.

Три дня постоянной давки, бесконечных очередей и рекламы элитных брендов на фоне грязи и мусора.

Мой муж, который терпеть не может обсценную лексику, ругался здесь больше, чем за всю нашу совместную жизнь.

Его главный вопрос был: «Нахуя????»

Для меня ответ очевиден:

Потому что контраст лечит.

Проведите пару дней в Гонконге — и вы никогда больше не будете ныть, что у вас маленькая квартира, дорогая аренда или кто-то не уважает ваше личное пространство.

Вы начнёте ценить то, что раньше считали должным: тишину, размеренность, уют.

Вы вернётесь домой, откроете окно в комнату больше 2,2 м² — и заплачете от благодарности.

Пройдёте по улице, не задевая локтями десяток незнакомцев каждые три шага — и поймёте: это и есть свобода.

Увидев, во что вырождается общество потребления, возведённое в абсолют, вы невольно почувствуете отвращение к капиталистическим идеалам.

Гонконг — не место для жизни. Это кривое зеркало, которое показывает, куда ведёт путь необузданного потребительства, где пространство и сам человек превращаются в товар.

И именно поэтому сюда стоит приехать.

Продолжаем спасать лису

42

Да уж, спасение утопающих – дело рук самих утопающих... *ворчит по-кошочьи* Ладно, давайте продолжим цепочку, в которую меня внезапно втянула @Rian. Она выглядит (если я правильно поняла) следующим образом: @Linda_M, @zmmx, @Kukabara, @talk.about, @capybarystic, @Rian.


Так уж сложилось, что я приехала в гости к родителям и они заставили попросили приготовить блины. Не на своей плите и не на своей свободе было тяжеловато :)

Рецепт блинов
Яйца – 3 шт.
Молоко – 400 мл.
Вода (кипяток) – 200 мл.
Мука – 180 г.
Соль – 0.5 ч.л.
Сахар – 3 ст.л.
Подс. масло – 2 ст.л.
---------------------------------------
Смешать яйца с солью и сахаром, добавить часть молока. Всыпать муку, хорошо перемешать (будет густо, но так можно избежать образования комочков). Долить молоко и снова перемешать. Теперь тонко влить кипяток, постоянно помешивая. Добавить масло и оставить на полчасика, потом жарить.
хоп
хоп
хоп
хоп

Последний блин получился смешным носатым мужиком.

Конечно, блины нужно есть с чем-нибудь вкусным. Хоть @Rian от меня ждёт интересных сочетаний, но я покажу банальщину...

Блин первый: творожный сыр и «икра».

Второй блин чуть хитрее: мягкий творог, груша, банан, кедровые орешки, шоколад.

Родителям блины понравились (мне тоже), пост написан – миссия выполнена.


Передаю эстафету @SergPrg.

«Танчики» на html5

Реакция на попадание снаряда

38
Читалка
Внезапно сразу результат

А теперь давайте посмотрим, что изменилось.

В первую очередь, конечно же, изменился метод checkTileCollision внутри класс патрона.

checkTileCollision(newX, newY, gameMap) {
        const tiles = getTilesUnderEntity(newX, newY, BULLET_SIZE, BULLET_SIZE);

        if (tiles.length === 0) return false;

        // Находим тайлы на передней кромке по направлению движения
        let frontTiles;
        switch (this.direction) {
            case Direction.UP:
                // Минимальный Y = передняя кромка
                const minY = Math.min(...tiles.map(t => t.ty));
                frontTiles = tiles.filter(t => t.ty === minY);
                break;
            case Direction.DOWN:
                // Максимальный Y = передняя кромка
                const maxY = Math.max(...tiles.map(t => t.ty));
                frontTiles = tiles.filter(t => t.ty === maxY);
                break;
            case Direction.LEFT:
                // Минимальный X = передняя кромка
                const minX = Math.min(...tiles.map(t => t.tx));
                frontTiles = tiles.filter(t => t.tx === minX);
                break;
            case Direction.RIGHT:
                // Максимальный X = передняя кромка
                const maxX = Math.max(...tiles.map(t => t.tx));
                frontTiles = tiles.filter(t => t.tx === maxX);
                break;
            default:
                frontTiles = tiles;
        }

        let hasCollision = false;

        // Проверяем только тайлы на передней кромке
        for (const {tx, ty} of frontTiles) {
            const tileId = gameMap.getTile(tx, ty);
            const tileDef = TILE_DEFS[tileId];

            if (!tileDef) continue;

            // Пуля блокируется этим тайлом?
            if (tileDef.blocksBullet) {
                hasCollision = true;

                // Пытаемся разрушить тайл
                gameMap.damageTile(tx, ty, this.direction, this.power);
            }
        }

        if (hasCollision) {
            this.destroy();
            return true;
        }

        return false;
    }

Изменился внутренний мир объекта, отвечающего за направления

DamageState = Object.freeze({
//было
    FULL: 0b11,
    HALF_LEFT: 0b10,
    HALF_RIGHT: 0b01,
    DESTROYED: 0b00
//стало
    FULL: 0,
    HALF_LEFT: 1,   // Осталась левая половина (вертикальный срез)
    HALF_RIGHT: 2,  // Осталась правая половина (вертикальный срез)
    HALF_TOP: 3,    // Осталась верхняя половина (горизонтальный срез)
    HALF_BOTTOM: 4, // Осталась нижняя половина (горизонтальный срез)
    DESTROYED: 5
});

Эта побитовая маска оказалась весьма нестабильной историей на тестах.

Ну и как говорил в прошлом выпуске, мне не нравилось, как у меня был сделан инпут, поэтому я его переделал. Он больше не принимает на вход карту и коллекцию патронов, а делает только то, что должен: отслеживает инпут. Логика обработки вынесена уже в main.js

export function getPlayerActions() {
    const actions = {
        movement: null,  // Direction.UP/DOWN/LEFT/RIGHT или null
        shoot: false
    };

    // Собираем ввод с клавиатуры
    collectKeyboardActions(actions);

    // Собираем ввод с геймпада
    collectGamepadActions(actions);

    return actions;
}
function update(dt) {
  // 1. Получаем действия игрока из input
  const actions = getPlayerActions();

  // 2. Применяем действия к игроку
  if (player && !player.destroyed) {
    // Движение
    if (actions.movement !== null) {
      player.move(actions.movement);
    }

    // Стрельба
    if (actions.shoot && player.canShoot()) {
      const bullet = player.shoot();
      if (bullet) {
        bullets.push(bullet);
      }
    }

    player.update(dt);
  }

  // 3. Обновление пуль
  for (const bullet of bullets) {
    bullet.update(gameMap);
  }

  // 4. Удаление неактивных пуль
  bullets = bullets.filter(b => b.active);

  // 5. Подсчёт FPS для отладки
  frameCount++;
  fpsTimer += dt;

  if (fpsTimer >= 1000) {
    fps = frameCount;
    frameCount = 0;
    fpsTimer = 0;

    // Обновляем FPS на странице
    const fpsElement = document.getElementById('fps');
    if (fpsElement) {
      fpsElement.textContent = fps;
    }
  }
}

Внутри карты поменялось получение и редактирование карты урона

getDamage(x, y) {
    const key = `${x},${y}`;
    // Если нет в маске — значит либо FULL, либо не разрушаемый
    if (!this.damageMask.has(key)) {
      return DamageState.FULL;
    }
    return this.damageMask.get(key);
  }
setDamage(x, y, state) {
    const key = `${x},${y}`;
    if (state === DamageState.DESTROYED) {
      this.damageMask.delete(key);
      this.tileGrid[y][x] = TileType.EMPTY;
    } else if (state === DamageState.FULL) {
      // FULL — удаляем из маски (дефолтное состояние)
      this.damageMask.delete(key);
    } else {
      this.damageMask.set(key, state);
    }
    this.dirty = true;
  }

И появился большой новый метод, который и занимается непосредственно разрушением:

damageTile(x, y, direction, power) {
    if (x < 0 || x >= GRID_SIZE || y < 0 || y >= GRID_SIZE) return false;

    const tileId = this.getTile(x, y);
    const tileDef = TILE_DEFS[tileId];

    if (!tileDef) return false;

    // Проверяем можно ли разрушить этот тайл
    if (!canBulletDestroy(tileDef, power)) {
      return false;
    }

    // Получаем текущее состояние повреждения
    const currentDamage = this.getDamage(x, y);

    // Если уже разрушен — ничего не делаем
    if (currentDamage === DamageState.DESTROYED) {
      return false;
    }

    // Определяем новое состояние в зависимости от направления пули
    let newDamage;

    if (currentDamage === DamageState.FULL) {
      // Первое попадание — создаём половину
      // Пуля убирает ту часть, в которую летит
      switch (direction) {
        case Direction.UP:
          // Пуля летит вверх → убирает нижнюю часть → остаётся верхняя
          newDamage = DamageState.HALF_TOP;
          break;
        case Direction.DOWN:
          // Пуля летит вниз → убирает верхнюю часть → остаётся нижняя
          newDamage = DamageState.HALF_BOTTOM;
          break;
        case Direction.LEFT:
          // Пуля летит влево → убирает правую часть → остаётся левая
          newDamage = DamageState.HALF_LEFT;
          break;
        case Direction.RIGHT:
          // Пуля летит вправо → убирает левую часть → остаётся правая
          newDamage = DamageState.HALF_RIGHT;
          break;
      }
    } else {
      // Второе попадание — полное разрушение
      newDamage = DamageState.DESTROYED;
    }

    // Обновляем состояние
    this.setDamage(x, y, newDamage);

    return true;
  }

Пока складывается впечатление, что начинаю наворачивать мрак и ужас. Поэтому со следующего выпуска начну помимо введения новых фишек смотреть, что можно упростить и улучшить по архитектуре и коду. Как я уже в этот раз сделал с системой ввода.


Всем хороших игр!

ЗОЖные блинчики

36

Ответ на пост Блиновое: продолжаем цепочку @kimpokom, приглашаю в нашу цепочку @Nataalika

Не идёт у меня в этот раз с блинами, но я старалась) Сегодня вместо подробного фотоотчёта будет краткий:

Берём 500 мл кефира, подогреваем в микроволновке
Берём 500 мл кефира, подогреваем в микроволновке

Добавляем 2 ст. ложки сахара, щепотку соли, 1 ч.л. соды, перемешиваем.

Добавляем два яйца
Добавляем два яйца

В этот момент я поняла, что мука у меня кончилась ещё на прошлых блинах, осталась только цельнозерновая!!!

Добавляем 260-270 грамм муки
Добавляем 260-270 грамм муки
Кипятим 200 мл молока и вливаем тонкой струйкой в тесто
Кипятим 200 мл молока и вливаем тонкой струйкой в тесто

В конце добавляем 4 ст.л. подсолнечного масла и идём жарить блинчики

Блинчики получаются симпатичные
Блинчики получаются симпатичные

На третьем блинчике я увидела, что в муке завелись жучки... фууу! Пришлось всё выбросить. Но так как первый блинчик я уже успела съесть, могу сказать, что рецепт неплох, но цельнозерновая мука тяжеловата для блинчиков. Оставим её зожникам, в следующий раз всё-таки с обычной мукой попробую =)

200226•10615

ДНЕВНИК АЛЬПАКИ

36
Оранжевый — значит, что близко к красному, то есть плохому, но до редфлага не хватает нервного срыва.
Оранжевый — значит, что близко к красному, то есть плохому, но до редфлага не хватает нервного срыва.

Сегодня почувствовал в своём сознании блок, что больше искать нейропушистиков уже нельзя: нет ни сил, ни мотивации, ни стимула...

...особенно когда кидают в чс с нихуя. 8 лет публиковал анкеты... и понял, что это неэффективная хуйня, а лапками-копытами вручную копаться нужен ресурс, где на сообщения могут тоже не ответить... и вот он ушёл.
...особенно когда кидают в чс с нихуя. 8 лет публиковал анкеты... и понял, что это неэффективная хуйня, а лапками-копытами вручную копаться нужен ресурс, где на сообщения могут тоже не ответить... и вот он ушёл.

Кстати, сегодня кнопка на ноуте тоже чуть не сдалась...

...кое-как, но получилось ей указать своё место.

Фотофокс, неделя 22. Большой

37

Ответ на пост Фотофокс, неделя 22

Достаточно большой?
Достаточно большой?
Внутрь не заходили, но за забором там тоже много интересного
Внутрь не заходили, но за забором там тоже много интересного