Fistashka & Pipius
Hey Pipius, imagine if we could code a game where the level layout spins around like a spinning top every time you hit a button—would you be up for the challenge?
That sounds insane, but I love insane. Let’s hash out a physics engine that treats the map as a rigid body, use a quaternion rotation around the center of mass each button press, and keep the collision mesh updated on the fly. I’ll start with a simple 2D prototype in SDL, then expand to 3D with my own light physics loop. Don’t worry about the UI, I’ll throw that out the window if it slows me down. Ready to spin?
Wow, this is going to be a whirlwind! I’m all in—let’s spin this into a wild ride! Just give me the first chunk of code, and I’ll jump in with a crazy idea for the collision mesh update. Let’s keep the UI optional, because who needs it when you can dance on the edge of physics? Let's do it!
```c
// spinning_level.c
#include <SDL.h>
#include <math.h>
#define WIDTH 800
#define HEIGHT 600
#define ROT_SPEED 0.05
typedef struct {
SDL_Rect rect;
double angle; // current rotation angle
} Tile;
Tile tiles[10]; // simple 10 tiles for demo
int numTiles = 10;
void initTiles() {
for (int i = 0; i < numTiles; ++i) {
tiles[i].rect.x = i * 70 + 50;
tiles[i].rect.y = HEIGHT / 2 - 25;
tiles[i].rect.w = 60;
tiles[i].rect.h = 50;
tiles[i].angle = 0;
}
}
void rotateTile(Tile *t, double delta) {
t->angle += delta;
if (t->angle > 2*M_PI) t->angle -= 2*M_PI;
if (t->angle < 0) t->angle += 2*M_PI;
}
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *win = SDL_CreateWindow("Spin",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
WIDTH, HEIGHT, 0);
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
initTiles();
int running = 1;
while (running) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) running = 0;
if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_SPACE) {
for (int i = 0; i < numTiles; ++i)
rotateTile(&tiles[i], ROT_SPEED);
}
}
SDL_SetRenderDrawColor(ren, 30, 30, 30, 255);
SDL_RenderClear(ren);
for (int i = 0; i < numTiles; ++i) {
SDL_Rect r = tiles[i].rect;
SDL_Point center = { r.x + r.w/2, r.y + r.h/2 };
SDL_RenderSetScale(ren, 1, 1); // reset scale
SDL_RenderSetViewport(ren, NULL);
// rotate the renderer's matrix
SDL_RenderSetScale(ren, cos(tiles[i].angle), sin(tiles[i].angle));
SDL_SetRenderDrawColor(ren, 200, 100, 50, 255);
SDL_RenderFillRect(ren, &r);
}
SDL_RenderPresent(ren);
SDL_Delay(16);
}
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
```
OMG, that’s already a cool start, but let’s crank it up a notch! Instead of trying to spin the renderer matrix, use `SDL_RenderCopyEx` to rotate each tile around its center – it’s way smoother. Also, the scale trick with cos/sin is a bit wonky; you’ll end up squashing the tiles. And hey, maybe keep a simple vector for the center of mass and rotate the whole array of tiles around that point, so the whole level feels like a spinning carousel. Ready to swap the math for real rotation and watch the chaos unfold? Let's do it!
Got it, let’s ditch the matrix hack and use SDL_RenderCopyEx for true rotation. I’ll keep a global center of mass, rotate each tile’s position around it, and pass that to RenderCopyEx. Here’s the updated chunk:
```c
// add this near the top
typedef struct { double x, y; } Vec2;
Vec2 cm = { WIDTH/2.0, HEIGHT/2.0 };
// rotate a point around 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); // for now, just fill
// eventually swap with RenderCopyEx using a texture
}
}
// in the main loop after input handling
for (int i = 0; i < numTiles; ++i)
rotateTile(&tiles[i], ROT_SPEED);
renderTiles(ren);
```
Now every tile spins around the shared center, and you can later swap the fill for a real sprite via RenderCopyEx. Time to see the chaos.
Sounds like a blast! 🎉 Just one quick tweak—make sure the rotation angle stays in 0‑2π, otherwise the tiles will get a little… off‑beat. And when you swap in textures, don’t forget to set the pivot point in `SDL_RenderCopyEx` so they spin right where you want. Can’t wait to see that whole level doing the salsa dance! Keep the energy up!
Just keep the angle in [0,2π] with a quick if after rotateTile. For the texture swap, pass the tile’s center as the second point in RenderCopyEx. That way the pivot stays fixed and the salsa spins clean. You’ll see the whole level groove. Keep that math tight, don’t let the tiles drift. Let's crank the dance floor.
Got it—tight angles, tight groove. Just load a texture per tile, set the pivot to that center, and let RenderCopyEx do the dancing. We’ll make sure nothing drifts, all spinning in sync. Ready to crank this into a full-on rave? Let's spin!