Медведь
Немного ювелирного 😎 я конечно в этом рукожëпь но всёЖ
Проба литья, которая мне уже нравится как выходит)
Проба литья, которая мне уже нравится как выходит)
Сделал бюст хищника из нержавейки с помощью аргонодуговой сварки и болгарки.
Нержавейка и бронза.
Приятного просмотра;)
После прекрасного мультика, которым с нами любезно поделилась @etoshtrudel пошла читать Эдварда Лира. Это же он писал Лимерики, которые кто только не переводил (а читать лучше в оригинале, потому что это того же порядка тексты, что и сказки об Алисе - хрен переведёшь даже в прозе, а в стихах и подавно).
Евгений Клюев (тот самый, чей перевод "Уточки и Кенгуру" использовался в мультике) писал, что переводил их из чистого упрямства - настолько они непереводимы.
Принесла вам немножко:
Некоторые из них в детстве читала в журнале "Трамвай". Кто-нибудь помнит журнал "Трамвай"?
А это мой любимый (и сдаётся мне, что то что немного выше про Этну - другой перевод одного и того же лимерика):
Всем спасибо за внимание, а под конец сообщу, что большая часть лимериков прекрасно ложится на мотив "Стюардессы по имени Жанна", а за сим убегаю, уворачиваясь от летящих тапков тех, кто сегодня весь день будет их распевать 😂
Также имеет название "голубая австралийская квакша". И это название ей подходит! Вид у неё аж какой-то фарфоровый.
Для квакши она довольно крупная, до 10 см. Помимо зелёно-бирюзовой расцветки выделяется своим горизонтальным зрачком. На лапках есть присоски.
Кожные выделения литории обладают бактерицидными и противовирусными свойствами (так что вполне можно добавить в список безумных дел на жизнь "помыть руки лягушкой").
Выделения немного восковые, поэтому препятствуют испарению влаги.
Квакша обитает в Австралии и Новой Гвинее. Любит влажные леса, предпочитая селиться в сырых дуплах деревьев. Тем не менее, может вести и наземный образ жизни вдали от водоёмов. Спокойно живёт на болотах и лугах.
Литории совсем не боятся людей, поэтому могут даже забрести в чей-нибудь дом и жевать мух на подоконнике.
Эта квакша — одна из самых популярных и простых в уходе домашних лягушек. В неволе доживает до 20 лет. Единственной проблемой может быть ожирение от перекармливания :D
Что ж. Намеченный план был выполнен полностью.
Было три итерации, сначала сделал так, чтоб танки могли крошить всех (в том числе и враги уничтожали друг друга).
Потом я запретил им убивать друг друга, а на третьем этапе ещё добавил взаимоуничтожение снарядов игрока и врага при попадании.
Давайте посмотрим, что там по коду интересного и не очень.
Из нового: появился файлик effects.js, который отвечает за всякие красивости, из самого заметного: взрывы)
const EFFECT_CONFIG = {
[EffectType.EXPLOSION_SMALL]: {
maxFrames: 3,
frameTime: 3, // 3 игровых кадра на кадр анимации (100ms при 30 FPS)
size: BULLET_SIZE * 2,
colors: ['#FFFF00', '#FFA500', '#FF4500'] // Жёлтый → оранжевый → красный
},
[EffectType.EXPLOSION_BIG]: {
maxFrames: 5,
frameTime: 3,
size: TANK_SIZE * 1.5,
colors: ['#FFFFFF', '#FFFF00', '#FFA500', '#FF4500', '#8B0000'] // Белый → жёлтый → оранжевый → красный → тёмно-красный
},
[EffectType.SPAWN]: {
maxFrames: 4,
frameTime: 4,
size: TANK_SIZE,
colors: ['#FFFFFF', '#888888', '#FFFFFF', '#888888'] // Мигание
}
};
И сам класс эффекта:
export class Effect {
/**
* @param {number} x - Логическая координата X (центр эффекта)
* @param {number} y - Логическая координата Y (центр эффекта)
* @param {string} type - Тип эффекта (EffectType)
*/
constructor(x, y, type = EffectType.EXPLOSION_SMALL) {
this.x = x;
this.y = y;
this.type = type;
// Получаем конфигурацию для этого типа эффекта
const config = EFFECT_CONFIG[type] || EFFECT_CONFIG[EffectType.EXPLOSION_SMALL];
this.maxFrames = config.maxFrames;
this.frameTime = config.frameTime;
this.size = config.size;
this.colors = config.colors;
// Состояние анимации
this.frame = 0;
this.age = 0;
}
/**
* Обновление состояния эффекта
* @param {number} dt - Время кадра (не используется при fixed timestep)
*/
update(dt) {
this.age++;
// Переход к следующему кадру анимации
if (this.age >= this.frameTime) {
this.frame++;
this.age = 0;
}
}
/**
* Проверка завершения анимации
* @returns {boolean} true если анимация закончилась
*/
isDone() {
return this.frame >= this.maxFrames;
}
/**
* Отрисовка эффекта
*/
render() {
if (this.isDone()) return;
const ctx = foregroundCtx;
// Конвертация логических координат в физические
const px = GAME_FIELD_X + this.x * GAME_SCALE;
const py = GAME_FIELD_Y + this.y * GAME_SCALE;
// Размер эффекта меняется в зависимости от кадра
const progress = this.frame / (this.maxFrames - 1);
const currentSize = this.size * GAME_SCALE * (0.5 + progress * 0.5);
// Цвет из массива цветов
const colorIndex = Math.min(this.frame, this.colors.length - 1);
const color = this.colors[colorIndex];
// Рисуем взрыв как круг
ctx.beginPath();
ctx.arc(px, py, currentSize / 2, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
// Внутренний круг (ядро взрыва)
if (this.type === EffectType.EXPLOSION_BIG && this.frame < this.maxFrames - 1) {
ctx.beginPath();
ctx.arc(px, py, currentSize / 4, 0, Math.PI * 2);
ctx.fillStyle = '#FFFFFF';
ctx.fill();
}
}
}
Часть этого кода перепишется, когда я переведу игру на спрайты, оставив только смену кадров и "возраст", а все остальные визуальности удалив.
В файле коллизий появилась ещё пара новых методов:
export function checkBulletTankCollision(bullet, tanks) {
const bulletBox = {
x: bullet.x,
y: bullet.y,
width: BULLET_SIZE,
height: BULLET_SIZE
};
// Определяем, является ли владелец пули врагом
const ownerIsEnemy = bullet.owner && bullet.owner.type !== TankType.PLAYER;
for (const tank of tanks) {
// Пропускаем владельца пули и уничтоженных
if (tank === bullet.owner || tank.destroyed) continue;
// Вражеские пули пролетают сквозь других врагов (как в оригинале)
if (ownerIsEnemy && tank.type !== TankType.PLAYER) continue;
const tankBox = tank.getBounds();
if (checkAABBCollision(bulletBox, tankBox)) {
return tank; // Попадание в танк
}
}
return null;
}
export function checkBulletBulletCollisions(bullets) {
const collisions = [];
for (let i = 0; i < bullets.length; i++) {
const bullet1 = bullets[i];
if (!bullet1.active) continue;
const box1 = {
x: bullet1.x,
y: bullet1.y,
width: BULLET_SIZE,
height: BULLET_SIZE
};
// Определяем, принадлежит ли пуля игроку
const isPlayer1 = bullet1.owner && bullet1.owner.type === TankType.PLAYER;
for (let j = i + 1; j < bullets.length; j++) {
const bullet2 = bullets[j];
if (!bullet2.active) continue;
const isPlayer2 = bullet2.owner && bullet2.owner.type === TankType.PLAYER;
// Сталкиваются только пули разных команд (игрок vs враг)
if (isPlayer1 === isPlayer2) continue;
const box2 = {
x: bullet2.x,
y: bullet2.y,
width: BULLET_SIZE,
height: BULLET_SIZE
};
if (checkAABBCollision(box1, box2)) {
collisions.push({ bullet1, bullet2 });
}
}
}
return collisions;
}
В целом, тут можно было бы выбрать и иные решения, коллизия и методы их проверки могли бы стать более универсальными, как это сделано, скажем, в Unity. Навесить на все объекты box collider'ы и просто проверять их столкновения без отдельных методов (проверить ТанкТанк, проверить ТанкПуля, проверить ПуляПуля). В таком случае логичнее было бы добавить возможность делать коллизии триггерными, для отработки логики уже внутри самих объектов. Но в таком случае для такой простой игры значительно усложнилась бы архитектура. Поэтому в жертву универсальности я пошёл по более прямолинейному пути.
План на следующий этап:
Не было у меня такого инструмента, а теперь есть. Даже где-то в комментариях про него разговор был с @Brainy но сохранений тогда не было, так что это не точно. Ну раз появился надо срочно что-то запилить!
Взял монетку с дыркой, в качестве материала, отмыл. Жаль испорчена, лежала бы в альбомчике...
Не нашел дома тонкие фломастеры чтоб нарисовать прям на металле и ничего умнее наклейки не придумал. Пилить оказалось не суперсложно, полотно порвал всего два раза :) Дальше был процесс шкурения и немного полировки. Достал свои тонкие сверла делать глоза, пусть будут круглые и прикрутил первую попавшуюся цепочку. Там конечно еще много чего исправить и улучшить, но еще не все нужные приспособы у меня есть, да и списочек их теперь вырос. Поэтому...
Готово!
всегда любила мелкие фигурки из металла. а коша даже как постоянный брелок.
Ты же тоже умеешь в аргонодуговую, давай, показывай шедевры!
Йодорастворимый