首页 > 解决方案 > 如何使用数学围绕 ggez 图像的中心而不是左上角旋转?

问题描述

我正在使用ggez制作游戏,使用来自ggez_goodies的相机。

这台相机只能从图像的左上角旋转,但我想从中心旋转。有没有一种很好的方法来定位图像,以便它围绕中心旋转?

我假设您只需更改位置即可解决此问题,我目前拥有的只是位置

self.image
    .draw_camera(
        camera,
        ctx,
        graphics::Point2::new(self.position.0, self.position.1),
        self.rotation,
    )
    .unwrap();

我猜一个修复看起来像这样:

self.image
    .draw_camera(
        camera,
        ctx,
        graphics::Point2::new(
            self.position.0 + self.rotation_offset.0,
            self.position.1 + self.rotation_offset.1,
        ),
        self.rotation,
    )
    .unwrap();

我认为可以使用偏移量,但我不知道如何根据旋转角度设置偏移量。

我可以对位置进行哪些偏移/更改以使图像围绕中心而不是围绕左上角旋转?

标签: rustrotationgame-physicsdiscrete-mathematics

解决方案


在以下示例中:

use ggez;
use ggez::event;
use ggez::graphics;
use ggez::graphics::{DrawMode, MeshBuilder};
use ggez::nalgebra as na;
use ggez::timer::check_update_time;
use ggez::{Context, GameResult};
use std::env;
use std::path;

struct MainState {
    rotate: f32,
    sprite_batch: graphics::spritebatch::SpriteBatch,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let image = graphics::Image::new(ctx, "/sprite_sheet.png").unwrap();
        let batch = graphics::spritebatch::SpriteBatch::new(image);
        Ok(MainState {rotate: 0.0, sprite_batch: batch})
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult {
        while check_update_time(ctx, 30) {
            self.rotate += 0.1;
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, graphics::BLACK);

        let mesh = MeshBuilder::new().circle(
            DrawMode::fill(),
            na::Point2::new(400.0, 300.0),
            2.0,
            2.0,
            graphics::WHITE,
        ).build(ctx)?;
        self.sprite_batch.add(
            graphics::DrawParam::new()
                .src(graphics::Rect::new(0.0, 0.0, 1.0, 1.0))
                .rotation(self.rotate)
                .dest(na::Point2::new(400.0, 300.0))
                .offset(na::Point2::new(0.5, 0.5)),
        );

        graphics::draw(
            ctx,
            &self.sprite_batch,
            graphics::DrawParam::new().dest(na::Point2::new(0.0, 0.0)),
        )?;
        graphics::draw(
            ctx,
            &mesh,
            graphics::DrawParam::new().dest(na::Point2::new(0.0, 0.0)),
        )?;

        self.sprite_batch.clear();
        graphics::present(ctx)?;

        Ok(())
    }
}

pub fn main() -> GameResult {
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("oc", "bux")
        .add_resource_path(resource_dir)
        .window_mode(ggez::conf::WindowMode::default().dimensions(800.0, 600.0));
    let (ctx, event_loop) = &mut cb.build()?;

    let state = &mut MainState::new(ctx)?;
    event::run(ctx, event_loop, state)
}

在哪里resources/sprite_sheet.png在此处输入图像描述

从图像中心旋转的是:

.offset(na::Point2::new(0.5, 0.5))

推荐阅读