大家好!最近在学习一些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 轴上的位置。