#[Сокровищница]

Сова

44

Было давно @Pepels сказал надо запилить сову!

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

Возьмем образец
Возьмем образец
Сделаем 3д рисунок в Gemini
Сделаем 3д рисунок в Gemini
В китайской нейронке получаем модель
В китайской нейронке получаем модель
Страшное
Страшное

Цели сделать сразу хорошо не стояло, поэтому отправил я её на печать добавив подставку. Чего и следовало ожидать, зубы и ноги частично отлетели, страшные края у крыльев и всё вот это вот. Нужно ноги с подставкой сделать отдельно, увеличить размер модельки и можно приводить в красивый вид. Но это потом, когда я с Блендером разберусь немного.

Кому надо моделька тут. Архив 30.1 Мб, сама модель 75,5 Мб. У нее овермного вершин, но упрощается это легко.

NGC 1068

36

Композитное изображение — комбинация данных нескольких телескопов. Данные в видимом диапазоне — от телескопа «Хаббл», а инфракрасные данные — от телескопа «Джеймс Уэбб» (жёлтые, серые и золотистые тона). Плюс данные в рентгеновском диапазоне — от телескопа «Чандра» (синий цвет) и радиоволны — от телескопа VLA (розовый).

В центре галактики мы видим мощные ветры от её ядра, в котором скрыта сверхмассивная чёрная дыра.
В центре галактики мы видим мощные ветры от её ядра, в котором скрыта сверхмассивная чёрная дыра.

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

Примитивный ИИ врагов

41
Читалка

Всем причастных с праздником!

Я тут вспомнил, что в прошлом посте забыл добавить планы на будущее. Планами было: добавить врагов.

Соответственно: точки спавна, их перемещение по карте, стрельба.

Давайте посмотрим на результат.

Появился новый класс, отвечающий за поведение врагов

export class EnemyAI {
    constructor(tank) {
        this.tank = tank;

        // Таймер смены направления
        this.changeDirectionTimer = 0;
        this.changeDirectionInterval = 60; // ~2 сек при 30 FPS

        // Cooldown стрельбы
        this.shootCooldown = 0;
        this.shootInterval = 30; // ~1 сек при 30 FPS

        // Флаг застревания (для смены направления при коллизии)
        this.wasBlocked = false;
    }

    randomDirection() {
        const directions = [Direction.UP, Direction.RIGHT, Direction.DOWN, Direction.LEFT];
        return directions[Math.floor(Math.random() * 4)];
    }

    update(allTanks, gameMap, bullets) {
        const tank = this.tank;

        if (tank.destroyed) return;

        // === 1. Логика смены направления ===
        this.changeDirectionTimer++;

        // Смена направления по таймеру
        if (this.changeDirectionTimer >= this.changeDirectionInterval) {
            tank.direction = this.randomDirection();
            this.changeDirectionTimer = 0;
            // Рандомизируем интервал (40-80 кадров)
            this.changeDirectionInterval = 40 + Math.floor(Math.random() * 40);
        }

        // === 2. Попытка движения ===
        const prevX = tank.x;
        const prevY = tank.y;

        tank.move(tank.direction);

        // Проверка: застрял ли танк (не сдвинулся)
        const stuck = (tank.x === prevX && tank.y === prevY && !tank.moving);

        if (stuck && !this.wasBlocked) {
            // Танк только что застрял — меняем направление
            tank.direction = this.randomDirection();
            this.wasBlocked = true;
            this.changeDirectionTimer = 0;
        } else if (!stuck) {
            this.wasBlocked = false;
        }

        // === 3. Автоматическая стрельба ===
        this.shootCooldown--;

        if (this.shootCooldown <= 0 && tank.canShoot()) {
            const bullet = tank.shoot();
            if (bullet) {
                bullets.push(bullet);
                // Рандомизируем cooldown (20-50 кадров)
                this.shootCooldown = 20 + Math.floor(Math.random() * 30);
            }
        }
    }
}

Он простой как три рубля, так что, думаю, можно обойтись без объяснений (тем более что комментариев в коде и так предостаточно).

К файле main появились коллекции врагов и их "мозгов"

/** @type {Array<Tank>} */
let enemies = [];

/** @type {Array<EnemyAI>} */
let enemyAIs = [];

Спавн врагов при старте игры

spawnEnemy(0, 0);           // Левый угол
spawnEnemy(12 * 8, 0);      // Центр (96px)
spawnEnemy(24 * 8 - 16, 0); // Правый угол (176px, учитываем размер танка)
// Пока спавню сразу все три, а не по очереди, как в оригинале
function spawnEnemy(x, y) {
    const enemy = new Tank(x, y, TankType.ENEMY_BASIC);
    enemy.direction = Direction.DOWN; // Враги всегда смотрят вниз
    enemy.setMap(gameMap);

    // Создаём AI для врага
    const ai = new EnemyAI(enemy);

    enemies.push(enemy);
    enemyAIs.push(ai);

    console.log(`Enemy spawned at (${x}, ${y})`);
}

И рисуем это

for (const enemy of enemies) {
    if (!enemy.destroyed) {
      enemy.render();
    }
  }

Там ещё есть обновление ссылок чтоб чистить из памяти уничтоженные танки, но в целом ничего больше интересного.

Оптимистичный план на следующий этап вот такой:

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

Сказ про то, как всем миром Лису спасали!

51
Читалка

Жили-были. И всё у них было. И блины пеклись, и масло шкворчало, и Масленица во дворе плясала.

Да вот беда приключилася. Наша хлопотунья Лиса, главная по блинам да по праздникам, поскользнулась на маслице — и бух! Прямиком в тёмный подвал, где солёные огурцы в банках дозревают да картошка прошлогодняя дремлет.

Сидит Лиса, бедная, под провалом в подвал, лапой утирается, тонко подвывает:

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

Услыхал тот плач первый блинодел. Прибежал, сковал ПЕРВОЕ ЗВЕНО, спустил цепь — тянет-потянет, а вытянуть не может. Да и что сказать? Не цепь, а всего одно звено!

Кликнул он соседа — второе звено сковали. Тянут-потянут — всё одно не достаёт. Кликнули бывалого блинопёка — третье звено приковали. Тянут-потянут — нет, не вытянуть!

И пошло-поехало! Кого только ни кликали: мастеров с печатями, песенников-скоморохов с блинами «жирненькими», стряпух с блинами безлактозными, заварными да разными, гостей заморских привечали, а еще того самого, кто сначала на печи лежал, бока отлёживал, а потом как подскочит - «Ща ворвусь»!

Много звеньев сковали — а цепи всё не хватает. Лиса ухватится, ее тянут, а звенья только растягиваются.

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

И тут поняли они: одной цепи мало. Нужна СЕТЬ! Чтобы не одной ниточкой тянуть, а всем миром сразу, со всех сторон!

И пошла плестись СЕТЬ СПАСЕНИЯ!

И стали они кликать всех-всех-всех: и тех, кто блины печет, и тех, кто только смотрит, и тех, кто в комментариях шутит, и тех, кто в пяти цепочках сразу бежит!

И когда цепь эта стала длинною в бесконечность, когда связала она всех воедино — от первого блинодела до последнего молчуна в комментариях, — дружно они крикнули:

— РАЗ! ДВА! ТРИ! ТЯНИ-И-И-И!!!

И — АЙ ДА МОЛОДЦЫ! АЙ ДА СПАСАТЕЛИ!

ВЫТЯНУЛИ ЛИСУ!

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

— Спасибо вам, добрые люди! — раскланялась Лиса на все стороны. — Век вашей доброты не забуду! А теперь — ВСЕМ ЗА СТОЛ! БЛИНЫ ЕСТЬ! МАСЛЕНИЦУ ВСТРЕЧАТЬ!

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

А Лиса, главная затейница, всем по блину подкладывала да приговаривала:

— Ешьте, родимые! Ешьте, спасители мои! Без вас бы я там, с огурцами, навеки осталась!

И тут слово молвил главный блинный летописец:

— А кто Лису спасал, кто блины пек да в цепочках стоял — всем носить отныне почётное звание «ВОТ БЛИН ПЕРВОЙ СТЕПЕНИ»! И мастер наш искусный уже за работу принялся — награды ладит, одна к одной, круглые да румяные, прямо как блины, только с душой и на вечную память!

Тут и сказке конец. А кто дочитал да блином закусил — тот и в цепочке нашей навеки остался. С Масленицей вас, люди добрые! 🥞🦊

Любителей красивых чисел из Новосибирска подвела погода...

Нумерологам и любителям всяких числовых комбинаций

40

Вчера даже завел будильник, что бы "поймать" мгновение. Но мороз подкачал.