You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SDL2角色移动角度异常:无法匹配旋转网格的30°移动求助

等距网格角色移动匹配问题

我绘制了一个向右旋转π/6(30°)的网格以实现深度效果,希望角色(Sprite)能沿网格方块移动。根据三角函数逻辑,左右移动应遵循π/6角度,上下移动应遵循π/3角度,但实际右移仅对应约20°,无法和网格对齐。多次测试仍无法解决,特来求助。

当前代码如下:

#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <math.h>
#include "graphique.h"
#include "../constantes.h"

#define GRID_ROWS 15
#define GRID_COLS 12
#define CELL_WIDTH (WINDOW_WIDTH / GRID_COLS)
#define CELL_HEIGHT (WINDOW_HEIGHT / GRID_ROWS)
#define CELL_RATIO (CELL_HEIGHT / CELL_WIDTH)

typedef struct {
    float x;
    float y;
} Point;

int graphicGame(int joueur) {

    if (SDL_Init(SDL_INIT_EVERYTHING)) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in init: %s", SDL_GetError());
        exit(-1);
    }
    atexit(SDL_Quit);

    if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in image init: %s", IMG_GetError());
        exit(-1);
    }
    atexit(IMG_Quit);

    SDL_Window *window;
    window = SDL_CreateWindow("JETAGAME", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                                             WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
    if (!window) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in window init: %s", SDL_GetError());
        exit(-1);
    }

    SDL_Renderer *renderer;
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (!renderer) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in renderer init: %s", SDL_GetError());
        exit(-1);
    }

    SDL_Surface *playerSpriteSurface = IMG_Load("src/Graphique/Sprites/sprite.png");
    if (!playerSpriteSurface) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in player sprite surface init: %s", IMG_GetError());
        exit(-1);
    }

    SDL_Texture *playerSpriteTexture = SDL_CreateTextureFromSurface(renderer, playerSpriteSurface);
    if (!playerSpriteTexture) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in player sprite texture init: %s", SDL_GetError());
        exit(-1);
    }

    SDL_FreeSurface(playerSpriteSurface);

    int playerSpriteFullWidth, playerSpriteFullHeight;
    if (SDL_QueryTexture(playerSpriteTexture, NULL, NULL, &playerSpriteFullWidth, &playerSpriteFullHeight)) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in query texture: %s", SDL_GetError());
        exit(-1);
    }

    int playerSpriteWidth = playerSpriteFullWidth / 4;
    int playerSpriteHeight = playerSpriteFullHeight / 4;

    SDL_Event event;
    bool running = true;
    int offset = 0;
    double playerX = 3.5, playerY = 3.5;
    int direction = 0;

    double angleHorizontal = M_PI / 6;
    double angleVertical = M_PI / 6;

    double Cx = WINDOW_WIDTH / 2;
    double Cy = WINDOW_HEIGHT / 2;

    while (running) {
        if (SDL_PollEvent(&event)) {
            switch (event.type) {
            case SDL_QUIT:
                running = false;
                break;
            case SDL_KEYDOWN:
                switch (event.key.keysym.sym) {
                case SDLK_DOWN:
                    playerX -= cos(M_PI/3);
                    playerY += sin(M_PI/3);
                    offset += 1;
                    offset %= 4;
                    direction = 0;
                    break;

                case SDLK_UP:
                    playerX += cos(M_PI/2.5);
                    playerY -= sin(M_PI/2.5);
                    offset += 1;
                    offset %= 4;
                    direction = 1;
                    break;

                case SDLK_LEFT:
                    playerX -= cos(M_PI/6);
                    playerY -= sin(M_PI/6);
                    offset += 1;
                    offset %= 4;
                    direction = 2;
                    break;

                case SDLK_RIGHT:
                    playerX += cos(M_PI/6);
                    playerY += sin(M_PI/6);
                    offset += 1;
                    offset %= 4;
                    direction = 3;
                    break;
                }

                break;
            case SDL_KEYUP:
                offset = 0;
                break;
            }
            SDL_Color const BACKGROUND_COLOR = {.r = 0xFF, .g = 0xE6E6E6, .b = 0xFF, .a = SDL_ALPHA_OPAQUE};

            if (SDL_SetRenderDrawColor(renderer, BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, BACKGROUND_COLOR.a)) {
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in set render draw color: %s", SDL_GetError());
            }

            if (SDL_RenderClear(renderer)) {
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in render clear: %s", SDL_GetError());
            }

            SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
            for (int i = 0; i <= GRID_ROWS; ++i) {
                double y = i * (WINDOW_HEIGHT / GRID_ROWS);
                double x1 = 0;
                double y1 = y;
                double x2 = WINDOW_WIDTH;
                double y2 = y;

                double Rx1 = (x1 - Cx) * cos(angleHorizontal) - (y1 - Cy) * sin(angleHorizontal) + Cx;
                double Ry1 = (x1 - Cx) * sin(angleHorizontal) + (y1 - Cy) * cos(angleHorizontal) + Cy;
                double Rx2 = (x2 - Cx) * cos(angleHorizontal) - (y2 - Cy) * sin(angleHorizontal) + Cx;
                double Ry2 = (x2 - Cx) * sin(angleHorizontal) + (y2 - Cy) * cos(angleHorizontal) + Cy;
                SDL_RenderDrawLine(renderer, (int)Rx1, (int)Ry1, (int)Rx2, (int)Ry2);
            }
            for (int j = 0; j <= GRID_COLS; ++j) {
                double x = j * (WINDOW_WIDTH / GRID_COLS);
                double x1 = x;
                double y1 = 0;
                double x2 = x;
                double y2 = WINDOW_HEIGHT;

                double Rx1 = (x1 - Cx) * cos(angleVertical) - (y1 - Cy) * sin(angleVertical) + Cx;
                double Ry1 = (x1 - Cx) * sin(angleVertical) + (y1 - Cy) * cos(angleVertical) + Cy;
                double Rx2 = (x2 - Cx) * cos(angleVertical) - (y2 - Cy) * sin(angleVertical) + Cx;
                double Ry2 = (x2 - Cx) * sin(angleVertical) + (y2 - Cy) * cos(angleVertical) + Cy;

                SDL_RenderDrawLine(renderer, (int)Rx1, (int)Ry1, (int)Rx2, (int)Ry2); // Lignes verticales
            }

            SDL_Rect playerSpriteRect = {.x = offset * playerSpriteWidth, .y = direction * playerSpriteHeight, .w = playerSpriteWidth, .h = playerSpriteHeight};
            SDL_Rect playerDestRect = {.x = playerX * CELL_WIDTH, .y = playerY * CELL_HEIGHT, .w = playerSpriteWidth, .h = playerSpriteHeight};
            if (SDL_RenderCopy(renderer, playerSpriteTexture, &playerSpriteRect, &playerDestRect))
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error in render copy: %s", SDL_GetError());

            SDL_RenderPresent(renderer);
        }
    }

    return 0;
}
  • 尝试使用π/6的实际效果:尝试效果
  • 期望实现的效果:期望效果

内容的提问来源于stack exchange,提问作者EleZen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:59:53