Null pointer in DynamicSprite array

Started by GlaDOSik, Sat 16/11/2013 14:06:58

Previous topic - Next topic

GlaDOSik

Hi,

I'm working in AGS on RGB filter. It uses GetPixel on small sprite (160x100) and then render images (16000) made of 3 colors like pixel on monitor does. It uses 2 functions. The first one iterates through all AGS colors (0-65535), separets RGB colors, renders dynamic sprites (pixels) and save them into the dynamic sprite array. And here is the problem and I can't find the solution. It looks like my function works to number 29998. All above that (29999-65535) throws null pointer error. Code is here:

Code: ags

function initScreenRen(){                    //initScreenRen() is called once in room_AfterFadeIn()
  
  int pixelCounter;                         //pixel counter
  pixelImg = DynamicSprite.Create(3, 3);    //creates dynamic sprite for pixel 3x3 px
  
 while (pixelCounter <= 65535){                     //iterates through all AGS colours and makes pixels for them
  
  bool highBit = true;                              //AGS color to RGB
  if (pixelCounter > 65535) pixelCounter -= 65536;
  rgb[0] = ((pixelCounter >> 11) & 31) << 3;
  rgb[1] = ((pixelCounter >> 6) & 31) << 3;
  rgb[2] = (pixelCounter & 31) << 3;
  if (highBit)
  {
    rgb[0] = rgb[0] | 7;
    rgb[1] = rgb[1] | 3;
    rgb[2] = rgb[2] | 7;                            //end AGS color to RGB
  }

 DrawingSurface *pixelSurface = pixelImg.GetDrawingSurface();               //draw subpixels into pixelImg      //CO KDYBYCHOM VYKRESLOVALI PŠ˜àMO DO BANKY PIXELŠ®?
    pixelSurface.DrawingColor = Game.GetColorFromRGB(rgb[0], 0, 0);
      pixelSurface.DrawLine(0, 0, 0, 2);
    pixelSurface.DrawingColor = Game.GetColorFromRGB(0, rgb[1], 0);
      pixelSurface.DrawLine(1, 0, 1, 2);
    pixelSurface.DrawingColor = Game.GetColorFromRGB(4, 4, rgb[2]);          //end draw subpixels into pixelmg 
      pixelSurface.DrawLine(2, 0, 2, 2);
  pixelSurface.Release();    
  
  pixelBank[pixelCounter] = DynamicSprite.CreateFromExistingSprite(pixelImg.Graphic);     //move pixelIMG to array of dynamic sprites pixelBank 
  
  pixelCounter++;           //iterates the color to 65535
 }
 
  object[0].Graphic = pixelBank[29999].Graphic;   //null pointer? why? it iterates to 65535
  }


Header is here:

Code: ags

DynamicSprite *pixelBank[65536];
DynamicSprite *pixelImg;
int rgb[3];
import function initScreenRen();


Any help is appreciated. Thanks.

Crimson Wizard

#1
You can have not more than 30000 sprites in your game, both dynamic and static ones (imported in project).

Also what you describe sounds as a very non-optimal solution... perhaps there's other better ways to do what you want?
Unfortunately, I am loaded with work myself now, hopefully someone else can give advice.

Khris

You have to rewrite this so that the function creates the 3x3 sprite when it is called.
What you can do to optimize this is store the rgb values for each color combination in huge arrays.

GlaDOSik

#3
Thanks. So the sprite limit applies on dynamic sprites too. I completely forgot about that.

Khris: That's exactly what I made first time. I only pre-calculate rgb values and store them in array. Each cycle I rendered all 16000 pixels. But that was heavy. It has about 12 fps. Then I use this dynamic sprite array but I render and store the pixel only when it wasn't in array. So after one cycle, it just load pixel sprites from this array. I store only colors from few sprites so I didn't exceed sprite limit. That was much better though. About 30 fps. But that solution wasn't good for animations, because new pictures have new colors that wasn't in array. And then I came to this "pre-render all colors" which can't work because of this limit.

I also store pre-rendered sprites on disk (SaveToFile) but that was the worst thing. 0,5 fps. It looks that the best thing would be draw game graphic in limited color palette.

Khris

Yeah, as great as AGS is, whenever you want to do something CPU intensive, you're prone to hitting a wall pretty soon, unfortunately.

What is the effect you're going for? Couldn't you replace all sprites and backgrounds with filtered versions at the start of the game?

GlaDOSik

Well, the game code will render the game graphics into the buffer (dynamic sprite 160x100 px). Then this buffer will go through this RGB filter and result will have lo-fi effect (example is in attachment). I can't pre-render all backgrounds at start, because I want to use the effect on whole screen (GUI, background, animated character).

Code: ags
https://www.dropbox.com/s/nkl0uip6frvoqfs/SDE.zip

Khris

I see, that looks pretty cool.
The thing is though, have you tried whether it's actually possible to do full-screen effects like that? Because in order to change the final image rendered by the engine, you have to take a screenshot, change that, then display it. But since it now would appear in the screenshot, you have to turn off the GUI displaying the filtered version to take the screenshot.

The only workaround I can see would be to replicate the engine's rendering of the screen to a DynamicSprite (including drawing all GUI elements manually, etc), at which point coding a plugin instead is much more feasible.
Or have you found another way?

Scavenger

#7
Quote from: Khris on Sat 16/11/2013 18:28:41
The only workaround I can see would be to replicate the engine's rendering of the screen to a DynamicSprite (including drawing all GUI elements manually, etc), at which point coding a plugin instead is much more feasible.

You know what would be a really useful thing here? A plugin that takes a Sprite, and spits out an array, and can take arrays and build them back into sprites. I've been thinking about pixel-level graphical functions for a long while, and AGS could probably handle most of it itself, it's just the actual sprite drawing that's super slow. GlaDOSik has most of the work for their filter done - if it could be done to an array instead of a drawing surface AGS could handle it super easily with minimal loss of FPS. Heck, I'd find it useful too, I've just not been able to figure out how to handle arrays in plugins. The general nature of the plugin, that is, that it performs one function and one function only, would allow a wide variety of effects to be made super easily in-script without the need of bespoke plugins and the ability to program in C++, though it might suffer a tiny bit in performance.

I've been stifled many times by AGS' slow pixel level drawing functions.

Edit: Since AGS doesn't support returning arrays from functions, why not use Strings instead? It'd be easily to serialise that way, and a string is just a 1D array anyway. You could use GetChar to populate an array - with 8-bit being single characters, 16 bit being 1 character bitshifted to the left 4, and added to the second character's value, and so on.

Crimson Wizard


GlaDOSik

Khris: Well, the idea is to render GUI, mouse cursor and NPS directly into DynamicSprite.

Crimson Wizard: His filters are nice, but aren't they only for DirectDraw? I find, that a lot of people have problems with DD. Also, I'm able to simulate noise and line offset so I can degrade the screen. And I think it would be good part of gameplay. Do you know game called Experience 112? My idea is similar. Player can control different cameras, door locks, lights, alarm systems etc. And NPC would react to that. And differet cameras could have different parameters and quality of signal. I could even design some puzzles, where you have to properly set your camera (turn off colors and have black and white screen, filter red/green/blue). So that's why I working on my own solution. But it started on "am I able to make RGB filter?". The game and gameplay is now secondary.

SMF spam blocked by CleanTalk