Отгадай-ка
Так как я отгадал половину предыдущей загадки, а @vervolph загадывать не хочет, то вот вам от меня простая загадка.
Этот орган у человека никогда не болит. Какой?
Так как я отгадал половину предыдущей загадки, а @vervolph загадывать не хочет, то вот вам от меня простая загадка.
Этот орган у человека никогда не болит. Какой?
В выходной, да в плохую погоду, очень не хочется куда-то двигаться, а вкусно себя покормить очень даже. Сегодня захотелось шаурмы, будем крутить :)
Подмаринуем мясо и пожарим без всяких грилей, прям в сковороде.
Разбираем поджаренный на сковороде рулетик и готово.
Всем приятного аппетита и спасибо за внимание!
От имени своего журнала @VariusSoft выкладывал посты про то, как тетрис запилить и сейчас серия постов о том как воссоздать танчики. В процессе разработки осознал, что в них надо играть вдвоём, а как же это делать, если сесть за одну денди и взять в руки два джойстика нет возможности?
Ну, онлайн, чё тупить. Но как организовать онлайн? В общем покумекал я немного и решил, что для этого необходим сервер. Но писать полноценный сервер для игры в танчики – это, как будто, прям из пушки по воробьям. Поэтому я решил написать универсальный сервер, который одновременно может обслуживать несколько игр, каждая на пару-тройку десятков одновременных игроков.
Выглядит это безобразие так:
Написан он на Шарпе и скомпилирован под 8 дот нет, чтоб была возможность запустить и на маках и на линях. Но ещё, для пущей уверенности, завернул к херам в докер это безобразие.
Каков же алгоритм работы?
Первый игрок, который хочет с кем-то поиграть, нажимает кнопочку «Создать комнату» в интерфейсе игры, игры стучится на сервер и получает идентификатор комнаты. Дальше и эта игра и другие клиенты подключаются к этой же комнате. Первый клиент выступает в роли хоста. То есть вся обработка геймплея и игрового мира происходит на нём. Как это всегда было в КС, Халфе и прочих сессионных зарубах.
Также написал SDK на JS для встраивания работы с сервером в любую HTML5 игру.
Математически при хорошем канале данный сервер способен вытянуть одну игру на 400-500 человек или 10 игр по 40. Как на практике будет работать, посмотрим. Хотя, сэмулировать нагрузку в 500 человек я даже если очень хочу, не смогу)
Но! Если вы вдруг увлекаетесь игронаписанием, я могу вам выдать сервак на растерзание, ну или просто для своей игры себе чтоб подняли и использовали.
И да, я уже предвижу комментарии из цикла: «Нахер изобретать велосипед», но мне насрать, серьёзно. Я хотел написать, я написал.
Всем хороших игр!
Ответ на пост Ответ на пост: На волне "Нелицеприятный"
У меня всё без длинной истории, но всё же волна так волна))
Будучи мелкой школьницей услышала два похожих друг на друга слова и они у меня слились в одно...
Поэтому, "медитировать" и "мастурбировать" - были для меня словами с одинаковым значением))
Ответ на пост На волне "Нелицеприятный"
Воспоминание разблокировано!
Происходило это в весьма позднем детстве. Лето. Мне почти четырнадцать лет. Моя сестра поступила в вуз — и не абы куда, а в Москву! Гордость всей семьи!
Я тогда была созданием более чем невинным и далёким от глубоких познаний дворовых мальчишек о человеческих пороках.
Иду из магазина — и вдруг за мной увязались трое пацанов на пару лет младше. Докапываются: то уродкой назовут, то дурочкой, то лохушкой. Сначала их шугала, а потом стала за ними гоняться с обещаниями поймать и отлупить. А им только этого и надо: разбегаются в разные стороны, хохочут и продолжают дразниться. И тут среди прочих обидных эпитетов вылетает: «Праститутка!»
Я остановилась. Слово это слышала и раньше во дворе — применяли его к уже взрослым и красивым девочкам. Таким же взрослым и красивым, как моя сестра! Так кто же такая праСТИТУТка?.. Наверное, это та, кто учится в инСТИТУТе! — решила я и продолжила гоняться за шпаной, но теперь уже выкрикивая на весь двор:
«Не обзывайтесь так! Праституткой быть хорошо! У меня сестра — праститутка в Москве! И я, когда вырасту, тоже стану праституткой! А вы глупые и ничего не понимаете!»
У нас появилась функция опросов.
С одной стороны, мне бы хотелось попробовать голосование за слово для фотофокс проводить с их помощью, чтобы в одном посте сразу были выкачены слова и там на месте уже бы все могли проголосовать, а не искали пост и не разворачивали комменты, чтобы глянуть все выдвинутые слова и поставить им оценку, как это делается сейчас…
Мне это кажется удобным. Но есть одно НО :D
Я не могу сообразить, как изменить механику начала выбора этих слов. Ибо если оставить всё так же, то получится странно, ведь по привычке, скорее всего, люди будут голосовать +/- в комментах и если я буду выкатывать эти слова потом опросом для повторного голосования - тоже неправильно.
Может быть, у кого-то найдутся мысли, как можно переебать систему, чтобы подрубить к выбору слова опросы? У меня чёт пока не приходит в голову.
Или, может, вообще не стоит ничего менять?
Ну что, дорогие мои детишечки, пришло время заняться серьезными вещами и немножечко напрячь свой мозг, который у вас большой, огромный, как у доцентов.
Давайте-ка начнем с чего-нибудь простого и всем известного. Так сказать, разомнем ваши пальчики. Хорошо? нет
Вот вам первый вопрос в качестве тренировки. Давайте думать вместе. Рассуждения и обсуждения, конечно же, происходят в комментариях. Потому что тс может нести хуйню... Уже начал есичо
Но если вы не хотите обсуждать и рассуждать, то просто молча ткните кнопку и идите по своим делам дальше, скролить бесконечную ленту.
Итак.
Фая!
Правильный ответ задан автором.
Следующим этапом сделаем систему отображения тайлов на игровом поле. Мы предполагаем, что у нас есть тайлы разных типов: кирпичи там, бетон, вода, лёд, кусты.
И чтобы эти самые блоки рисовать на игровом поле, нужно ввести сущность карты и самих блоков.
Сущность карты:
class GameMap {
constructor() {
// Сетка 26x26 субтайлов
this.tileGrid = [];
for (let y = 0; y < GRID_SIZE; y++) {
this.tileGrid[y] = new Array(GRID_SIZE).fill(TILE_EMPTY);
}
// Карта для хранения состояния повреждений разрушаемых тайлов
this.damageMask = new Map();
// Флаг необходимости перерисовки фона
this.dirty = true;
}
}
Ну и в нашем основном классе надо карту создать:
/** @type {GameMap} */
let gameMap = null;
...
// в методе init
// Создаём и загружаем карту
gameMap = new GameMap();
gameMap.loadLevel(TEST_LEVEL_1);
// Рисуем фон (карта + рамка)
renderBackground(gameMap);
gameMap.dirty = false;
При это тестовый уровень сейчас выглядит вот так:
export const TEST_LEVEL_1 = [
'..........................', // 0 верхний ряд пустой (под спавн врагов)
'..........................', // 1
'..BB..BB..BB..BB..BB..BB..', // 2 кирпичные стены
'..BB..BB..BB..BB..BB..BB..', // 3
'..BB..BB..BB..BB..BB..BB..', // 4
'..BB..BB..SS..BB..BB..BB..', // 5 сталь/бетон
'..BB..FF..SS..FF..BB..BB..', // 6 лес
'..BB..FF......FF..BB..BB..', // 7
'..BB..BB..BB..BB..BB..BB..', // 8
'..BB..BB..BB..BB..BB..BB..', // 9
'..........BB..BB..........', // 10
'..........BB..BB..........', // 11
'..BB..BB..........BB..BB..', // 12
'..BB..BB..........BB..BB..', // 13
'..BB..BB..BB..BB..BB..BB..', // 14
'..BB..BB..BB..BB..BB..BB..', // 15
'......WW..BB..BB..WW......', // 16 вода
'......WW..BB..BB..WW......', // 17
'..BB..BB..II..II..BB..BB..', // 18 лёд
'..BB..BB..II..II..BB..BB..', // 19
'..BB..BB..BB..BB..BB..BB..', // 20
'..BB..BB..BB..BB..BB..BB..', // 21
'..........BBBBBB..........', // 22 защита базы
'..........BBBBBB..........', // 23
'..........BBEEBB..........', // 24 база
'..........BBEEBB..........', // 25
];
Не знаю, пока, на сколько такой формат хранения данных корректен и будет удобен в использовании в дальнейшем, но сейчас он по крайне мере очень нагляден и удобен для ручного левел дизайна.
Рисование блоков достаточно просто:
export function renderBackground(gameMap) {
const ctx = backgroundCtx;
// Очищаем весь фон
clearBackground();
// Рамка игрового поля
renderGameFieldBorder();
// Рисуем все непустые тайлы
for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
const tileId = gameMap.getTile(x, y);
if (tileId === TILE_EMPTY) continue;
const tileDef = TILE_DEFS[tileId];
if (!tileDef) continue;
// Логические координаты → физические координаты на canvas
const px = GAME_FIELD_X + x * TILE_SIZE * GAME_SCALE;
const py = GAME_FIELD_Y + y * TILE_SIZE * GAME_SCALE;
const size = TILE_SIZE * GAME_SCALE;
ctx.fillStyle = tileDef.color; // цвет в самих тайлах пока храню
ctx.fillRect(px, py, size, size); // потом буду спрайты рисовать
}
}
}
Хранятся тайлы у меня вот таким образом:
TILE_DEFS = {
[TILE_EMPTY]: {
id: TILE_EMPTY,
name: 'empty',
blocksTank: false,
blocksBullet: false,
destructible: false,
overlay: false,
color: COLOR_EMPTY // эта вся фигня в константах забита
},
...
У сущности карты есть метод для загрузки из вот того текстового бреда, который чуть выше скинут
loadLevel(levelData) {
for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
const char = levelData[y]?.[x] || '.';
this.tileGrid[y][x] = charToTile(char);
}
}
// Инициализируем damageMask для всех разрушаемых тайлов
this.damageMask.clear();
for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
const tileDef = TILE_DEFS[this.tileGrid[y][x]];
if (tileDef && tileDef.destructible) {
this.damageMask.set(`${x},${y}`, DAMAGE_FULL);
}
}
}
this.dirty = true;
console.log(`Level loaded. Destructible tiles: ${this.damageMask.size}`);
}
function charToTile(char) {
switch (char) {
case 'B': return TILE_BRICK;
case 'S': return TILE_STEEL;
case 'W': return TILE_WATER;
case 'F': return TILE_FOREST;
case 'I': return TILE_ICE;
case 'E': return TILE_BASE;
default: return TILE_EMPTY;
}
}
И вот такой вот получается итог
В целом, уже похоже на правду и с этим можно работать.
план на следующий этап:
Ага:) Просто подкалываю Куку:)
Эвоно как. Ясно:)
Вроде последний месяц починился, значит не у всех)