2012-03-04 20 views
0

我想製作一個將在像素網格上繪製線條,然後繪製到位圖上的東西。我可以(非常)通過用'new'重新分配內存來獲得我想要的效果(儘管數組要大到刪除[],所以最終導致內存泄漏)。將數組的所有點設置爲0,對重新分配動態內存有不同的影響

我的問題是,我不能爲我的生活,工作,爲什麼這樣做:

for (register unsigned int i = 0; i < WIDTH + HEIGHT * 4; i++) 
{ 
    previewedPixels[i] = 0; 
} 

比做

previewedPixels = new sf::Uint8[WIDTH * HEIGHT * 4]; 

這是代碼的其餘部分不同的效果,以透視(重新分配內存並導致內存泄漏的行被評論)。請原諒的混亂:對

#include <SFML/Graphics.hpp> 
#include <SFML/System.hpp> 
#include <vector> 
#include <iostream> 

#define WIDTH 800 
#define HEIGHT 600 

class element 
{ 
public: 
    unsigned char value; 
    unsigned char red; 
    unsigned char green; 
    unsigned char blue; 
}; 

const int WIDTHxHEIGHT = WIDTH * HEIGHT; 
std::vector< std::vector<short> >XandY(WIDTHxHEIGHT * 2, std::vector<short>(2, 0));          //This is the x and y values for the arrays below 
sf::Uint8 *mainPixels  = new sf::Uint8[WIDTH * HEIGHT * 4]; 
sf::Uint8 *previewedPixels = new sf::Uint8[WIDTH * HEIGHT * 4]; //Previewed pixel co-  ordinates 
sf::Uint8 *pixels   = new sf::Uint8[WIDTH * HEIGHT * 4]; //Put the preview and  main pixel grids together on this 
element *currentElement; //Value of the element currently selected 
/*****Declare Elements Here*****/ 

element metal; 

void elementInit() 
{ 
    metal.value = 1; 
    metal.blue  = 90; 
    metal.red  = 90; 
    metal.green = 90; 
} 

inline void wipe() 
{ 
    for (register unsigned int i = 0; i < WIDTH + HEIGHT * 4; i++) 
    { 
     previewedPixels[i] = 0; 
    } 
} 

inline void draw(short x, short y, unsigned char r, unsigned char g, unsigned char b,  bool preview) 
{ 
    if (preview) 
    { 
     previewedPixels[(x + WIDTH * y) * 4 + 0] = r; 
     previewedPixels[(x + WIDTH * y) * 4 + 1] = g; 
     previewedPixels[(x + WIDTH * y) * 4 + 2] = b; 
     previewedPixels[(x + WIDTH * y) * 4 + 3] = 255; 
    } 
    else 
    { 
     mainPixels[(x + WIDTH * y) * 4 + 0] = r; 
     mainPixels[(x + WIDTH * y) * 4 + 1] = g; 
     mainPixels[(x + WIDTH * y) * 4 + 2] = b; 
     mainPixels[(x + WIDTH * y) * 4 + 3] = 255; 
    } 
} 

void display(void *UserData) 
{ 

} 

void lineDraw(short x1, short y1, short x2, short y2, bool preview) 
{ 
    short xDiff = std::abs(x1 - x2); //Difference between the two 'x' co-ordinates 
    short yDiff = std::abs(y1 - y2); //and the two y co-ordinates 
    unsigned char red, green, blue; 
    red = currentElement->blue; 
    green = currentElement->green; 
    blue = currentElement->blue; 

    if (xDiff > yDiff && x1 < x2) //Which quadrant it's in. This one is horizontal  going right 
    { 
     if (preview)  //If it is a preview then then put it onto a different array  of mainPixels 
     { 
      for (short i = x1; i <= x2; i++) 
       draw(i, y1, red, green, blue, true); 
     } 
     else    //If it's not a preview then just go ahaid on the normal  array 
     { 
      for (short i = x1; i <= x2; i++) 
       draw(i, y1, red, green, blue, false); 
     } 
    } 
    else if (xDiff > yDiff && x1 > x2) //Horizontal going left 
    { 
     if (preview) 
     { 
      for (short i = x1; i >= x2; i--) 
       draw(i, y1, red, green, blue, true); 
     } 
     else 
     { 
      for (short i = x1; i >= x2; i--) 
       draw(i, y1, red, green, blue, false); 
     } 
    } 
    else if (xDiff < yDiff && y1 > y2) //Going down 
    { 
     if (preview) 
     { 
      for (short i = y1; i >= y2; i--) 
       draw(x1, i, red, green, blue, true); 
     } 
     else 
     { 
      for (short i = y1; i >= y2; i--) 
       draw(x1, i, red, green, blue, false); 
     } 
    } 
    else if (xDiff < yDiff && y1 < y2) //Going Up 
    { 
     if (preview) 
     { 
      for (short i = y1; i <= y2; i++) 
       draw(x1, i, red, green, blue, true); 
     } 
     else 
     { 
      for (short i = y1; i <= y2; i++) 
       draw(x1, i, red, green, blue, false); 
     } 
    } 
} 


int main() 
{ 
    //Inititialization stuff 
    for (unsigned int i = 0; i < WIDTHxHEIGHT * 2; i++) 
    { 
     XandY[i][0] = i % WIDTH; 
     XandY[i][1] = i/WIDTH; 
    } 
    elementInit(); //Initialize the Elements with their values 
    currentElement = &metal; //By default, select metal 
    sf::RenderWindow App(sf::VideoMode(WIDTH, HEIGHT, 32), "ElectroToy"); 
    sf::Thread graphics(&display, &App); //Create the thread that will deal with the  graphics 
    graphics.Launch();  //Launch Graphics thread 
    sf::Image screen(WIDTH, HEIGHT); 
    sf::Sprite sprite, prevSprite; //The first one is the main picture, the other is  the one for the preview mainPixels 
    sf::Event Event; 
    const sf::Input & Input = App.GetInput(); 
    short mouseX = Input.GetMouseX(); 
    short mouseY = Input.GetMouseY(); 
    short oldMouseX = mouseX; 
    short oldMouseY = mouseY; 
    bool running = true; 
    //End of Initialization stuff 
    while (running)     //main loop 
    { 
     mouseX = Input.GetMouseX(); 
     mouseY = Input.GetMouseY(); 
    bool leftMouseDown = Input.IsMouseButtonDown(sf::Mouse::Left); 
    bool rightMouse = Input.IsMouseButtonDown(sf::Mouse::Right); 
    bool LShift = Input.IsKeyDown(sf::Key::LShift); 
     while (App.GetEvent(Event)) 
     { 
      if (Event.Type == sf::Event::Closed) 
      { 
       App.Close(); 
       running = false; 
      } 
     } 
     if (leftMouseDown) 
     { 
      oldMouseX = mouseX;  //Remember the X,Y co-ordinates when the button was  pressed 
      oldMouseY = mouseY; 
      while (leftMouseDown) 
      { 
       while (App.GetEvent(Event)); //recieve events so it doesn't get stuck  in an infinite loop 
       leftMouseDown = Input.IsMouseButtonDown(sf::Mouse::Left); //update mouse button status 
       mouseX = Input.GetMouseX(); 
       mouseY = Input.GetMouseY(); 
       lineDraw(oldMouseX, oldMouseY, mouseX, mouseY, true); 

       for (register unsigned int i = 0; i < WIDTHxHEIGHT * 4; i++) //Combine  the two pixel arrays to create what will go on the screen 
       { 
        pixels[i] = mainPixels[i]; 
        pixels[i] = previewedPixels[i]; 
       } 
       wipe(); 
       //previewedPixels = new sf::Uint8[WIDTH * HEIGHT * 4]; 
       screen.LoadFromPixels(WIDTH, HEIGHT, pixels); 
       sprite.SetImage(screen); 
       App.Clear(); 
       App.Draw(sprite); 
       App.Display(); 
      } 
      lineDraw(oldMouseX, oldMouseY, mouseX, mouseY, false); 
     } 
     oldMouseX = mouseX; 
     oldMouseY = mouseY; 
     screen.LoadFromPixels(WIDTH, HEIGHT, mainPixels); 
     sprite.SetImage(screen); 
     App.Clear(); 
     App.Draw(sprite); 
     App.Display(); 
    } 
} 
+3

「*太大刪除*」什麼? – Pubby 2012-03-04 04:49:31

+0

當我第一次發現它時,我也感到困惑。顯然刪除[]不能刪除大於65536(我認爲)的字節。 – Jalfor 2012-03-04 05:00:29

回答

3

好,

for (register unsigned int i = 0; i < WIDTH + HEIGHT * 4; i++) 

使用從

previewedPixels = new sf::Uint8[WIDTH * HEIGHT * 4]; 

不同的是,它的邊界?

+0

哦,我覺得很愚蠢。哈哈。謝謝:) – Jalfor 2012-03-04 04:58:03

+0

沒有看到自己的拼寫錯誤是很常見的。如果你不再邀請第二雙眼睛去尋找它們,那隻會覺得很蠢。 – 2012-03-04 05:05:52

0

幾十年來編譯器忽略register關鍵字。無論如何,我會建議memset:

memset(previewedPixels, 0, WIDTH * HEIGHT * 4);