Субботний скриншот
Реквестирую возрождение старой традиции
Каждую субботу делиться скринами того, что напрограммировали на неделе
Я вот фаерболы для своей игры сделал
Реквестирую возрождение старой традиции
Каждую субботу делиться скринами того, что напрограммировали на неделе
Я вот фаерболы для своей игры сделал
Люблю ли я зиму? НЕТ. Тем не менее признаю, что она бывает очень красивой. И даже временами вам это показываю.
Cегодняшнюю работу (вернее, серию) я закончила ещё неделю назад. Но у нас как раз стремительно теплело, всё потекло, и писать про зимние сюжеты настроения не было. А сегодня снова шарахнуло -20 с лишним, да ещё с таким потрясающе ледяным ветром... В общем, самое время пилить пост.
Эти наборы мне подарили на день рождения почти два года назад. И я очень их хотела, ведь миниатюры (а они действительно очень маленькие) совершенно прекрасные.
Вышиваются они легко и быстро. Даже если не торопиться, за неделю один «прикончить» вполне реально. И это с учётом полного цикла: постирать после крестиков, высушить, отутюжить, сделать бэк, натянуть на картонку.
Но я бы не была собой, если бы не растянула всё это удовольствие на два года. Я не умею вышивать что-то одно: часто отвлекаюсь, переключаюсь, а иногда и вовсе не вышиваю месяцами.
Об одно регулярно запиналась – не всегда замечала, что где-то нужно вышивать в одну нить, а не в две. Приходилось распускать и переделывать. Смирение и терпение – важная часть этого хобби.
Особая прелесть этих миниатюр в том, что буквально из нескольких крестиков и пары-тройки стежков бэкстича рождаются узнаваемые образы – лошади меня особенно покорили.
Вообще у этого производителя целый цикл таких наборов: зима, весна, лето, осень. Весенняя и летняя серии меня так не зацепили, поэтому покупать не стала.
А вот осенняя... Осенняя у меня есть. Но покажу её, если всё сложится удачно, только (не поверите) осенью. Она пока не готова :)
Перед вами планетарная туманность NGC 2440, находящаяся в созвездии Корма на расстоянии около 4 000 световых лет от Земли.
Это не просто газопылевое облако в космосе, а то, что осталось от звезды, которая когда-то была похожа на Солнце: на исходе жизни она сбросила внешние слои, обнажив свое раскаленное ядро, которое начало "дожигать" окружающий материал своим мощным излучением.
Обнаженное ядро, расположенное в центре туманности, представляет собой белый карлик — самый горячий из известных с температурой поверхности около 200 000 градусов Цельсия. Для сравнения: температура поверхности Солнца около 5 500 градусов.
Этот раскаленный остаток, чья светимость в 1 100 раз превосходит солнечную, и делает туманность видимой: ультрафиолетовое излучение ионизирует выброшенный газ, из-за чего он начинает светиться.
Форма NGC 2440 не похожа на аккуратный "пузырь". Туманность сложная, асимметричная, местами словно "рваная", встречаются узлы и неравномерные струи. Связано это с тем, что звезда сбросила свои оболочки не за один заход: выбросы происходили импульсами и каждый раз в разных направлениях — поэтому туманность выглядит хаотично.
Исследование таких объектов имеет огромную ценность для прогнозирования будущего Солнечной системы. Дело в том, что мы не можем проследить эволюцию одной и той же звезды от ее рождения до гибели — жизненный цикл занимает миллиарды лет. Но солнцеподобные звезды во Вселенной представлены на разных этапах жизни: где-то они только начали "разгораться", где-то пребывают в стабильном состоянии, где-то уже раздуваются в красные гиганты, а где-то, как здесь, завершили свой эволюционный путь и оставили после себя планетарную туманность с белым карликом.
И вот, объединяя такие "кадры", полученные из разных уголков Млечного Пути, мы фактически воссоздаем хронологию событий и понимаем, какое будущее ждет наше Солнце. Пока оно находится на главной последовательности, каждый миллиард лет его светимость будет увеличиваться примерно на 10%. Уже при таком росте Земля со временем станет непригодной для жизни*, хотя простейшие организмы, скрывающиеся глубоко под поверхностью, будут продолжать существовать еще несколько миллиардов лет.
*Эволюция Солнца приведет к сильному повышению температуры на Земле, испарению всех водоемов, включая Мировой океан, и последующему росту температуры из-за усиления парникового эффекта. Земля станет подобием Венеры.
Затем, когда запасы водорода в светиле начнут заканчиваться, ядро сожмется и разогреется еще сильнее, а внешние слои звезды начнут раздуваться — Солнце перейдет в фазу красного гиганта примерно через 5–6 миллиардов лет. Это приведет к поглощению Меркурия и Венеры, хотя Земля в физическом плане может уцелеть. Затем Солнце сбросит оставшиеся оболочки, а излучение со стороны ядра ионизирует выброшенный газ, заставив его ярко светиться. Примерно через 10–50 тысяч лет окружающее облако газа станет слишком разреженным и перестанет быть видимым. И тогда на месте Солнца останется лишь медленно остывающий белый карлик.
Представьте себе самые злачные трущобы Гарлема. Добавьте туда толкучку в метро в час пик.
Представили?
Теперь представьте смесь ароматов деревенского сортира, химического завода и выхлопной трубы «КамАЗа».
И напоследок оберните всё это в упаковку низкопробного киберпанка — настолько гротескного и невразумительного, что читатель невольно кривится: да ну, так не бывает.
Если смешать все эти образы воедино, получится Гонконг.
Поездка в Гонконг — это не путешествие ради удовольствия. Это шоковая терапия ценой в 300 баксов за ночь в «лакшери квин отеле», где номер размером с гардеробную, а вместо постельного белья на старую шконку вам любезно набросят нетканый материал.
Наше путешествие по Гонконгу проходило под лозунгом «Сраные малины». Потому что здесь всё:
а) засрано,
б) пестрит малиновым безумием.
Неоновые вывески лезут со всех сторон, светятся так агрессивно, будто пытаются стереть вам память.
Это не «Бегущий по лезвию» и даже не «Киберпанк 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 м² — и заплачете от благодарности.
Пройдёте по улице, не задевая локтями десяток незнакомцев каждые три шага — и поймёте: это и есть свобода.
Увидев, во что вырождается общество потребления, возведённое в абсолют, вы невольно почувствуете отвращение к капиталистическим идеалам.
Гонконг — не место для жизни. Это кривое зеркало, которое показывает, куда ведёт путь необузданного потребительства, где пространство и сам человек превращаются в товар.
И именно поэтому сюда стоит приехать.
Да уж, спасение утопающих – дело рук самих утопающих... *ворчит по-кошочьи* Ладно, давайте продолжим цепочку, в которую меня внезапно втянула @Rian. Она выглядит (если я правильно поняла) следующим образом: @Linda_M, @zmmx, @Kukabara, @talk.about, @capybarystic, @Rian.
Так уж сложилось, что я приехала в гости к родителям и они заставили попросили приготовить блины. Не на своей плите и не на своей свободе было тяжеловато :)
Последний блин получился смешным носатым мужиком.
Конечно, блины нужно есть с чем-нибудь вкусным. Хоть @Rian от меня ждёт интересных сочетаний, но я покажу банальщину...
Блин первый: творожный сыр и «икра».
Второй блин чуть хитрее: мягкий творог, груша, банан, кедровые орешки, шоколад.
Родителям блины понравились (мне тоже), пост написан – миссия выполнена.
Передаю эстафету @SergPrg.
Вчера снова было затишье:
И ну я:
А теперь давайте посмотрим, что изменилось.
В первую очередь, конечно же, изменился метод 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;
}
Пока складывается впечатление, что начинаю наворачивать мрак и ужас. Поэтому со следующего выпуска начну помимо введения новых фишек смотреть, что можно упростить и улучшить по архитектуре и коду. Как я уже в этот раз сделал с системой ввода.
зразы вроде тоже что-то такое
Удобно. И ждать никого не надо
Какая красота!
И картина тоже классная!