gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > A drawing anomaly. Update from previous problems.

#177749 - Skalbe - Sun Jan 27, 2013 2:38 pm

Hi guys. I`m trying to create a game on GBA that would resemble a classic D&D adventure, but I`m already stuck.. just with the basic drawing part of my program. What I have and what I`m trying to do is:
I got a class with variables, a member drawing function, a constructor and later in the main I initialize two objects off of this. I use the function to re-draw my object1 in the while loop and I use the constructor to initialize my both objects just outside of the while loop. The thing is I can`t initialize my variable values within the constructor as one usually would because I use it to draw my both objects, but then I use the function to `move` just one of them. I need to make it so that the function updates my initialized variable values of object1 and redraws it in a new position as I press the buttons. I feel like the problem resides in some faulty logic and I can`t figure it out. Yet I know it can be done. So far I have tried changing around the value increment/decrement with the draw function and also commenting out both FlipBuffers and ClearScreen, but nothing changes. Also the result of this code is my two objects are drawn at their starting positions and I can`t move them. Also hi Adam... if you are here for some reason I feel terribly ashamed for my stupidity, but at the same time I will feel more ashamed if I don`t go and try to understand this.
**********
Code:
#include <stdint.h>
#include <stdlib.h>
#include "gba.h"

// A class with variables for the characters.
class CHARBOX
{
   public:
   int init_;
   int str_;
   int health_;
   int posx_;
   int posy_;
   int width_;
   int height_;
   int colour_;

   public:
   // Constructor.
   CHARBOX(int posx, int posy, int width, int height, int colour)
        : init_(0), str_(0), health_(0), posx_(posx), posy_(posy),
          width_(width), height_(height), colour_(colour)
   {
      DrawBox();
   }
   
   // Drawing functions.
   void DrawBox()
   {
      for (int x = posx_; x < posx_ + width_; x++)
      {
         for (int y = posy_; y < posy_ + height_; y++)
         {
            PlotPixel8(x, y, colour_);
         }
      }
   }
};

// The entry point for the game.
int main()
{
   // Put the display into bitmap mode 4, and enable background 2.
   REG_DISPCNT = MODE4 | BG2_ENABLE;
   
   // Defining some colour palettes.
   SetPaletteBG(1, RGB(90,0,0));
   SetPaletteBG(2, RGB(0,90,0));
   SetPaletteBG(3, RGB(0,0,90));
   SetPaletteBG(4, RGB(90,90,0));
   SetPaletteBG(5, RGB(90,0,90));
   
   // Draw the player dude-box at a starting location.
   CHARBOX player(10, 24, 6, 8, 1);
      
   // Draw the enemy dude-box at a starting location.
   CHARBOX enemy(80, 24, 6, 8, 2);
   
   while (true);
   {
      // Flip buffers to smoothen the drawing.
      FlipBuffers();
      
      // Clear screen and paint background.
      ClearScreen8(1);
      
      // Screen edges.
      if (player.posx_ > (SCREEN_WIDTH - 8))
      {
         player.posx_ = (SCREEN_WIDTH - 8);
      }
      if (player.posx_ < 2)
      {
         player.posx_ = 2;
      }
      if (player.posy_ > (SCREEN_HEIGHT - 6))
      {
         player.posy_ = (SCREEN_HEIGHT - 6);
      }
      if (player.posy_ < 1)
      {
         player.posy_ = 2;
      }
   
      // Redraw the player dude-box.
      if ((REG_KEYINPUT & KEY_LEFT) == 0)
      {
         player.DrawBox();
         player.posx_--;
      }
      
      if ((REG_KEYINPUT & KEY_RIGHT) == 0)
      {
         player.DrawBox();
         player.posx_++;
      }
      
      if ((REG_KEYINPUT & KEY_UP) == 0)
      {
         player.DrawBox();
         player.posy_--;
      }
      
      if ((REG_KEYINPUT & KEY_DOWN) == 0)
      {
         player.DrawBox();
         player.posy_++;
      }
   WaitVSync();
   }
return 0;
}


Last edited by Skalbe on Mon Jan 28, 2013 12:36 am; edited 2 times in total

#177750 - elhobbs - Sun Jan 27, 2013 4:29 pm

this is true when the key is not pressed
Code:
(REG_KEYINPUT & KEY_LEFT) == 0


I think you probably only want to do something when a key is pressed
Code:
(REG_KEYINPUT & KEY_LEFT) != 0

#177751 - Skalbe - Sun Jan 27, 2013 4:59 pm

No, the key logic is fine. I was pointed to the fact that my code didn't actually get to my main loop... because I had a semi-colon after my while...

however now that the original problem is solved my drawing part still has some issues:
The drawing is smooth, but it leaves a trail of the previous positions of the box. I am using the ClearScreen function to set the background once. I moved it out of my while to my main just before the object initialization and I`m using FlipBuffers just at the start of my while loop. I am following my tutorial guides and I believe this should work like this, but it does not.

Edit: To make the trail disappear I believe I should be redrawing the screen every time the loop runs, right? But if I move my ClearScreen function to my while(true) the objects do not appear at their starting positions at the start anymore, because the ClearScreen just clears them away.
This is how the code is now:
Code:

#include <stdint.h>
#include <stdlib.h>
#include "gba.h"

// A class with variables for the characters.
class CHARBOX
{
   public:
   int init_;
   int str_;
   int health_;
   int posx_;
   int posy_;
   int width_;
   int height_;
   int colour_;

   public:
   // Constructor.
   CHARBOX(int posx, int posy, int width, int height, int colour)
        : init_(0), str_(0), health_(0), posx_(posx), posy_(posy),
          width_(width), height_(height), colour_(colour)
   {
      DrawBox();
   }
   
   // Drawing functions.
   void DrawBox()
   {
      for (int x = posx_; x < posx_ + width_; x++)
      {
         for (int y = posy_; y < posy_ + height_; y++)
         {
            PlotPixel8(x, y, colour_);
         }
      }
   }
};

// The entry point for the game.
int main()
{
   // Put the display into bitmap mode 4, and enable background 2.
   REG_DISPCNT = MODE4 | BG2_ENABLE;
   
   // Defining some colour palettes.
   SetPaletteBG(1, RGB(90,0,0));
   SetPaletteBG(2, RGB(0,90,0));
   SetPaletteBG(3, RGB(0,0,90));
   SetPaletteBG(4, RGB(90,90,0));
   SetPaletteBG(5, RGB(90,0,90));
   SetPaletteBG(6, RGB(0,0,0));
   
   // Clear screen and paint background.
   ClearScreen8(4);

   // Draw the player dude-box at a starting location.
   CHARBOX player(10, 24, 6, 8, 1);

   // Draw the enemy dude-box at a starting location.
   CHARBOX enemy(80, 24, 6, 8, 3);
   
   while (true)
   {
      // Flip buffers to smoothen the drawing.
      void FlipBuffers();
      
      // Screen edges.
      if (player.posx_ > (SCREEN_WIDTH - 6))
      {
         player.posx_ = (SCREEN_WIDTH - 6);
      }
      if (player.posx_ < 0)
      {
         player.posx_ = 0;
      }
      if (player.posy_ > (SCREEN_HEIGHT - 8))
      {
         player.posy_ = (SCREEN_HEIGHT - 8);
      }
      if (player.posy_ < 0)
      {
         player.posy_ = 0;
      }
   
      // Redraw the player dude-box.
      if ((REG_KEYINPUT & KEY_LEFT) == 0)
      {
         player.DrawBox();
         player.posx_--;
      }
      
      if ((REG_KEYINPUT & KEY_RIGHT) == 0)
      {
         player.DrawBox();
         player.posx_++;
      }
      
      if ((REG_KEYINPUT & KEY_UP) == 0)
      {
         player.DrawBox();
         player.posy_--;
      }
      
      if ((REG_KEYINPUT & KEY_DOWN) == 0)
      {
         player.DrawBox();
         player.posy_++;
      }

   frames++;
   WaitVSync();
   }
return 0;
}


After this I came up with a solution where I basically put these three lines of code at the very top of my main above the FlipBuffers function:
Code:
ClearScreen8(4);
      
   player.DrawBox();
   enemy.DrawBox();


This doesn`t feel like a good solution though because I feel like if I`m starting to draw my boxes there I might just as well just throw the constructor away. Also now when I move my player box to the upper part of the screen at one point it disappears kind of `behind` the screen which leads me to believe that some of my code makes the program draw something outside the screen although I have given it borders. This was not happening before my last `solution`.

Edit: After some more experiments I discovered that moving the ClearScreen function into my while loop is what creates the anomalies. I tried replacing the ClearScreen function with a manual draw the screen background function with a for within a for loop and that made the anomaly disappear, but the redrawing was happening incredibly slowly and the boxes were flickering.

#177752 - elhobbs - Mon Jan 28, 2013 12:33 pm

That's fine. The key logic looks weird since you are alway adding and subtracting the position each frame and drawing the player in all cases - 4 times each frame if no button is pressed. And not drawing when a key is pressed.