C语言 如何使月球登陆车游戏的移动在一个320x240显示器的嵌入式系统上更流畅?

o2g1uqev  于 2022-12-22  发布在  其他
关注(0)|答案(1)|浏览(127)

我在一个嵌入式系统上用C语言制作了一个月球登陆器游戏,我们有一个相当简单的运动矢量。它还没有完成,但是我遇到了一个问题,登陆器本身的运动看起来很不稳定,我相信这是因为我使用的显示驱动程序只允许传入int,以便绘图。
我现在的逻辑是给盒子的位置加上一个速度值,每一个滴答声本质上就是给加速度加上一个加速度常数,加速度常数加到加到盒子的位置上,这使得重力可以不断地把盒子拉下来,同时也使得垂直和水平推力可以根据cos和sin值加上,cos和sin值是从着陆器的Angular 计算出来的。
这里有一个链接到我的系统(很抱歉质量很差,我从来没有发布到YouTube)https://youtube.com/shorts/NVvTxVoZjY4
所有的代码是非常大的,但我会张贴部分,我认为是相关的。

#include "game_control.h"
#include "buttons.h"
#include "display.h"
#include "stdio.h"
#include "lander.h"

#define THRUST_SCALER 0.3

int16_t x0 = -10;
int16_t y_point0 = 0;
int16_t x1 = 0;
int16_t y_point1 = 0;
int16_t x2 = 0;
int16_t y2 = 10;
int16_t x3 = -10;
int16_t y3 = 10;
int16_t x_origin = 0;
int16_t y_origin = 120;
#define gravity 0.05
double y_velocity = 0.9;
double x_velocity = 1;
bool tick_is_odd = true;
int8_t tick_fourth = 0;
int8_t rotate = 0;

double thrust_x = 0.;
double thrust_y = 0.;

struct lander_t the_lander;

void map1() {
  display_drawLine(0, 240, 100, 200, DISPLAY_WHITE);
  display_drawLine(100, 200, 160, 220, DISPLAY_WHITE);
  display_drawLine(160, 220, 190, 220, DISPLAY_DARK_YELLOW);
  display_drawLine(190, 220, 300, 160, DISPLAY_WHITE);
  display_drawLine(300, 160, 320, 240, DISPLAY_WHITE);
}

// Tick the game control logic
//
// This function should tick the lander and check for wins on the game
void gameControl_tick() {

  uint8_t button_value = buttons_read();
  printf("vertical velocity: %f\n", y_velocity);
  printf("horizontal velocity: %f\n\n", x_velocity);
  

  if((button_value & BUTTONS_BTN0_MASK) == BUTTONS_BTN0_MASK){
    lean_right(&the_lander);

  } else if ((button_value & BUTTONS_BTN3_MASK) == BUTTONS_BTN3_MASK){
    lean_left(&the_lander);

  }



  //testing rotations given preset rotation values
  if (y_point0 <= 230) {
    display_drawLine(x0, y_point0, x1, y_point1, DISPLAY_BLACK);
    display_drawLine(x1, y_point1, x2, y2, DISPLAY_BLACK);
    display_drawLine(x2, y2, x3, y3, DISPLAY_BLACK);
    display_drawLine(x3, y3, x0, y_point0, DISPLAY_BLACK);
    display_drawPixel(x0, y_point0, DISPLAY_BLACK);
    y_point0 = y_point0 + (int)y_velocity;
    y_point1 = y_point1 + (int)y_velocity;
    y2 = y2 + (int)y_velocity;
    y3 = y3 + (int)y_velocity;
    x0 = x0 + x_velocity;
    x1 = x1 + x_velocity;
    x2 = x2 + x_velocity;
    x3 = x3 + x_velocity;
    if (tick_fourth == 1) {
      tick_fourth = 0;
      // if statements to turn left
      if (((button_value & BUTTONS_BTN0_MASK) == BUTTONS_BTN0_MASK) &&
          (rotate == 0)) {
        x0 = x0 + 3;
        y_point0 = y_point0 - 1;
        x1 = x1 + 1;
        y_point1 = y_point1 + 3;
        x2 = x2 - 3;
        y2 = y2 + 1;
        x3 = x3 - 1;
        y3 = y3 - 3;
        rotate++;
      } else if (((button_value & BUTTONS_BTN0_MASK) == BUTTONS_BTN0_MASK) &&
                 (rotate == 1)) {
        x0 = x0 + 2;
        y_point0 = y_point0 - 1;
        x1 = x1 + 1;
        y_point1 = y_point1 + 2;
        x2 = x2 - 2;
        y2 = y2 + 1;
        x3 = x3 - 1;
        y3 = y3 - 2;
        rotate++;
      } else if (((button_value & BUTTONS_BTN0_MASK) == BUTTONS_BTN0_MASK) &&
                 (rotate == 2)) {
        x0 = x0 + 2;
        y_point0 = y_point0 + 1;
        x1 = x1 - 1;
        y_point1 = y_point1 + 2;
        x2 = x2 - 2;
        y2 = y2 - 1;
        x3 = x3 + 1;
        y3 = y3 - 2;
        rotate++;
      } else if (((button_value & BUTTONS_BTN0_MASK) == BUTTONS_BTN0_MASK) &&
                 (rotate == 3)) {
        x0 = x0 + 3;
        y_point0 = y_point0 + 1;
        x1 = x1 - 1;
        y_point1 = y_point1 + 3;
        x2 = x2 - 3;
        y2 = y2 - 1;
        x3 = x3 + 1;
        y3 = y3 - 3;
        rotate++;
      } else if (((button_value & BUTTONS_BTN0_MASK) == BUTTONS_BTN0_MASK) &&
                 (rotate == -1)) {
        x0 = x0 + 1;
        y_point0 = y_point0 - 3;
        x1 = x1 + 3;
        y_point1 = y_point1 + 1;
        x2 = x2 - 1;
        y2 = y2 + 3;
        x3 = x3 - 3;
        y3 = y3 - 1;
        rotate++;
      } else if (((button_value & BUTTONS_BTN0_MASK) == BUTTONS_BTN0_MASK) &&
                 (rotate == -2)) {
        x0 = x0 + 1;
        y_point0 = y_point0 - 2;
        x1 = x1 + 2;
        y_point1 = y_point1 + 1;
        x2 = x2 - 1;
        y2 = y2 + 2;
        x3 = x3 - 2;
        y3 = y3 - 1;
        rotate++;
      } else if (((button_value & BUTTONS_BTN0_MASK) == BUTTONS_BTN0_MASK) &&
                 (rotate == -3)) {
        x0 = x0 - 1;
        y_point0 = y_point0 - 2;
        x1 = x1 + 2;
        y_point1 = y_point1 - 1;
        x2 = x2 + 1;
        y2 = y2 + 2;
        x3 = x3 - 2;
        y3 = y3 + 1;
        rotate++;
      } else if (((button_value & BUTTONS_BTN0_MASK) == BUTTONS_BTN0_MASK) &&
                 (rotate == -4)) {
        x0 = x0 - 1;
        y_point0 = y_point0 - 3;
        x1 = x1 + 3;
        y_point1 = y_point1 - 1;
        x2 = x2 + 1;
        y2 = y2 + 3;
        x3 = x3 - 3;
        y3 = y3 + 1;
        rotate++;
      }

      // turn right calculations:
      else if (((button_value & BUTTONS_BTN3_MASK) == BUTTONS_BTN3_MASK) &&
               (rotate == 1)) {
        x0 = x0 - 3;
        y_point0 = y_point0 + 1;
        x1 = x1 - 1;
        y_point1 = y_point1 - 3;
        x2 = x2 + 3;
        y2 = y2 - 1;
        x3 = x3 + 1;
        y3 = y3 + 3;
        rotate--;
      } else if (((button_value & BUTTONS_BTN3_MASK) == BUTTONS_BTN3_MASK) &&
                 (rotate == 2)) {
        x0 = x0 - 2;
        y_point0 = y_point0 + 1;
        x1 = x1 - 1;
        y_point1 = y_point1 - 2;
        x2 = x2 + 2;
        y2 = y2 - 1;
        x3 = x3 + 1;
        y3 = y3 + 2;
        rotate--;
      } else if (((button_value & BUTTONS_BTN3_MASK) == BUTTONS_BTN3_MASK) &&
                 (rotate == 3)) {
        x0 = x0 - 2;
        y_point0 = y_point0 - 1;
        x1 = x1 + 1;
        y_point1 = y_point1 - 2;
        x2 = x2 + 2;
        y2 = y2 + 1;
        x3 = x3 - 1;
        y3 = y3 + 2;
        rotate--;
      } else if (((button_value & BUTTONS_BTN3_MASK) == BUTTONS_BTN3_MASK) &&
                 (rotate == 4)) {
        x0 = x0 - 3;
        y_point0 = y_point0 - 1;
        x1 = x1 + 1;
        y_point1 = y_point1 - 3;
        x2 = x2 + 3;
        y2 = y2 + 1;
        x3 = x3 - 1;
        y3 = y3 + 3;
        rotate--;
      } else if (((button_value & BUTTONS_BTN3_MASK) == BUTTONS_BTN3_MASK) &&
                 (rotate == 0)) {
        x0 = x0 - 1;
        y_point0 = y_point0 + 3;
        x1 = x1 - 3;
        y_point1 = y_point1 - 1;
        x2 = x2 + 1;
        y2 = y2 - 3;
        x3 = x3 + 3;
        y3 = y3 + 1;
        rotate--;
      } else if (((button_value & BUTTONS_BTN3_MASK) == BUTTONS_BTN3_MASK) &&
                 (rotate == -1)) {
        x0 = x0 - 1;
        y_point0 = y_point0 + 2;
        x1 = x1 - 2;
        y_point1 = y_point1 - 1;
        x2 = x2 + 1;
        y2 = y2 - 2;
        x3 = x3 + 2;
        y3 = y3 + 1;
        rotate--;
      } else if (((button_value & BUTTONS_BTN3_MASK) == BUTTONS_BTN3_MASK) &&
                 (rotate == -2)) {
        x0 = x0 + 1;
        y_point0 = y_point0 + 2;
        x1 = x1 - 2;
        y_point1 = y_point1 + 1;
        x2 = x2 - 1;
        y2 = y2 - 2;
        x3 = x3 + 2;
        y3 = y3 - 1;
        rotate--;
      } else if (((button_value & BUTTONS_BTN3_MASK) == BUTTONS_BTN3_MASK) &&
                 (rotate == -3)) {
        x0 = x0 + 1;
        y_point0 = y_point0 + 3;
        x1 = x1 - 3;
        y_point1 = y_point1 + 1;
        x2 = x2 - 1;
        y2 = y2 - 3;
        x3 = x3 + 3;
        y3 = y3 - 1;
        rotate--;
      }
    }

    display_drawLine(x0, y_point0, x1, y_point1, DISPLAY_CYAN);
    display_drawLine(x1, y_point1, x2, y2, DISPLAY_CYAN);
    display_drawLine(x2, y2, x3, y3, DISPLAY_CYAN);
    display_drawLine(x3, y3, x0, y_point0, DISPLAY_CYAN);
    display_drawPixel(x0, y_point0, DISPLAY_YELLOW);

//this is where the velocities are actually being incremented given the calculated thrust values.
    y_velocity = y_velocity + gravity - (THRUST_SCALER *thrust_y);
    x_velocity = x_velocity + (THRUST_SCALER * thrust_x);
    
  }

  //change thrust value if button 1 is being pressed
  if((button_value & BUTTONS_BTN1_MASK) == BUTTONS_BTN1_MASK){
    thrust_x = get_thrust_x(&the_lander);
    thrust_y = get_thrust_y(&the_lander);
  } else {
    thrust_x = 0;
    thrust_y = 0;
  }
  tick_is_odd = !tick_is_odd;
  tick_fourth++;
}

请原谅糟糕的编码实践,我还在测试概念。
这是着陆器的结构是如何实现的。

void lander_init(struct lander_t *lander){
    lander->angle = 90;
//there going to be more values here, location etc, but I haven't implemented them yet.

}

这是推力和Angular 的计算方法。

static double cos_degrees(double theta){
    
    //convert radians to degrees
    theta = theta * (3.14 / 180);
    // printf("cos_degrees %f\n", cos(theta));
    return cos(theta);

}

static double sin_degrees(double theta){
    
    //convert radians to degrees
    theta = theta * (3.14 / 180);
    // printf("sin_degrees %f\n", sin(theta));
    return sin(theta);

}

//calculates the x and y thrust values given the current angle
double get_thrust_y(struct lander_t *lander){
    return sin_degrees(lander->angle);
}

double get_thrust_x(struct lander_t *lander){
    return cos_degrees(lander->angle);
}

//increment the angle 
void lean_left(struct lander_t *lander){
    if(lander->angle < 180){
    lander->angle += 10;
    }
}

//decrement the angle
void lean_right(struct lander_t *lander){
    if(lander->angle > 0){
    lander->angle -= 10;
    }
}

任何建议都将不胜感激!谢谢你的帮助!还有人遇到过类似的问题吗,他们在这样的屏幕上的加速度总是离散的?
下面是我正在使用的显示驱动程序的github链接。https://github.com/byu-cpe/ecen330_student/blob/main/include/display.h
我试过改变游戏的滴答速度,试图让它不那么明显,但我不满意。
我在想,我可以创建一些帮助绘图的函数,它可以接受当前的加速度或速度值,并以某种方式将它们绘制得更平滑,但我还没有能够想清楚它是如何工作的。

6tdlim6h

6tdlim6h1#

我可以通过改变控制游戏的状态机的频率来减慢移动速度。所以对于0到1之间的速度,我可以通过每4次、每3次或每隔1次等等来创建3个速度。这让我可以让移动速度更慢,看起来更像模拟,而不是总是添加离散像素。因为你仍然添加了一个像素的位置,但你只添加了一半的频率,而不是试图增加每一次。
如果有什么不明白的地方或者其他人有其他问题,请告诉我。

相关问题