fillRect() and fillScreen() too slow and flickers too much

I just found this out, the library is uses 16-bit color. But I only need Black and White, so could I make a 1-bit color function or something. Would this be fast or same speed?

The library and display support 16 bit colour so all of its functions will do the same, so any function that you write that calls a library function will actually be working with 16 bits

You would be better off using a monochome screen and a library to go with it

Ok, thanks for the help, I'll just get a monochrome display.

I have closed your duplicate topic and directed readers of it to this one

Please do not cross post as it wastes time

I guess putting the pictos in ram would increase the update rate significantly.
And they are not really big, so it should not be a problem.
Maybe also make them global so they are put from program memory into ram only once.

Worth a try, certainly

When I remove the PROGMEM keyword all the sprites just mess up.

When I was talking about changing 16-bit colour to a 1-bit, I'm talking about changing the library by adding a new function. Would that work?

Maybe your adafruit drawbitmap assumes that the picto is in progmem... (that would explain why you do not need the special progmem handling).
Maybe the library has an alternative call to drawbitmap (an overloaded function) or an alternative function to draw bitmaps from ram?
I am not that well into this library...

I am not familiar with this screen, but could it be wired parallel? That would allow 8x faster updates.
But also would use 9 or 10 output pins...
I guess you now have an SPI or I2C like connection for data transfer...

Ok so, I serach through the library and found these 2 functions:

/**************************************************************************/
/*!
   @brief      Draw a PROGMEM-resident 1-bit image at the specified (x,y)
   position, using the specified foreground color (unset bits are transparent).
    @param    x   Top left corner x coordinate
    @param    y   Top left corner y coordinate
    @param    bitmap  byte array with monochrome bitmap
    @param    w   Width of bitmap in pixels
    @param    h   Height of bitmap in pixels
    @param    color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[],
                              int16_t w, int16_t h, uint16_t color) {

  int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
  uint8_t byte = 0;

  startWrite();
  for (int16_t j = 0; j < h; j++, y++) {
    for (int16_t i = 0; i < w; i++) {
      if (i & 7)
        byte <<= 1;
      else
        byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
      if (byte & 0x80)
        writePixel(x + i, y, color);
    }
  }
  endWrite();
}

/**************************************************************************/
/*!
   @brief      Draw a PROGMEM-resident 1-bit image at the specified (x,y)
   position, using the specified foreground (for set bits) and background (unset
   bits) colors.
    @param    x   Top left corner x coordinate
    @param    y   Top left corner y coordinate
    @param    bitmap  byte array with monochrome bitmap
    @param    w   Width of bitmap in pixels
    @param    h   Height of bitmap in pixels
    @param    color 16-bit 5-6-5 Color to draw pixels with
    @param    bg 16-bit 5-6-5 Color to draw background with
*/
/**************************************************************************/
void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[],
                              int16_t w, int16_t h, uint16_t color,
                              uint16_t bg) {

  int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
  uint8_t byte = 0;

  startWrite();
  for (int16_t j = 0; j < h; j++, y++) {
    for (int16_t i = 0; i < w; i++) {
      if (i & 7)
        byte <<= 1;
      else
        byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
      writePixel(x + i, y, (byte & 0x80) ? color : bg);
    }
  }
  endWrite();
}

/**************************************************************************/
/*!
   @brief      Draw a RAM-resident 1-bit image at the specified (x,y) position,
   using the specified foreground color (unset bits are transparent).
    @param    x   Top left corner x coordinate
    @param    y   Top left corner y coordinate
    @param    bitmap  byte array with monochrome bitmap
    @param    w   Width of bitmap in pixels
    @param    h   Height of bitmap in pixels
    @param    color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w,
                              int16_t h, uint16_t color) {

  int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
  uint8_t byte = 0;

  startWrite();
  for (int16_t j = 0; j < h; j++, y++) {
    for (int16_t i = 0; i < w; i++) {
      if (i & 7)
        byte <<= 1;
      else
        byte = bitmap[j * byteWidth + i / 8];
      if (byte & 0x80)
        writePixel(x + i, y, color);
    }
  }
  endWrite();
}

/**************************************************************************/
/*!
   @brief      Draw a RAM-resident 1-bit image at the specified (x,y) position,
   using the specified foreground (for set bits) and background (unset bits)
   colors.
    @param    x   Top left corner x coordinate
    @param    y   Top left corner y coordinate
    @param    bitmap  byte array with monochrome bitmap
    @param    w   Width of bitmap in pixels
    @param    h   Height of bitmap in pixels
    @param    color 16-bit 5-6-5 Color to draw pixels with
    @param    bg 16-bit 5-6-5 Color to draw background with
*/
/**************************************************************************/
void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w,
                              int16_t h, uint16_t color, uint16_t bg) {

  int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
  uint8_t byte = 0;

  startWrite();
  for (int16_t j = 0; j < h; j++, y++) {
    for (int16_t i = 0; i < w; i++) {
      if (i & 7)
        byte <<= 1;
      else
        byte = bitmap[j * byteWidth + i / 8];
      writePixel(x + i, y, (byte & 0x80) ? color : bg);
    }
  }
  endWrite();
}

All of the functions have the same name so I don't known how to call them.

I also wired it like so:

Display -> Arduino
VCC -> 5V
GND -> GND
DIN -> 12
CLK -> 11
CS -> 10
DC -> 9
RST -> 8

The last two calls have no progmemread in it. So I guess you need to call one of those.
You must adjust your arguments to the function so that it matches the pattern of the library function you want to use...

I've changed the arguments to:

void UpdateDisplay()  
{
  display.fillScreen(BLACK);
  for(int across=0;across<NUM_ALIEN_COLUMNS;across++)
  {
    for(int down=0;down<NUM_ALIEN_ROWS;down++)
    {
      switch(down)  
      {
        case 0: 
          display.drawBitmap(Alien[across][down].Ord.X, Alien[across][down].Ord.Y,  InvaderTopGfx, AlienWidth[down], 8, WHITE);
          break;
        case 1: 
          display.drawBitmap(Alien[across][down].Ord.X, Alien[across][down].Ord.Y,  InvaderMiddleGfx, AlienWidth[down], 8, WHITE);
          break;
        default: 
          display.drawBitmap(Alien[across][down].Ord.X, Alien[across][down].Ord.Y,  InvaderBottomGfx, AlienWidth[down], 8, WHITE);
      }
    }
  }
}

The arguments are already the same.

Which matches the arguments the function wants but now it looks like this:

But it should look like this:

It seems you are getting close...
X and y shuffled?
Off by one error?
Why not call the function once with comprehensible (const int) arguments? This way we it is not easy to see what arguments are used when you call the function.

So, x and y are not shuffled and there isn't any errors.
What do you mean by "Why not call the function once with comprehensible (const int) arguments? This way we it is not easy to see what arguments are used when you call the function." I don't know what that means.
And is EEPROM and RAM the same?

Your update display function is rather complicated. We cannot easily see what arguments are sent to the function...
And which switch it takes...

Doi it like
int x=0;
int y=0;
int width= ;
int height= ;
drawPicto(x,y,bmp,width,height, WHITE);

Or do a serial print of all your arguments before the print...

Sometimes x an y are swapped on displays. There might be a setRotation function to fix that. But swapping height and width may also work...

EEPROM is another type of memory than RAM. It is very limited in size and persists after reboot, shutdown, power off.

Here is a clearer version:

void UpdateDisplay()  
{
  for(int across=0;across<NUM_ALIEN_COLUMNS;across++)
  {
    for(int down=0;down<NUM_ALIEN_ROWS;down++)
    {
      int x = Alien[across][down].Ord.X;
      int y = Alien[across][down].Ord.Y;
      int width = AlienWidth[down];
      const int height = 8;
      switch(down)  
      {
        case 0: 
          display.drawBitmap(x, y, InvaderTopGfx, width, height, WHITE);
          break;
        case 1: 
          display.drawBitmap(x, y, InvaderMiddleGfx, width, height, WHITE);
          break;
        default: 
          display.drawBitmap(x, y, InvaderBottomGfx, width, height, WHITE);
      }
    }
  }
}

An off by one error is not a syntactic error, but a semantic error. It will not throw an error.
Happens a lot using arrays, as elements in N element array are numbered 0 to n-1.
Some smart compilers will throw a warning if you try to access a non existing element of an array...

You just use the function name and call it with the appropriate list of parameter types to match the flavour of the function that you want to call.

This is exactly how you are able to call Serial.print() with parameters of many different types and even a different number of parameters