5

对于 Gameboy 编程中的游戏,我使用了四个名为topoldTopbottom的数组oldBottom

struct Point { int x, y; };
struct Rect  { struct Point xx, yy; };

Rect top[size], oldTop[size];
Rect bottom[size], oldBottom[i];

其中 Rect 是由两个结构点组成的结构,左上角点和右下角点。

游戏的想法是让随机高度的方块从天花板上向下,从地板上向下。它类似于直升机经典游戏。在我的无限 while 循环中,我使用以下代码将所有矩形向下移动一个像素

while (1)
{
    for (int i = 0; i < size; i++)
    {
        //in Struct Rect, xx is the top-left corner point, and yy is the bottom right
        top[i].xx.x--;
        top[i].yy.x--;
        bottom[i].xx.x--;
        bottom[i].yy.x--;

        if (top[i].xx.x < 0)
        {
            top[i].xx.x += 240;
            top[i].yy.x += 240;
        }

        if (bottom[i].xx.x < 0)
        {
            bottom[i].xx.x += 240;
            bottom[i].yy.x += 240;
        }
    }

    for (int i = 0; i < size; i++)
    {
        drawRect(oldTop[i], colorBlack);
        drawRect(oldBottom[i], colorBlack);
    }

    /*call delay function that wait for Vertical Blank*/
    for(int i = 0; i < size; i++)
    {
        drawRect(top[i], colorGreen);
        drawRect(bottom[i], colorGreen);
        oldTop[i] = top[i];
        oldBottom[i] = bottom[i];
    }
}

drawRect 方法使用 DMA 来绘制矩形。

使用此代码,代码应显示如下矩形:(在油漆中绘制) 在此处输入图像描述

但我得到的结果是

在此处输入图像描述

奇怪的是,如果我根本不画底行,那么顶行画得很好。当我画两者时,结果只会变得混乱。这真的很奇怪,因为我认为代码应该可以正常工作,并且代码不是很复杂。发生这种情况是否有特定原因,有没有办法解决这个问题?

谢谢。

我用来绘制矩形的代码如下所示:

void drawRect(int row, int col, int width, int height){
    int i;
for (i=0; i<height; i++)
{
    DMA[3].src = &color;
        DMA[3].dst = videoBuffer + (row+r)*240 +  col);
    DMA[3].cnt = DMA_ON | DMA_FIXED_SOURCE | width;
}
}
4

1 回答 1

4

这是一个基于您的代码的调试 SSCCE(简短、独立、正确的示例)。此代码中有触发的断言;它运行,但已知不正确。我已重命名bottombtmoldBottomoldBtm使名称是对称的;它使代码布局更加系统化(但在其他方面无关紧要)。

#include <assert.h>
#include <stdio.h>

typedef struct Point { int x, y; } Point;
typedef struct Rect  { struct Point xx, yy; } Rect;
enum { size = 2 };
typedef enum { colourGreen = 0, colourBlack = 1 } Colour;

/*ARGSUSED*/
static void drawRect(Rect r, Colour c)
{
    printf(" (%3d)(%3d)", r.xx.x, r.yy.x);
}

int main(void)
{
    Rect top[size], oldTop[size];
    Rect btm[size], oldBtm[size];
    int counter = 0;

    for (int i = 0; i < size; i++)
    {
        top[i].xx.x = 240 -  4 * i;
        top[i].xx.y =   0 + 10 + i;
        top[i].yy.x = 240 - 14 * i;
        top[i].yy.y =   0 + 20 + i;
        btm[i].xx.x =   0 + 72 * i;
        btm[i].xx.y =   0 + 10 * i;
        btm[i].yy.x =   0 + 12 * i;
        btm[i].yy.y =   0 + 20 * i;
        oldTop[i] = top[i];
        oldBtm[i] = btm[i];
    }

    while (1)
    {
        if (counter++ > 480)  // Limit amount of output!
            break;
        for (int i = 0; i < size; i++)
        {
            //in Struct Rect, xx is the top-left corner point, and yy is the bottom right
            top[i].xx.x--;
            top[i].yy.x--;
            btm[i].xx.x--;
            btm[i].yy.x--;

            if (top[i].xx.x < 0)
            {
                top[i].xx.x += 240;
                top[i].yy.x += 240;
            }

            if (btm[i].xx.x < 0)
            {
                btm[i].xx.x += 240;
                btm[i].yy.x += 240;
            }
        }

        for (int i = 0; i < size; i++)
        {
            assert(top[i].xx.x >= 0 && top[i].yy.x >= 0);
            assert(btm[i].xx.x >= 0 && btm[i].yy.x >= 0);
        }

        for (int i = 0; i < size; i++)
        {
            drawRect(oldTop[i], colourBlack);
            drawRect(oldBtm[i], colourBlack);
        }

        /*call delay function that wait for Vertical Blank*/
        for(int i = 0; i < size; i++)
        {
            drawRect(top[i], colourGreen);
            drawRect(btm[i], colourGreen);
            oldTop[i] = top[i];
            oldBtm[i] = btm[i];
        }
        putchar('\n');
    }
    return(0);
}

正如后期评论中所指出的,这与您的代码之间的一个很大区别是oldBottom您的代码中声明为:

Rect top[size], oldTop[size];
Rect bottom[size], oldBottom[i];

使用大小i而不是size. 这可能是您看到的数组覆盖问题的原因。

但是还有第二个问题;中间火循环中的断言:

 (240)(240) (  0)(  0) (236)(226) ( 72)( 12) (239)(239) (239)(239) (235)(225) ( 71)( 11)
 (239)(239) (239)(239) (235)(225) ( 71)( 11) (238)(238) (238)(238) (234)(224) ( 70)( 10)
 (238)(238) (238)(238) (234)(224) ( 70)( 10) (237)(237) (237)(237) (233)(223) ( 69)(  9)
 (237)(237) (237)(237) (233)(223) ( 69)(  9) (236)(236) (236)(236) (232)(222) ( 68)(  8)
 (236)(236) (236)(236) (232)(222) ( 68)(  8) (235)(235) (235)(235) (231)(221) ( 67)(  7)
 (235)(235) (235)(235) (231)(221) ( 67)(  7) (234)(234) (234)(234) (230)(220) ( 66)(  6)
 (234)(234) (234)(234) (230)(220) ( 66)(  6) (233)(233) (233)(233) (229)(219) ( 65)(  5)
 (233)(233) (233)(233) (229)(219) ( 65)(  5) (232)(232) (232)(232) (228)(218) ( 64)(  4)
 (232)(232) (232)(232) (228)(218) ( 64)(  4) (231)(231) (231)(231) (227)(217) ( 63)(  3)
 (231)(231) (231)(231) (227)(217) ( 63)(  3) (230)(230) (230)(230) (226)(216) ( 62)(  2)
 (230)(230) (230)(230) (226)(216) ( 62)(  2) (229)(229) (229)(229) (225)(215) ( 61)(  1)
 (229)(229) (229)(229) (225)(215) ( 61)(  1) (228)(228) (228)(228) (224)(214) ( 60)(  0)
Assertion failed: (btm[i].xx.x >= 0 && btm[i].yy.x >= 0), function main, file video.c, line 63.

我认为您的“非负面”检查应修改为:

            if (top[i].xx.x < 0)
                top[i].xx.x += 240;
            if (top[i].yy.x < 0)
                top[i].yy.x += 240;

            if (btm[i].xx.x < 0)
                btm[i].xx.x += 240;
            if (btm[i].yy.x < 0)
                btm[i].yy.x += 240;

这阻止了任何消极的事情。但是,您应该简单地使用原始块检查右下角的 x 坐标(而不是左上角的坐标),这是完全合理的。或者,环绕可能需要更复杂。那是你来破译的。但我认为出现奇怪的显示是因为您在不打算也不应该提供的地方提供了负值。

这里需要注意的关键点是:

  1. 在调试算法时,您不必使用正常的显示机制。
  2. 调试时,尽可能减小循环大小 ( size == 2)。
  3. 仅打印相关信息(此处为 x 坐标)有助于减少输出。
  4. 使用计数器代码来限制输出量可以简化事情。
  5. 如果出现问题,请尽早寻找问题的模式。

drawRect()在我得到所示设计之前,我有各种版本的函数,它在宽屏幕(例如 120x65)终端窗口上运行良好。

于 2013-03-31T23:47:16.690 回答