0

大家好!最近在学习一些PSP编程,尝试用pspdisplay.h库做一个小游戏。游戏非常基础,目前只有一个红色方块四处移动,屏幕上出现了一些十字形的东西。一切都很顺利,直到我注意到根据我更新和交换帧缓冲区的频率,屏幕上的某个地方会出现一个区域?其中所有输出的对象往往会闪烁。该区域的宽度均为 480 像素,高度为 10-20 像素。该区域在 Y 轴上的位置取决于帧缓冲区更新的频率。如何解决?是什么原因造成的?为什么区域位置取决于帧缓冲区的更新频率?PS如果你想看它的视频,这里是我的reddit问题的链接,关于固定到它的视频的相同问题:https://www.reddit.com/r/PSP/comments/mccjp4/been_studying_some_psp_programming_recently_and/?utm_source=share&utm_medium=web2x&context=3

要重现此问题,您需要 PSP 3000、psptoolchain 和 pspsdk。

我有一个小的 Cell 结构,它包含一个 8x8 正方形左上角的坐标、它的颜色和方向,即上、下、左、右或无:

struct Cell{

    uint32_t color;

    int x;
    int y;

    directions direction;

    bool occupied;

    inline Cell();

    inline Cell(uint32_t, int, int, bool, directions);

    ~Cell();
}; 

之后,我初始化 PSP 屏幕并控制并启动一个循环,该循环一直运行到用户按下 START 按钮。在控制检查之后,时间检查是否已经过了所需的毫秒数,将正方形沿其方向移动一个像素。

while(running){

        running = is_running();

        sceCtrlPeekBufferPositive(&button_input, 1);
        if(button_input.Buttons != 0){
            if(button_input.Buttons & PSP_CTRL_UP){
                cl.direction = directions::up;
            }
            if(button_input.Buttons & PSP_CTRL_DOWN){
                cl.direction = directions::down;
            }
            if(button_input.Buttons & PSP_CTRL_LEFT){
                cl.direction = directions::left;
            }
            if(button_input.Buttons & PSP_CTRL_RIGHT){
                cl.direction = directions::right;
            }
            if(button_input.Buttons & PSP_CTRL_START){
                running = 0;

            }
        }

        if(current_timestamp() - lmt >= 40){
              clear(0xff000);
              switch(cl.direction){
                  case directions::up: 
                      cl.y--;
                      break;
                  case directions::down:
                      cl.y++;
                      break;
                  case directions::left:
                      cl.x--;
                      break;
                  case directions::none:
                      break;
                  case directions::right:
                      cl.x++;
               }

        }
        draw_cell(cl);
        swap_buffers();
        sceDisplayWaitVblank();
        lmt = current_timestamp();
}       

draw_cell(Cell cl) 函数只是将一个单元格写入绘图缓冲区。swap_buffers() 函数通过将我的方块输出到屏幕上来交换绘图缓冲区和显示缓冲区。clear 函数只是用一种颜色填充绘图缓冲区,作为它的参数。

void draw_cell(Cell cl){
    for(int y = cl.y; y < cl.y+8; y++){
        for(int x = cl.x; x < cl.x+8; x++){
            draw_buffer[x + y * 512] = cl.color;
        }
    }

}

void clear(uint32_t color){
    for(int i = 0; i < 512 * 272; i++){
        draw_buffer[i] = color;
    }   
}

void swap_buffers(){
        uint32_t* temp = disp_buffer;
        disp_buffer = draw_buffer;
        draw_buffer = temp;

        sceKernelDcacheWritebackInvalidateAll();
        sceDisplaySetFrameBuf(disp_buffer, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_IMMEDIATE);
    }

使用此代码,您将能够重新创建我的问题(您还需要初始化显示和控件,并设置退出回调以使程序工作,当然,创建一个 Cell 类型的对象,称为 cl)。要在程序运行时注意问题,请在屏幕上移动你的方块并观察它。最终你会偶然发现屏幕上的一个区域,你的方块会在那里闪烁。离开该区域将使闪烁停止,再次进入该区域将再次开始闪烁。如果您使用时间检查调整 if() 并更改屏幕更新之间的时间,您会注意到闪烁区域将更改其在 Y 轴上的位置。

4

0 回答 0