XNA GraphicsDeviceManager.ApplyChanges() causes flicker when called on application start - c#

I have a function with the following code in it:
GameStateManagementGame.GraphicsDeviceManager.PreferredBackBufferWidth = width;
GameStateManagementGame.GraphicsDeviceManager.PreferredBackBufferHeight = height;
GameStateManagementGame.GraphicsDeviceManager.IsFullScreen = isFullScreen;
GameStateManagementGame.GraphicsDeviceManager.ApplyChanges();
When it's called at application start, if isFullScreen = true, there is very noticeable screen flicker for a second or 2 even if the width and height are the same as the desktop resolution. If I don't have the ApplyChanges(); call this doesn't happen (but the settings do get applied). If I call the function after the game has fully started without the ApplyChanges() call, the settings don't get applied.
Now I can solve this problem by putting something in to skip the ApplyChanges() call at startup but I'd like to know why this is happening.
The only information I've managed to find regarding this problem say that the flicker shouldn't happen if you're using the same resolution as the desktop or have provided overcomplicated and broken workarounds.
So my question is what is the reason for the behaviour described above and what's the best workaround?

The settings you set on GraphicsDeviceManager are applied in these cases:
If you call ApplyChanges()
If you call ToggleFullScreen()
By Game when Game.Run() is called (it creates the graphics device)
Noteably, modifying any of the settings will not cause those settings to be applied immediately.
The likely reason for your flickering is that you are doing #3 and then immediately doing #1 (you are applying the settings twice in a row).
For initial start-up, you should set the correct settings on the GraphicsDeviceManager instance during your game class's constructor. Then those settings will be correct when Game.Run() is called.
Use ApplyChanges() only when the user changes the settings while the game is running.

Related

Problem with adding with ++ operator, what can I do?

So, I as trying to create an "Open world exploration" game in C# WinForms, And while coding the mining, (which works just fine), I encountered a problem with saving the number of broken blocks to the inventory (a label). Basically, for every block player breaks, it gets added to the inventory as inventoryWrite.Text = $"Grass: {grassHolder}, Rock: {rockHolder}";.
Now, the thing is, sometimes, even though I use the ++ operator, it adds up to 4 to the inventory. I'm citing the code below.
private void Remove(object sender, EventArgs e, PictureBox itm)
{
if (itm.BorderStyle == BorderStyle.FixedSingle)
{
if (itm.Tag.Equals("grass") && items.Contains(itm))
{
grassHolder++;
itm.Tag = "";
}
if (itm.Tag.Equals("rock") && items.Contains(itm))
{
rockHolder++;
itm.Tag = "";
}
if (itm.Tag.Equals("dio") && items.Contains(itm))
{
dioHolder++;
itm.Tag = "";
}
this.Controls.Remove(itm);
items.Remove(itm);
}
}
I update the inventory in a public loop, don't worry about that (interval is 1ms). But I don't think that's the problem, since I tried putting it in the Remove() function, and nothing seemed to change.
I've even double locked the if statement, but nothing! It still adds more than 1. Can anybody tell me how to solve this? Thank you a lot.
EDIT:
As a reply to Ronald's comment, the if statement is called ONLY when the block is selected. ONLY once when the method is called.
There are too many points to cover in a comment and so I've had to enter an answer.
In itself the ++ operator is not the issue and will always behave as it should, but as someone reviewing a small piece of code the following points crop up.
grassHolder, rockHolder, dioHolder appear to have
accessibility beyond this function and so could be altered
elsewhere.
Function void Remove(object sender, EventArgs e, PictureBox itm) appears to be an event handler and yet there is no locking mechanism to ensure that the externally accessible parameters are not changed or used elsewhere whilst the function code is executed. Specifically items which is appears to be a collection of sorts and is used both in logic to determine whether parameters in (1) are incremented, but also has its contents changed within the function.
From comments made it would appear that this logic is run in
response to user interaction, maybe by use of a mouse button or key
event. Is this base event de-bounced to ensure that multiple
triggers aren't handled?
Your statement "saving the number of broken blocks to the inventory (a label)." Implies that you are storing game data within the UI. This should be avoided as it ties game data directly to the UI implementation and therefore makes it difficult to alter the game, but also ties any handling of game data directly to the UI thread.
Recommended actions:
Ensure that the parameters in question are not accessed and altered
elsewhere causing the issue seen.
Utilize a lock(x) statement to ensure that items is not changed
whilst this function is being executed. More information here
De-bounce the mouse button or key click that triggers this function
to ensure that multiple events aren't triggered. This is performed
by placing a minimum time between event triggers. A minimum time
period of say 150ms would be a good starting point. This would equate to a reasonably quick, conscious user action, but be slower than multiple events triggered by partial/poor switch contact. Incidentally this is especially true on touch screen interfaces.
Consider controlling access to global parameters through use of
access functions. For example
int IncrementRockHolder(){ rockHolder++;} Although implementation may appear onerous, they can greatly help with debugging as call stack information is then available showing what code is calling the function and thus making the change.
Implement a game engine class to control access to game data and implement game logic. This
would allow you to unit test game functionality whilst also freeing
it from UI implementation and restrictions.

UnitySharpNEAT How to deactivate a unit

I'm hoping that someone here is familiar with UnitySharpNEAT as I'm running into a problem I can't seem to find the solution to. I can describe it, but providing code won't really be helpful as it extends over multiple scripts. It really requires that someone already know how to use this.
I'm running a simulation where a creature must find food, or die of starvation. For the purposes of "dying", I can see two different options of how to deactivate a unit, but neither one is giving me the results I am desiring.
The first option is if the hunger reaches zero, I can do this:
IsActive = false;
The problem with using this method is that if all the units are inactivated before the end of the duration of the trial, the trial just continues running until the time is elapsed, and I don't know how to make it start a new generation when all the units are inactive.
The other option is to call
DeactivateUnit()
from the base class UnitController. This Deactivates the unit, but for some reason, continues to try to perform operations on it, specifically the activate method, and results in a NullReferenceException, because it's trying to access a blackbox that has been set to null, which it shouldn't even do because that block of code is only supposed to be called if IsActive is true, but it's set to false by the DeactivateUnit() method.
All I'm looking for, is a way to deactivate a unit that has failed, by starvation or touching a wall, and if all units are deactivated, to immediately begin a new generation.

Do I have to keep creating a Graphics object

I am an old delphi programmer, I am used to creating objects and using them entire time for efficient memory usage. But in c# (maybe all the tutorials I've ever seen), you are creating stuffs with new every time (thanks to garbage collector!!, let me do the coding)..
Anyway, I am trying to create a designing software which has lots of drawing.
My question is: do I have to create a graphics object, or use the protected override void OnPaint(PaintEventArgs e) e.Graphics every painting event.. because when I create a graphic object and then resize the control that I draw on, the graphic object that I created, has that clipping problem and only draws old rectangle region..
thanks
Caching objects makes sense when the object is expensive to create, cheap to store and relatively simple to keep updated. A Graphics object is unique in that none of these conditions are true:
It is very cheap to create, takes well less than a microsecond.
It is very expensive to store, the underlying device context is stored in the desktop heap of a session. The number of objects that can be stored is small, no more than 65535. All programs that run in the session share that heap.
It is very hard to keep updated, things happen behind your back that invalidates the device context. Like the user or your program changing the window size, invalidating the Graphics.ClipBounds property. You are wasting the opportunity to use the correct Graphics object, the one passed to you in a Paint event handler. Particularly a bug factory when you use double-buffering.
Caching a Graphics object is a bug.
If you want to draw on the surface always use the Graphics object from the Paint event!
If you want to draw into a Bitmap you create a Graphics object and use it as long as you want.
For the Paint event to work you need to collect all drawing in a List of graphic actions; so you will want to make a nice class to store all parameters needed.
In your case you may want to consider a mixed approach: Old graphic actions draw into a bitmap, which is the e.g. BackgroundImage or Image of your control
Current/ongoing drawing are done on the surface. This amounts to using the bitmap as a cache, so you don't have to redraw lots of actions on every little change etc
This is closely related to your undo/redo implementation. You could set a limit and draw those before into a Btimap and those after onto the surface..
PS: You also should rethink your GC attitude. It is simple, efficient and a blessing to have around. (And, yes, I have done my share of TP&Delphi, way back when they were affordable..) - Yes, we do the coding, but GC is not about coding but about house keeping. Boring at best.. (And you can always design to avoid it, but not with a Graphics object in a windows system.)
A general rule for every class that implements IDisposable is to Dispose() it, as soon as possible. Make sure you know about the using(...){} statement.
For drawing in WinForms (GDI+) the best practice is indeed to use the Graphics object from PaintEventArgs. And because you didn't create that one, do not Dispose() it. Don't stash it either.
I have to completely disagree with other more experienced members here who say it's no big deal or in fact better to recreate the Graphics object over and over.
The HDC is a pointer to a HDC__ struct, which is a struct with one member, "int unused". It's an absolute waste and stupidity to create another instance/object every time drawing needs to be done. The HDC is NOT large, it's either 4 or 8 bytes, and the struct it points to is in nearly all cases 4 bytes. Furthermore, on the point that one person made, it doesn't help that the graphics object be made with the "static" keyword at the beginning of the WndProc() before the switch, because the only way to give the Graphics object a device context or handle to paint on is by calling its constructor, so "static" does nothing to save you from creating it over and over again.
On top of that Microsoft recommends that you create a HDC pointer and assign it to the same value PAINTSTRUCT already has, every, single WM_PAINT message it sends.
I'm sorry but the WinAPI in my opinion is very bad. Just as an example, I spent all day researching how to make a child WS_EX_LAYERED window, to find out that in order to enable Win 8 features one has to add code in XML with the OS's ID number to the manifest. Just ridiculous.

D3DImage OutOfMemoryException when calling SetBackBuffer

I'm using D3DImage to show images rendered using Direct3D. The Direct3D rendering needs to be happening in its own thread, while the GUI thread takes a surface when it wants and puts it on the screen using D3DImage.
At first I tried to do this using a single D3D render target, however even with locks in place, I had serious tearing, i.e. the rendering thread was overwriting the surface as WPF was copying it on its frontbuffer. It seems like WPF is very unpredictable as to when it copies the data (i.e. it's not on D3DImage.Unlock() or even on the next D3DImage.Lock(), as the documentation suggests).
So now what I'm doing is I have two render targets, and every time WPF displays a frame, it asks the rendering thread to swap its targets. So I'm always rendering into the target WPF isn't using.
This means that on each graphical update of the window, I do something like
m_d3dImage.Lock();
m_d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, m_d3dRenderer.OutputSurface);
m_d3dImage.Unlock();
m_d3dRenderer.SwapSurfaces();
where OutputSurface is an IntPtr that points to the D3D render target we're not currently rendering to, and SwapSurfaces just swaps the two surface pointers and calls IDirect3DDevice9::SetRenderTarget with the one we'll use to render next.
EDIT: as requested, here is the code of SwapSurfaces():
var temp = m_renderingSurface;
m_renderingSurface = m_outputSurface;
m_outputSurface = temp;
m_d3dDevice.SetRenderTarget(0, m_renderingSurface);
Where m_renderingSurface and m_outputSurface are the two render targets (SharpDX.Direct3D9.Surface), and m_d3dDevice is the DeviceEx object.
This works beautifully, i.e. no tearing, however after a few seconds I get an OutOfMemoryException, and Direct3D has the following debug output:
Direct3D9: (ERROR) :Invalid iBackBuffer parameter passed to GetBackBuffer
Direct3D9: (ERROR) :Error during initialization of texture. CreateTexture failed.
Direct3D9: (ERROR) :Failure trying to create a texture
Direct3D9: (ERROR) :Error during initialization of texture. CreateTexture failed.
Direct3D9: (ERROR) :Failure trying to create a texture
MIL FAILURE: Unexpected HRESULT 0x8876017c in caller: CInteropDeviceBitmap::Present D3D failure
Direct3D9: (WARN) :Alloc of size 1577660 FAILED!
Direct3D9: (ERROR) :Out of memory allocating memory for surfaces.
Direct3D9: (ERROR) :Failure trying to create offscreen plain surface
I've found a related topic here where the proposed solution was to call D3DImage.SetBackBuffer() and pass IntPtr.Zero, however I've added this just before the existing call and it didn't solve the issue. I also tried calling Lock() and Unlock() around the SetBackBuffer(... IntPtr.Zero), and that didn't solve the issue either.
At this point I'm wondering if there's a bug in D3DImage or if I should use a different approach altogether. Could I replace my 2 render targets with a D3D swap chain instead, would that allow me to stop having to call SetBackBuffer with a different pointer all the time? I'm a newbie with Direct3D.
EDIT: I looked in the code of D3DImage.SetBackBuffer() using .NET Reflector, and it's creating an InteropBitmap every time. It doesn't do anything in particular for IntPtr.Zero. Since I'm calling this many times per second, perhaps the resources don't have the time to be freed. At this point I'm thinking of using 2 different D3DImages and alternating their visibility to avoid having to call their SetBackBuffer() all the time.
Thanks.
It appears that D3DImage creates a new Direct3D texture every time you set its backbuffer pointer to something different. This is eventually cleaned, but setting it 30 times per second like what I was doing doesn't leave it enough time, and is anyway a big performance killer. The approach I went for was to create several D3DImages, each with its own surface, put them all on top of each other and toggle their Visibility property so only one shows at a time. This seems to work very well and doesn't leak any memory.
I use a D3DImage to display images at a rapid framerate and ran into this same problem. I found out that D3DImage does create a new texture if you set the backbuffer pointer to a different pointer. But if you only change the backbuffer pointer's content (and not the pointer's address) it will not create a new texture.

XNA Lags when window has focus

I'm developing for xna game studion using XNA 3.1, and I've noticed a problem with some games, where they lag despite the system having plenty of resources to handle them, along with an inexplicable excess of processor usage. When the window from the game is in focus, process #1 (in task manager) goes to 100% usage, and the game shows signs of minor lag (largely notable when sound effects are repeated in sequence). When the game loses window focus, it continues to draw and update at real time, but the process usage decreases, and the lag disappears.
I have tested this with various games, and the results remain the same, proving that it has nothing to do with my code or code efficiency.
Is this a problem isolated to Xna 3.1, and is there fix for it? Or do I just have to switch to 4.0 and hope my games don't use anything that isn't backwards compatible?
The problem may occur because of garbage collector. Everytime garbage collector runs, the frame rate may drop for a second or two, though on Windows it shouldnt be a problem.
Add this line to your code and see how much heap memory is generated. Every time the value goes down, garbage collector is ran.
SpriteBatch.DrawInt64(FONT, GC.GetTotalMemory(false) / 1000 /* in kilobytes */, new Vector2(5, 30), Color.White, 0f);
SpriteBatch.DrawInt64 is a SpriteBatch extension which doesnt generate garbage on int, long etc. You can alternatively just use SpriteBatch.DrawString(..., (GC.GetTotalMemory(false) / 1000).ToString(), ... )
SpriteBatchExtensions.cs : http://pastebin.com/z9aB7zFH
XNA, from my experience, runs up to 60 frames per second while in focus, and at about 20 frames per second when out of focus. IF however, you have set IsFixedTimeStep = false; the game will run as fast as it possibly can when the process is in focus. With my game, on my machine, it runs at about 500-700 fps. This is also tied in to the number of Update() calls that occur. So my game is also updating 500-700 times per second.
My bet is that you have disabled the fixed timestep, and the massive number of Update and Draw calls are consuming 100% of your core and it is messing with your music. I would recommend removing the line IsFixedTimeStep = false; if it's there. If that line does not exist in your code, this is not the problem, although I would bet that your Update or Draw is doing more work than it should be.
Just noticed this in my own game, I have a Console.WriteLine statement (for debugging) in my update loop, this causes lots of lag.
XNA add a sleep when the window is not in focus!
I solved this problem some time ago overriding Game class and changing the way the Game class understand its form is active or not.
There is not way, as much as i know, to disable this behaviour without modifying Game class behaviour with code.
In particular, the way i found some time ago is a real hack\quirk!
Very unclean solution, but the only way i found.
public class MyGame
{
private MethodInfo pActivate;
public MyGame()
{
// We need to access base HostActivate method, that unfortunally, is private!
// We need to use reflection then, of course this method is an hack and not a real solution!
// Ask Microsoft for a better implementation of their class!
this.pActivate = typeof(Game).GetMethod("HostActivated", BindingFlags.NonPublic | BindingFlags.Instance);
}
protected sealed override void OnDeactivated(object sender, EventArgs args)
{
base.OnDeactivated(sender, args);
// Ok, the game form was deactivated, we need to make it believe the form was activated just after deactivation.
if (!base.Active)
{
// Force activation by calling base.HostActivate private methods.
this.pActivate.Invoke(this, new object[] { sender, args });
}
}
}

Categories

Resources