Изображение, полученное телескопом «Хаббл», показывает так называемую Космическую Змею — далёкую галактику с ярко выраженными узлами интенсивного звездообразования. Её изображение искажено эффектом гравитационного линзирования.
На самом деле эта галактика находится за массивным скоплением галактик MACSJ1206.2-0847, но благодаря сильному гравитационному полю скопления её свет искривляется и достигает Земли, образуя гигантскую дугу.
Свет от этой далёкой галактики с высоким красным смещением проходит мимо скопления, и его траектория искривляется под действием гравитации. Вместо того чтобы затруднять наблюдения, такое сильное линзирование увеличивает удалённый объект, улучшая разрешение и глубину изображения. В некоторых случаях оно даже создаёт несколько изображений одного и того же объекта, поскольку свет огибает скопление по разным траекториям.
Меня позвала @capybarystic Продолжим предаваться блинным воспоминаниям.
Стараюсь каждую масленицу напечь побольше блинов(больших, тонких, на дрожжах) и наделать кучу начинок(капуста, фарш, рыба, творог, икра, варенья, мед...). Всю неделю питаемся блинами. В другое время года практически не пеку их, если только внезапно захочется.
С юности умела печь тонкие блины. Другие не так интересны, а в тонкие можно завернуть все, что хочешь! Но для этого нужна простая советская раскаленная сковородка (а лучше 2-3 для скорости). И вот, переехав лет 12 назад на новую квартиру, я столкнулась с проблемой: индукционная плита прекрасна, но она не любит тонких блинов :( - раскаленная сковорода, это " алярм, алярм, я выключаюсь ой все!". И стою я с почти двумя литрами теста и пищащей плитой. Выкрутилась я тогда с помощью духовки. Если вы любите толстые, очень толстые блины - то духовка и силиконовые формы - ваш выбор. Были у меня тогда "блины" в форме котят, зайцев и медведей.
А потом попросила на др электроблинницу и по старой традиции задвоения подарков мне их две подарили! И это прекрасно. Да, блины не такие ажурные/зажаристые, зато большие и почти ровные. Почувствуй себя поваром в "Теремке"! Особенно когда рядом скачет ребенок: "мне Фермерский, мне Фермерский".
Нашла на нижней полке, вымыла как могла от пылищи, и в честь среды принесла вам. Жабку подарили когда-то давно и не из-за жабки, а из-за котика, потому что дело было на выставке кошек )
Изначально я хотел добавить поддержку геймпада только на финальном этапе разработки, но получилось так, что это делается достаточно просто, поэтому засунул сразу.
Пойдём по порядку
function handleKeyDown(e) {
keys[e.code] = true; // аккумулируем все нажатия, чтоб потом обработать
// Предотвращаем прокрутку страницы стрелками и пробелом
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Space'].includes(e.code)) {
e.preventDefault();
}
}
function handleKeyUp(e) {
keys[e.code] = false; // "забываем" отпущенную кнопку
}
function handleGamepadConnected(e) {
console.log(`Gamepad connected: ${e.gamepad.id}`);
gamepadIndex = e.gamepad.index;
}
function handleGamepadDisconnected(e) {
console.log(`Gamepad disconnected: ${e.gamepad.id}`);
if (gamepadIndex === e.gamepad.index) {
gamepadIndex = null;
}
}
В отличии от клавиатуры, которая отдаёт браузеру события о нажатии на кнопка, с геймпадом такой финт ушами не прокатывает и надо опрашивать его состояние самостоятельно (прям как на привычных движках в старые добрые времена).
Дальше заспавним наш "танк" на игровой сцене
const spawnX = 4 * CELL_SIZE; // 4 клетки от левого края = 64 px
const spawnY = 24 * 8 - 32; // Чуть выше базы = 160 px
player = new Tank(spawnX, spawnY, TANK_PLAYER);
Класс танка достаточно большой, он ко конструкторе принимает значения координат спавна и типа танка (танк игрока или тип врага). Ему устанавливается "здоровье" (сколько раз в него надо попасть, чтобы убить), сколько активных патронов есть и т.д.
constructor(x, y, type = TANK_PLAYER) {
this.x = x;
this.y = y;
// Направление (0=вверх, 1=вправо, 2=вниз, 3=влево)
this.direction = DIR_UP;
this.speed = TANK_SPEED_NORMAL; // в пекселях за кадр
// Тип танка
this.type = type;
this.health = 1;
this.destroyed = false;
// Флаг движения в текущем кадре
this.moving = false; // Пока только задаётся, но нигде не используется. Есть мысли на будущее, но если не понадобится, удалю
// Апгрейды (для игрока)
this.bulletLevel = 0; // 0=обычная, 1=быстрая, 2=усиленная
this.bulletCount = 1; // Макс. пуль на экране
this.hasShield = false; // Временная защита
this.hasBoat = false; // Движение по воде
// Активные пули (для подсчёта лимита)
this.activeBullets = 0;
}
Непосредственно движение выгляди таким образом:
move(direction) {
// Сначала поворачиваем, если нужно
if (this.direction !== direction) {
this.turn(direction);
return; // В оригинале, если повернуть, танк не двигается в этом кадре, может уберу, если плейтесты покажут необходимость
}
// Вычисляем смещение по направлению
let dx = 0;
let dy = 0;
switch (direction) {
case DIR_UP: dy = -this.speed; break;
case DIR_DOWN: dy = this.speed; break;
case DIR_LEFT: dx = -this.speed; break;
case DIR_RIGHT: dx = this.speed; break;
}
// Новая позиция
let newX = this.x + dx;
let newY = this.y + dy;
// Ограничение границами игрового поля
newX = Math.max(0, Math.min(newX, LOGICAL_FIELD_SIZE - TANK_SIZE));
newY = Math.max(0, Math.min(newY, LOGICAL_FIELD_SIZE - TANK_SIZE));
// TODO: Проверка коллизий с тайлами (Этап 4)
// TODO: Проверка коллизий с другими танками (Этап 7)
// Применяем новую позицию
this.x = newX;
this.y = newY;
this.moving = true;
}
Ну и рисование танка на игровом поле
render() {
if (this.destroyed) return;
const ctx = foregroundCtx;
// Конвертация логических координат в физические
const px = GAME_FIELD_X + this.x * GAME_SCALE;
const py = GAME_FIELD_Y + this.y * GAME_SCALE;
const size = TANK_SIZE * GAME_SCALE;
// Цвет танка в зависимости от типа, пока всего два, потом будут новые типы и новые цвета
// Основной квадрат танка
ctx.fillStyle = this.type === TANK_PLAYER ? COLOR_TANK_PLAYER : COLOR_TANK_ENEMY;
ctx.fillRect(px, py, size, size);
// Индикатор направления (треугольник)
this.renderDirectionIndicator(ctx, px, py, size); // понял, что просто квадрато недостаточно, поэтому добавил "морду"
}
Рендер танка вызывается в методе основного рендера после очистки всего динамического слоя
// Foreground canvas — очищаем и рисуем сущности каждый кадр
clearForeground();
// Рендер танка игрока
if (player) {
player.render();
}
// TODO: Здесь будет рендер врагов, пуль, эффектов
Результат всего этого безобразия
Танк ездит сквозь стены, потому что "физического" движка ещё нет. Проверка коллизий как раз на очереди.
Масленица она же не только про блины, но и про солнышко.
Это солнышко уже погасло, но оставило после себя столько тёплых воспоминаний!
Это Сосиска. В принципе я пекла блины только ради неё. Сама я их не настолько люблю, мужа вполне устроят покупные замороженные, а Сосисочка очень любила, когда я пеку блины. Ещё на стадии замеса теста приходила и начинала ждать. А потом, дождавшись первого, начинала спрашивать - мяу?
На самом деле у нас остальные кошки даже не знают, что можно что-то со стола спросить, потому что они громогласные и наглые, один раз дай - и на шею сядут.
А Сосисочка была деликатная кисонька, спрашивала тихо и скромно. И кто я, чтобы ей отказать? Главное чтобы остальные это не видели.
В те времена печь блины было особо некогда, но каждую масленицу я стралась сделать это хотя бы один раз для этого солнышка 💖
Тонкорукая чесночница из семейства рогатых чесночниц похожа на мурлока. На рогатую чесночницу она не очень похожа.
Leptobrachium hendricksoni
Эта малышка выделяется своими яркими глазами и тонкими лапками без перепонок и присосок. Коричневый окрас с пятнами способствует маскировке.
Вид распространён в Таиланде, Индонезии и Малайзии. Предпочитают они заболоченные леса и ведут наземный образ жизни. Едят всяких насекомых и червячков.
Приуныла
Тут особо много текста не будет, мне просто нравится, как она выглядит :)
Банан и творог надо попробовать) а вот с картошкой не получился фокус
Захотелось кушоц...