我正在尝试构建一个简单的低多边形球体,它可以使用Sega Saturn游戏手柄(类似于游戏Marble Madness)和Jo Engine(Sega Saturn的C引擎)来“玩”。我使用的代码如下:
#include <jo/jo.h>
#include "sphere.h"
jo_camera cam;
jo_img_8bits floor_image;
jo_palette image_pal;
jo_pos3Df sphere_position = {0, 50, 0}; // Inicializando a posição da esfera
jo_pos3Df pos;
jo_rot3Df rot;
jo_rot3Df sphere_rotation = {0.0f, 0.0f, 0.0f}; // Inicializando a rotação da esfera
void my_draw(void) {
jo_printf(12, 1, "*Simple 3D demo*");
jo_3d_camera_look_at(&cam);
jo_3d_push_matrix();
{
jo_3d_translate_matrixf(sphere_position.x, sphere_position.y, sphere_position.z);
jo_3d_rotate_matrix_rad(sphere_rotation.rx, sphere_rotation.ry, sphere_rotation.rz);
display_sphere_mesh();
jo_3d_set_mesh_texture(&Meshsphere, 0);
}
jo_3d_pop_matrix();
}
void my_gamepad(void) {
const float movement_speed = 1.0f;
const float rotation_speed = JO_DEG_TO_RAD(5.0f);
const float DIAGONAL_FACTOR = 0.707f; //(1/sqrt(2))
float delta_x = 0.0f;
float delta_z = 0.0f;
float delta_rx = 0.0f;
float delta_ry = 0.0f;
switch (jo_get_input_direction_pressed(0))
{
case LEFT:
delta_x = -movement_speed;
delta_ry = -rotation_speed;
break;
case RIGHT:
delta_x = movement_speed;
delta_ry = rotation_speed;
break;
case UP:
delta_z = movement_speed;
delta_rx = -rotation_speed;
break;
case DOWN:
delta_z = -movement_speed;
delta_rx = rotation_speed;
break;
case UP_LEFT:
delta_x = -movement_speed * DIAGONAL_FACTOR;
delta_z = movement_speed * DIAGONAL_FACTOR;
delta_ry = -rotation_speed * DIAGONAL_FACTOR;
delta_rx = -rotation_speed * DIAGONAL_FACTOR;
break;
case UP_RIGHT:
delta_x = movement_speed * DIAGONAL_FACTOR;
delta_z = movement_speed * DIAGONAL_FACTOR;
delta_ry = rotation_speed * DIAGONAL_FACTOR;
delta_rx = -rotation_speed * DIAGONAL_FACTOR;
break;
case DOWN_LEFT:
delta_x = -movement_speed * DIAGONAL_FACTOR;
delta_z = -movement_speed * DIAGONAL_FACTOR;
delta_ry = -rotation_speed * DIAGONAL_FACTOR;
delta_rx = rotation_speed * DIAGONAL_FACTOR;
break;
case DOWN_RIGHT:
delta_x = movement_speed * DIAGONAL_FACTOR;
delta_z = -movement_speed * DIAGONAL_FACTOR;
delta_ry = rotation_speed * DIAGONAL_FACTOR;
delta_rx = rotation_speed * DIAGONAL_FACTOR;
break;
case NONE:
return;
}
sphere_position.x += delta_x;
sphere_position.z += delta_z;
sphere_rotation.rx += delta_rx;
sphere_rotation.ry += delta_ry;
}
void load_floor_texture(void) {
pos.x = 800.0;
pos.y = 800.0;
pos.z = -35.0;
rot.rx = JO_DEG_TO_RAD(90.0);
rot.ry = JO_DEG_TO_RAD(0.0);
rot.rz = JO_DEG_TO_RAD(0.0);
jo_core_tv_off();
jo_enable_background_3d_plane(JO_COLOR_Black);
jo_tga_8bits_loader(&floor_image, JO_ROOT_DIR, "FLOOR.TGA", 0);
jo_background_3d_plane_a_img(&floor_image, image_pal.id, true, true);
jo_core_tv_on();
}
jo_palette *my_tga_palette_handling(void) {
jo_create_palette(&image_pal);
return (&image_pal);
}
void draw_3d_planes(void) {
jo_3d_push_matrix();
{
jo_3d_rotate_matrix_rad(rot.rx, rot.ry, rot.rz);
jo_3d_translate_matrixf(pos.x, pos.y, pos.z);
jo_background_3d_plane_a_draw(true);
}
jo_3d_pop_matrix();
}
void jo_main(void) {
jo_core_init(JO_COLOR_Black);
jo_set_tga_palette_handling(my_tga_palette_handling);
jo_sprite_add_tga(JO_ROOT_DIR, "ROCK.TGA", JO_COLOR_Transparent);
load_floor_texture();
jo_3d_camera_init(&cam);
jo_core_add_callback(my_draw);
jo_core_add_callback(my_gamepad);
jo_core_add_callback(draw_3d_planes);
jo_core_run();
}
结果是:
如您所见,当我向左或向右移动游戏手柄时,低多边形球体并没有像球一样旋转。相反,它似乎笨拙地旋转或绕错误的轴旋转。
如何使用 Jo Engine 正确实现球体的旋转,使其根据游戏手柄输入像滚球一样以正确的方向平滑旋转?
不是一个大问题,您只需将 Y 旋转与 Z 旋转切换即可。为了在地面上旋转球(X/Z 轴),您不想使用垂直轴(在本例中为 Y 轴)。这是一个更改后的版本,以反映我之前提到的更改。没有太多改变,我只是将
delta_ry
重命名为 delta_rz
并将其添加到末尾的右侧向量元素中。
void my_gamepad(void) {
const float movement_speed = 1.0f;
const float rotation_speed = JO_DEG_TO_RAD(5.0f);
const float DIAGONAL_FACTOR = 0.707f; //(1/sqrt(2))
float delta_x = 0.0f;
float delta_z = 0.0f;
float delta_rx = 0.0f;
float delta_rz = 0.0f;
switch (jo_get_input_direction_pressed(0))
{
case LEFT:
delta_x = -movement_speed;
delta_rz = rotation_speed;
break;
case RIGHT:
delta_x = movement_speed;
delta_rz = -rotation_speed;
break;
case UP:
delta_z = movement_speed;
delta_rx = -rotation_speed;
break;
case DOWN:
delta_z = -movement_speed;
delta_rx = rotation_speed;
break;
case UP_LEFT:
delta_x = -movement_speed * DIAGONAL_FACTOR;
delta_z = movement_speed * DIAGONAL_FACTOR;
delta_rz = rotation_speed * DIAGONAL_FACTOR;
delta_rx = -rotation_speed * DIAGONAL_FACTOR;
break;
case UP_RIGHT:
delta_x = movement_speed * DIAGONAL_FACTOR;
delta_z = movement_speed * DIAGONAL_FACTOR;
delta_rz = -rotation_speed * DIAGONAL_FACTOR;
delta_rx = -rotation_speed * DIAGONAL_FACTOR;
break;
case DOWN_LEFT:
delta_x = -movement_speed * DIAGONAL_FACTOR;
delta_z = -movement_speed * DIAGONAL_FACTOR;
delta_rz = rotation_speed * DIAGONAL_FACTOR;
delta_rx = rotation_speed * DIAGONAL_FACTOR;
break;
case DOWN_RIGHT:
delta_x = movement_speed * DIAGONAL_FACTOR;
delta_z = -movement_speed * DIAGONAL_FACTOR;
delta_rz = -rotation_speed * DIAGONAL_FACTOR;
delta_rx = rotation_speed * DIAGONAL_FACTOR;
break;
case NONE:
return;
}
sphere_position.x += delta_x;
sphere_position.z += delta_z;
sphere_rotation.rx += delta_rx;
sphere_rotation.rz += delta_rz;
}