Aid314
Опубликовано 2 месяца назад
Читать дальше...
Всех продержавшихся - с преодолением экватора. Мы большие молодцы!
А мои новые маркеры оставляют хороший след, надеюсь их теперь хватит до финиша :)
Работы за вчерашний день:
И моё... Бесконечность
В прошлый раз мы нарисовали наш танк и научили его передвигаться. Теперь необходимо научить его врезаться в стены/воду.
Для этого создаём сущность коллизии и после инициализации уровня храним в памяти все коллизии и в момент попытки двигаться проверяем столкновение коллизий.
Это некая базовая версия физического движка. Нужно понимать логику: то, что игрок видит на экране не имеет никакого значения. Физика просто работает и говорит можно ехать дальше или нет. В какой-то мере это почти тоже самое, что происходит, например, в Unity. Но там система сложнее и она работает скорее подобно тому, как у меня сделано в тетрисе:
Здесь же я просчёт сделал по принципу экстраполяции (С Юнити тоже есть такой вариант у коллизий), когда просчёт пересечений происходит как бы с взглядом в будущее, просчёт потенциального пересечение ещё до того, как оно произошло.
Давайте же посмотрим, как это выглядит.
Коллизия – это не класс как таковой, это просто набор общедоступных методов.
/**
* Получить список субтайлов, покрываемых прямоугольником
*
* @returns {Array<{tx: number, ty: number}>} Массив координат субтайлов
*/
export function getTilesUnderEntity(x, y, width, height) {
const left = Math.floor(x / TILE_SIZE);
const right = Math.floor((x + width - 1) / TILE_SIZE);
const top = Math.floor(y / TILE_SIZE);
const bottom = Math.floor((y + height - 1) / TILE_SIZE);
const tiles = [];
for (let ty = top; ty <= bottom; ty++) {
for (let tx = left; tx <= right; tx++) {
// Проверяем границы сетки
if (tx >= 0 && tx < GRID_SIZE && ty >= 0 && ty < GRID_SIZE) {
tiles.push({ tx, ty });
}
}
}
return tiles;
}
/**
* Проверить, может ли танк войти на данный тайл
*
* @returns {boolean} true если танк может войти
*/
export function canTankEnter(tileDef, tank) {
if (!tileDef) return true;
// Вода: проходима только с бонусом "лодка"
if (tileDef.id === TileType.WATER) {
return tank && tank.hasBoat;
}
return !tileDef.blocksTank;
}
/**
* Проверить коллизию танка с картой при движении в новую позицию
* та самая экстраполяция
*
* @returns {boolean} true если коллизия есть (нельзя двигаться)
*/
export function checkTankMapCollision(tank, newX, newY, gameMap) {
// Получаем субтайлы под новой позицией танка
const tiles = getTilesUnderEntity(newX, newY, TANK_SIZE, TANK_SIZE);
// Проверяем каждый субтайл
for (const { tx, ty } of tiles) {
const tileId = gameMap.getTile(tx, ty);
const tileDef = TILE_DEFS[tileId];
if (!canTankEnter(tileDef, tank)) {
return true; // Есть пересечение
}
}
return false; // Нет пересечений
}
/**
* Проверить коллизию двух AABB (Axis-Aligned Bounding Box)
*
* @returns {boolean} true если боксы пересекаются
*/
export function checkAABBCollision(a, b) {
return (
a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.y + a.height > b.y
);
}
/**
* Проверить коллизию двух танков
*
* @returns {boolean} true если есть коллизия с другим танком
*/
export function checkTankTankCollision(tank, newX, newY, tanks) {
const tankBox = {
x: newX,
y: newY,
width: TANK_SIZE,
height: TANK_SIZE
};
for (const other of tanks) {
// Пропускаем себя и уничтоженных
if (other === tank || other.destroyed) continue;
const otherBox = other.getBounds();
if (checkAABBCollision(tankBox, otherBox)) {
return true; // Коллизия с другим танком
}
}
return false;
}
А ещё с прошлого поста был проведён рефакторинг. У меня чесалось нёбо от неудобных некрасивых констант, с которыми были вездесущие сравнения. В целом, не магические числа – уже хорошо, но тем не менее. Енамки JS не поддерживает, поэтому делаем костыль через замороженные объекты.
// Было
export const TILE_EMPTY = 0;
export const TILE_BRICK = 1;
export const TILE_STEEL = 2;
export const TILE_WATER = 3;
export const TILE_FOREST = 4;
export const TILE_ICE = 5;
export const TILE_BASE = 6;
// Стало
export const TileType = Object.freeze({
EMPTY: 0,
BRICK: 1,
STEEL: 2,
WATER: 3,
FOREST: 4,
ICE: 5,
BASE: 6
});
Проверка самих коллизий происходит в методе передвижения танка
newX = Math.max(0, Math.min(newX, LOGICAL_FIELD_SIZE - TANK_SIZE));
newY = Math.max(0, Math.min(newY, LOGICAL_FIELD_SIZE - TANK_SIZE));
if (gameMap && checkTankMapCollision(this, newX, newY, gameMap)) {
return; // не применяем результат передвижения, просто выходим
}
Ну и в сам метод передаётся информация о карте в инпут менеджере
if (gp.buttons[12]?.pressed) player.move(Direction.UP, gameMap);
if (gp.buttons[13]?.pressed) player.move(Direction.DOWN, gameMap);
if (gp.buttons[14]?.pressed) player.move(Direction.LEFT, gameMap);
if (gp.buttons[15]?.pressed) player.move(Direction.RIGHT, gameMap);
А сам gameMap у нас и главного скрипта, а там он формируется как и раньше в
loadLevel(TEST_LEVEL_1);
Результат:
Далее по плану научить танк стрелять и, в идеале, отрабатывать попадания снарядов в стены.
Есть у нас в одной сети пекарен прикольные пирожные-корзиночки, а тут ебнуло мне, что можно ж самой такие попробовать сделать, чтоб не покупать их.
Купила, распробовала, вроде поняла, что должно быть в начинке и накатала себе список недостающего. Ну и как обычно - время 3 часа ночи, а значит, пора ебашить :D
(Ради любопытства полезла в галерею и убедилась, что по чистой случайности у меня многие кухонные пиздопляски происходят примерно в это время)
Корзинки там были с ладоху, у меня таких форм не оказалось, поэтому, сегодня они будут тарталетками :D
Итак...
Для теста:
- яйцо - 1 шт.
- мёд - 50 гр.
- сливочное масло (мягкое) - 60 гр.
- сахар - 40 гр.
- мука - 160 гр.
- разрыхлитель - 1 ч.л.
- ванилин по вкусу
Для творожного крема:
- творог 9% - 180 гр.
- яйцо - 1 шт.
- сгущёнка - 60 гр.
- мука - 20 гр.
- сахар - 20 гр.
- ванилин по вкусу.
В тех самых корзинках был ещё джем на дне (в каждой точке пекарни разный кладут) и ягоды в самом креме (раньше была вишня, сейчас чёрная смородина). У меня дома был черничный джем и чёрная смородина в морозилке. Взяла их.
Процесс лёгкий:
Смешать все ингредиенты для теста
Замесить в комочек
Брать по шарику и размазывать по формочке, чтоб с бортиками было
А потом смешать всё для крема
Сделать ВЖЖЖБЖЖББЖЖЖЖ блендером
Ну и всё, можно собирать одно в другое))
Поставила на 180° и ушла мыть посуду...
Так как в моём случае тарталетки были тонкие, за 15 минут всё уже было готово :)
Сделала вывод, что мне всё-таки нужны алюминиевые формочки для таких штук, ибо если выпекать в них, то корзинки будут более хрустящие, чем после силиконовых. И я бы разрыхлителя поменьше чуть добавила, чёт дохуя его как-то, имхо.
Закажу формочки и буду исправляться)
Города — это не просто среда обитания человека, а целая новая экосистема, в рамках которой виды эволюционируют быстрее, чем в дикой природе.
Комары лондонского метро (лат. Culex pipiens molestus) генетически отличаются от своих "деревенских" родственников настолько, что практически с ними не скрещиваются. Кроме того, они не впадают в зимнюю спячку, активны круглый год и эффективно размножаются в замкнутых пространствах туннелей. Кровь для развития яиц самки "добывают" у людей и крыс.
Птицы в городах поют громче и на более высоких частотах, чтобы пробиться сквозь шум транспорта и строек. Они меньше боятся людей и меняют суточный ритм из-за многочисленных источников искусственного освещения. Вороны вообще научились использовать автомобили как щелкунчики: кладут орехи на дорогу и ждут, пока проезжающая машина раздавит скорлупу.
Микробы тем более не стоят на месте. Бактерии на бетоне, пластике и металле смогли приспособиться к материалам, которых никогда не было в природе. Они учатся разлагать синтетические полимеры и выживать в присутствии всевозможных дезинфицирующих средств.
Город — это огромная лаборатория, где эволюцию можно наблюдать в "прямом эфире".
Я несколько дней думал насчёт того, чтобы формат дневника привязать к данному лисьему ресурсу, где это соберёт отклик и движ, ежели отдавать ВК, где примерно никому интересно. Итак: сегодня день не претендовал на хороший или плохой, он просто случился: вроде бы и негатива не испытал, но и позитива особо не было.
В фотографиях этот день почти не зафиксирован... кроме одной:
Гыыы
Вспомнилось. Розовый бинт - Агата кристи.mp3
Хотя у них много на эту тему.
@CircusBirdEli, попробуем по ролям что-нибудь лёгкое?))
Гыгыгы.. поддерживаешь?