wawa
Junior Member
Posts: 24
|
Post by wawa on Jul 19, 2020 9:08:19 GMT -8
Hello,
With Adafruit and other common libraries to display an image, a text or a shape, there's no need to swap between 2 buffers, we just need to call the graphical function to fill the screen with what we want. So if I want to add an image among others, I don't need to to clear all and display all the previous (memorized) things plus the new desired object. With Gameduino, I only found the swapping buffer method but all the code becomes very complexe because of it!
For example, a simple algo like "every 5 secondes display a grid of 9 random sprites" becomes boring to code because you need to memorize 10 random values just to display the same 9 sprites during a given time.
So, is there a way to display things without redrawing all??
|
|
|
Post by jamesbowman on Jul 19, 2020 15:25:02 GMT -8
Well, that's an interesting question. Those framebuffer libraries use "front-buffer" rendering. If you draw two sprites, one covering another, they will flicker because the first one is drawn, then the second one covers it. The reason that EVE works this way is to avoid this flicker. You only "show" the display when you have finished it, and call "swap()" If you want to update more slowly, you can. For example to update every 5s you can do: GD.Clear(); ... GD.swap(); delay(5000);
That is, you don't have to continuously swap() at 60 Hz. en.wikipedia.org/wiki/Multiple_buffering#Double_buffering_in_computer_graphics
|
|
wawa
Junior Member
Posts: 24
|
Post by wawa on Jul 20, 2020 12:57:59 GMT -8
So,it's not possible to just update the screen without clearing-filling-swapping?
|
|
|
Post by jamesbowman on Jul 20, 2020 18:33:07 GMT -8
Well, there is one way.
If you draw a bitmap on the screen, you can update that bitmap's data in RAM, and it will show up on the screen immediately.
So for example you can fill the whole screen with a bitmap, then draw pixels in that bitmap. It acts just like a cheap "single buffered" display: the drawn pixels show up immediately.
|
|
wawa
Junior Member
Posts: 24
|
Post by wawa on Jul 21, 2020 8:54:07 GMT -8
I tried what you said but it doesn't work. The following code should display side by side, every second, a random image but nothing is displayed :/ int ind=0; uint32_t timer;
void setup(){ GD.begin(~GD_STORAGE); LOAD_ASSETS(); GD.Clear(); }
void loop(){ if(millis()-timer>1000 && ind<5){ timer=millis(); GD.Begin(BITMAPS); GD.Vertex2ii(ind*90,0,IMG_HANDLE,random(2)); //GD.swap(); ind++; } } If I uncomment GD.swap(), only the last random image is displayed... on an strange pink background and the previous images are lost as you can see in the following video demonstration:
How to update bitmap data in the ram to show up immediatly on the screen??
|
|
|
Post by tftlcdcyg on Jul 21, 2020 14:02:19 GMT -8
Please, Could you share the images to reproduce the problem you are referring to?
|
|
|
Post by jamesbowman on Jul 21, 2020 15:30:47 GMT -8
void setup() { GD.begin(~GD_STORAGE); GD.cmd_setbitmap(0, RGB565, 480, 272);
GD.Clear(); GD.Begin(BITMAPS); GD.Vertex2f(0, 0); GD.swap(); }
void loop() { long x = random(480); long y = random(272); GD.wr16(2 * (x + y * 480), random(65536)); }
So this sets up the 480x272 bitmap, in RGB 565 format, and swaps once.
In "loop()" it paints random (x,y) pixels on the bitmap.
|
|
wawa
Junior Member
Posts: 24
|
Post by wawa on Jul 22, 2020 8:03:06 GMT -8
1) Ok, for pixels, you write word in the bitmap memory but for sprites ?? Again, the following code, shows only the last random drawing image, not all the previous: video sample here
#include <EEPROM.h> #include <SPI.h> #include <GD2.h>
#include "images.h" //90x90
void setup() { GD.begin(~GD_STORAGE); LOAD_ASSETS(); }
void loop() { //GD.Clear();
GD.Begin(BITMAPS); GD.Vertex2ii(random(480-90),random(272-90),IMG_HANDLE,random(2)); GD.swap(); delay(1000); }
2) Same problem to "paint" the screen with random texts:
const char *text[4][6]={"ONE","TWO","THREE","FOUR"};
void setup(){ GD.begin(0); }
void loop() { //GD.Clear(); GD.cmd_text(random(250),random(200),30,0,text[0][random(4)]); GD.swap(); delay(1000); }
So simple things seem complex to do with that library...
|
|
|
Post by tftlcdcyg on Jul 22, 2020 13:26:14 GMT -8
Screens like the gameduino don't work like the screens you've seen before. They are GPU chips which work at refresh rates close to 60 Hz. The erase-redraw technique that supports the GFX library for example (ILI9341, ILI9488, RA8875, ST7735, etc), does not work.
You should consider that the screen continuously shows the code inside the main loop. Forget about the delay () statement, use millis (), to manipulate the sampling times.
#include <EEPROM.h> #include <SPI.h> #include <GD2.h>
#include "images.h" //90x90 char txt[4][6]={"ONE","TWO","THREE","FOUR"};
void setup() { GD.begin(); LOAD_ASSETS(); }
long previousMillis1 = 0; long interval1 = 500; int Px1, Py1; int Px2, Py2;
int PTx1, PTy1; int PTx2, PTy2; int PTx3, PTy3; int PTx4, PTy4;
void loop() { GD.Clear(); GD.Begin(BITMAPS);
unsigned long currentMillis1 = millis(); if(currentMillis1 - previousMillis1 > interval1) { previousMillis1 = currentMillis1; Px1=random(GD.w-90); Py1=random(GD.h-90); Px2=random(GD.w-90); Py2=random(GD.h-90);
PTx1=random(GD.w-90); PTy1=random(GD.h-90); PTx2=random(GD.w-90); PTy2=random(GD.h-90); PTx3=random(GD.w-90); PTy3=random(GD.h-90); PTx4=random(GD.w-90); PTy4=random(GD.h-90); }
GD.Vertex2ii(Px1,Py1,IMG_HANDLE,1); GD.Vertex2ii(Px2,Py2,IMG_HANDLE,0);
GD.cmd_text(PTx1,PTy1,30,OPT_CENTER,txt[0]); GD.cmd_text(PTx2,PTy2,30,OPT_CENTER,txt[1]); GD.cmd_text(PTx3,PTy3,30,OPT_CENTER,txt[2]); GD.cmd_text(PTx4,PTy4,30,OPT_CENTER,txt[3]); GD.swap(); // delay(1000); }
|
|
|
Post by tftlcdcyg on Jul 22, 2020 14:36:38 GMT -8
This is a somewhat more complex example
|
|
|
Post by jamesbowman on Jul 22, 2020 16:52:34 GMT -8
That's quite nice -- do you have a pointer to the source and graphics? I like the fast-animating sprites.
|
|
wawa
Junior Member
Posts: 24
|
Post by wawa on Jul 23, 2020 8:16:35 GMT -8
Of course timers are often more judicious than delays but it was not the purpose of my question. I just wanted to be sure there were no other ways than store in memory all the previous data to paint a screen with random sprites or texts. Four variables just to draw 2 random sprites... Imagine you have more than 100! Of course I would use arrays of structures instead but it's what I expected because of the refresh system of the screen. Thanks to confirm my doubts! On "Adafruit" screens there would not need to memorize data like that and the code would be really lighter and simple for a such example, but of course there's no comparison with the speed to animate a game, but they still are interesting screens for static games. However, with some tips, I made games with animated sprites on background on that screens despite of the very limited memory of the UNO and the impossibility to refresh the screen: GAMES EXAMPLE
|
|
|
Post by avanti on Jul 26, 2020 4:26:55 GMT -8
You might also want to explore the use of the APPEND command to efficiently render static and dynamic screen segments. The idea is to write the static parts of a screen to RAM_DL, but without actually displaying them. You then copy the display lists to RAM. After that, you can add any of them to the current display list using a single APPEND command, after which you can add the dynamic parts of the display and do a SWAP.
|
|
wawa
Junior Member
Posts: 24
|
Post by wawa on Jul 26, 2020 9:19:27 GMT -8
Yes, why not, thanks for the idea Later I'll do a special version of the library so that I can add/remove/modify graphic objects (texte, bitmap etc.) at any time from a chained list. I'd like to code like I was used with ActionScript 3.0 and the DisplayObjectContainer...
|
|