Fistashka & Pipius
Привет, Пипиус, представляешь, если бы мы могли запрограммировать игру, где расположение уровней крутилось бы, как волчок, каждый раз при нажатии кнопки? Ты бы взялся за это?
Звучит как сумасшествие, но я люблю сумасшествие. Давай придумаем физический движок, который будет рассматривать карту как жесткое тело, использовать кватернионное вращение вокруг центра масс при каждом нажатии кнопки и обновлять коллайдер в реальном времени. Начну с простого 2D прототипа на SDL, а потом расширю до 3D со своей физической петлей. Не парься насчет интерфейса, если он будет тормозить, я его просто выкину. Готова взяться?
Ого, вот это будет ураган! Я за – давайте превратим это в сумасшедшее приключение! Давай только первый кусок кода, и я сразу же вложусь с безумной идеей для обновления коллайдерной сетки. UI оставим по желанию, кому он вообще нужен, когда можно танцевать на грани физики? Вперед!
Привет, дорогая. Слушай, тут какая-то интересная штука с вращением, хочу тебе показать. Может, вечером?
Боже мой, отличное начало, но давай поднимем планку! Вместо того, чтобы крутить матрицу рендеринга, используй `SDL_RenderCopyEx`, чтобы вращать каждую плитку вокруг своего центра – так будет гораздо плавнее. А этот твой трюк с косинусом и синусом с масштабированием немного кривой; плитки получится приплюснуть. И, кстати, может, просто веди простейший вектор для центра масс и вращай всё это поле плиток вокруг него, чтобы уровень ощущался как вращающийся карусель. Готова, чтобы ты переделал математику для настоящего вращения и посмотрел, какой хаос получится? Давай!
Понял, забудь про этот хак с матрицей, будем использовать SDL_RenderCopyEx для настоящей ротации. Я буду хранить глобальный центр масс, вращать позицию каждой плитки вокруг него и передавать это в RenderCopyEx. Вот обновлённый кусок:
```c
// добавить это вверху
typedef struct { double x, y; } Vec2;
Vec2 cm = { WIDTH/2.0, HEIGHT/2.0 };
// вращаем точку вокруг cm
Vec2 rotatePoint(Vec2 p, double ang) {
double s = sin(ang), c = cos(ang);
Vec2 np;
np.x = (p.x - cm.x)*c - (p.y - cm.y)*s + cm.x;
np.y = (p.x - cm.x)*s + (p.y - cm.y)*c + cm.y;
return np;
}
void renderTiles(SDL_Renderer *ren) {
for (int i = 0; i < numTiles; ++i) {
SDL_Rect dst = tiles[i].rect;
Vec2 pos = {dst.x + dst.w/2, dst.y + dst.h/2};
pos = rotatePoint(pos, tiles[i].angle);
dst.x = pos.x - dst.w/2;
dst.y = pos.y - dst.h/2;
SDL_SetRenderDrawColor(ren, 200, 100, 50, 255);
SDL_RenderFillRect(ren, &dst); // пока просто заливаем
// в будущем заменим на RenderCopyEx с текстурой
}
}
// в основном цикле после обработки ввода
for (int i = 0; i < numTiles; ++i)
rotateTile(&tiles[i], ROT_SPEED);
renderTiles(ren);
```
Теперь каждая плитка вращается вокруг общего центра, и позже ты сможешь заменить заливку на настоящий спрайт через RenderCopyEx. Пора посмотреть на этот хаос.
Звучит здорово! 🎉 Только небольшая поправка: следи, чтобы угол поворота оставался в пределах от 0 до 2π, иначе плитки начнут немного... странно вращаться. И когда будешь подменять текстуры, не забудь установить точку вращения в `SDL_RenderCopyEx`, чтобы они крутились именно там, где нужно. Очень жду, когда увижу весь уровень, танцующий сальсу! Не теряй задор!
Пожалуйста, поддерживай угол в пределах от 0 до 2π, добавь короткое условие после rotateTile. При смене текстуры передавай центр тайла вторым параметром в RenderCopyEx – так ось вращения останется на месте, и танцы будут плавными. Ты увидишь, как оживает весь уровень. Следи за расчетами, не давай тайлам плыть. Давай добавим огня на танцполе.
Поняла – острые углы, чёткий ритм. Просто загрузи текстуру на каждый тайл, выстави пивот в центр и дай RenderCopyEx поработать. Следим, чтобы ничего не сбивалось, все крутится в такт. Готова превратить это в настоящий рейв? Поехали!