I am loading a new PictureBox from an array at various intervals. I also have a character moving across the screen at different times. The more PictureBoxes I load, the slower my character moves. I have tried a Timer for the movement and a Do : DoEvents : Loop routine for the movement, but am getting the same results. I realize it is a memory issue. My question is: How do I flush the memory without losing the arrays so that my character doesn't slow down?
How many of these windows are you loading? A game designed with GDI windows will probably not perform well, depending on number of 'sprites' and complexity. You don't want to hear this, I think you are going about this the wrong way. But to try to be helpful, you might consider optimizing whatever loops are being entered during each move of each window. Generally, loops will be a speed bump in any game. Also understand that a lot of stuff happens when your windows move, dozens, if not 100s of messages may be triggered between affected windows and the objects behind/above that window in zOrder. Each time a window moves, screen needs to be updated. DoEvents slow down your code, but allow the form to remain responsive to the user.
In short, a simple answer to your question is not possible. I'm sure there are several issues, some minor/easy to fix, while others may be more complex.
Insomnia is just a byproduct of, "It can't be done"
Well, I'm not loading windows, I'm loading PictureBoxes, and it's possible to fill my Form with 600, but the "slow down" starts when I only have around 50. Keep in mind, these PictureBoxes are only about 50x50 pixels. Either way, the more PictureBoxes that are being used, the slower everything will be. I am wondering if there is a work-around to keep the speed at a constant rate.
FYI: Pictureboxes are windows. Windowed-controls are easy to identify as nearly all will have a hWnd property. Most controls used in VB are windows, very few are not. Windows eat up memory & require message traffic. Though the traffic probably isn't a real issue, it does add slightly to the lag I would imagine, but not severely.
Without seeing sections of your code, I'd first look at your loops. I'm sure you are doing stuff as each window moves, i.e., collision testing, repainting, ZOrder adjustments, and other stuff. This is almost always a good place to start optimizing to increase speed. I think people here would be able to and willing to assist with optimizing those loops if you need any help with that
Insomnia is just a byproduct of, "It can't be done"
Understood about the PictureBoxes being windows, but I prefer to call them by their names, as could lead to confusion for others.
Also, I am only moving 1 PictureBox. The other PictureBoxes are remaining still, though regioned for transparency. I just can't see having this much trouble with moving a single PictureBox.
I am also using a "pause" routine, as follows, in my loop to add hesitation between movements:
Code:
Function Pause(interval)
current = Timer
Do While Timer - current < Val(interval)
DoEvents
Loop
End Function
But, as it runs the exact same code in the beginning the first several times and shows no sign of slowing, I am lead to believe that the loop isn't the cause. I have run the loop continuously with only 2 PictureBoxes loaded and it doesn't slow over time. Of course, when I add more PictureBoxes, it seems to drive up the memory usage and boom... lag.
Okay. I've taken out the Regioning of the PictureBoxes, which removes the transparency, and it runs just fine without any "noticeable" lag. It would seem that a regioned PictureBox with an array and then loading more arrays of the same PictureBox is the culprit. But... I need those arrays and I need them to have transparency. It's what makes it look as good as it does.
Not sure how your code is set up, but will throw this out to consider:
1) Where possible drop the picture boxes (if each picturebox represents an icon) and create a Sprite instead.
2) Try with and without a double buffer. For one of my programs - because of real-time constraints -- I went to drawing (painting) directly to the object (picturebox) using the Paint event rather than using a double buffer.
3) Drop the transparency and do overlays instead. That is look at the order in which you place (draw) your objects such that the last object needed is on-top.
dw: I don't understand how to "create a sprite", nor do I understand what you mean by "double buffer". I need my PictureBoxes because they represent a reference point when attempting to move my character back to them. If I drop them, I lose both my picture and reference point.
Update: I have dropped regioning the PictureBoxes and used an ImageList and gained the transparency from that. I'm also now using an arrayed Shape control as reference points, which take up much less memory. The only thing that's bothering me now is, when I used PictureBoxes, I could change the ZOrder, making my tiled images look somewhat 3D. Now that I'm using the ImageList to Draw them onto my Form, I've lost that capability. Which leads me to believe my images now have to take on a more 2D look... which I'd really rather not have.
I don't know if the attached example will be of any interest. You can read about the history in a thread at this link. The example is from post #17.
Another poster did a Object Oriented version and it is attached in post #21.
It uses bitblt to draw the images and uses a twist on the usual method of using a black and white mask to do the transparent background blit. I came up with it on my own, but assume I'm not the first. Rather than prepare a black and white mask to define the transparent pixels, I just draw the same image in two pictureboxes, one with a black background and the other a white background. You then just bitblt the two images to a location to do the transparent blit. You use an OR rasterOP with the Black background and an AND rasterOP with the White background. Unlike the black and white mask, it doesn't matter which one you do first, the result will be the same.
I find it convenient if I want to dynamically draw a figure, or print text, etc. dynamically and still be able to drag it around with transparency. Just draw or print the same thing in both pictureboxes.
Anyway, food for though, but you might find it overwhelming.
Just for the heck of it, I'm including a second example demonstrating the dynamic transparency while drawing method I mentioned, which includes rotating the transparent image at the same time you're drawing it. You do the drawing in the boxes above the rotating display output.
Also have taken a shot at this, using no Picture- or Image-Controls, but two normal,
small Classes instead:
cSprites.cls (which aggregates the Sprites in a Collection and offers an Add-method)
Code:
Option Explicit
Public Col As New Collection
Public Sub AddAndInit(Sprite As cSprite, Key, ImgKey, x, y, Optional aShiftX, Optional aShiftY)
Sprite.Key = Key
Sprite.ImgKey = ImgKey
Sprite.dX = PngCache.Width(ImgKey)
Sprite.dY = PngCache.Height(ImgKey)
Sprite.x = x
Sprite.y = y
If Not IsMissing(aShiftX) Then Sprite.aShiftX = aShiftX
If Not IsMissing(aShiftY) Then Sprite.aShiftY = aShiftY
Col.Add Sprite, Key
End Sub
cSprite.cls (which offers StateProperties for a single Sprite-Instance and Draw- and Animate-Methods)
Code:
Option Explicit
Public Key, ImgKey, x, y, dX, dY 'standard Properties
Public aShiftX, aShiftY, aX, aY 'additional Props for (optional) animation
Public Sub Draw(ByVal hDC As Long)
PngCache.AlphaRenderTo hDC, ImgKey, x, y, IIf(aShiftX, aShiftX, dX), IIf(aShiftY, aShiftY, dY), aX, aY
End Sub
Public Sub MoveRel(xRel, yRel)
x = x + xRel
y = y + yRel
End Sub
Public Sub Animate()
aX = aX + aShiftX: If aX >= dX - 1 Then aX = 0
aY = aY + aShiftY: If aY >= dY - 1 Then aY = 0
End Sub
No flickering (using a PictureBox-Canvas in DoubleBuffer-Mode, aka AutoRedraw=True),
and CPU-Load being near Zero (whilst constantly rendering 95 Sprites with about 60Hz).