I'm trying to make a turn-based roguelike engine thing for XNA. I'm basically porting the game over from a previous work I did using an SDL-based roguelike library called libtcod. How can I modify the basic XNA template thing to make the game not redraw the screen every frame, but, instead, when I want?
The correct method for doing this is to call GraphicsDevice.Present() whenever you want to draw the back buffer onto the screen.
Now the difficulty here is that the Game class automatically calls Present for you (specifically in Game.EndDraw), which is something you don't want it to do. Fortunately Game provides a number of ways to prevent Present from being called:
The best way would be to override BeginDraw and have it return false, to prevent a frame from being drawn (including preventing Draw and EndDraw from being called), like so:
protected override bool BeginDraw()
{
if(readyToDraw)
return base.BeginDraw();
else
return false;
}
The other alternatives are to call Game.SuppressDraw, or to override EndDraw such that it does not call base.EndDraw() until you are ready to have a frame displayed on screen.
Personally I would simply draw every frame.
You don't need to inherit from Game class, it is entirely optional. You can write your own class which redraws the screen only when you want. There's some useful code in the class though, so you can use Reflector to copy code from there and then change its logic.
Related
I'm trying to make a floor for a top down style game, where I used to use pictureboxes
I was told that instead of using a Picturebox, I should be using the Graphics.DrawImage(); method, which seems to slightly help but still is very laggy.
My paint function looks like this to draw the background looks like this:
How should I make the drawing less laggy? The image is 2256 by 1504
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(PeanutToTheDungeon.Properties.Resources.tutorialFloor, 0, 0);
}
There are two points that I would make here.
Firstly, DO NOT use Properties.Resources like that. Every time you use a property of that object, the data for that resource gets extracted from the assembly. That means that you are creating a new Image object every time the Paint event is raised, which is often. You should use that resource property once and once only, assign the value to a field and then use that field repeatedly. That means that you will save the time of extracting that data and creating the Image object every time.
The second point may or may not be applicable but, if you are forcing the Paint event to be raised by calling Invalidate or Refresh then you need to make sure that you are invalidating the minimum area possible. If you call Refresh or Invalidate with no argument then you are invalidating the whole for, which means that the whole form will be repainted. The repainting of pixels on screen is actually the slow part of the process, so that's the part that you need to keep to a minimum. That means that, when something changes on your game board, you need to calculate the smallest area possible that will contain all the possible changes and specify that when calling Invalidate. That will reduce the amount of repainting and speed up the process.
Note that you don't need to change your drawing code. You always DRAW everything, then the system will PAINT the part of the form that you previously invalidated.
I'm finding it difficult implementing an undo feature for a game that I have developed using c# forms. I would like to have a button on the game screen which ,when clicked, reverses the move the player just made.
Anyone have an ideas how I would go about doing this ? I have been told that a stack is the best way to go about doing this but I'm unsure how to implement it.
You can wrap your game events into actions that can have methods Do() and Undo().
Lets take Paint program as an example. User draws line on the given coordinates, you put LineDrawnEvent on the stack with all related data, and invoke Do() method, which actually draws a line on the canvas. When user clicks undo button, you pop item from your stack and invoke Undo() method, which in LineDrawnEvent should remove the line which user has drawn.
You can also have interface for that, something like IProgramAction with Do() and Undo() methods, so you can have different events, for example CircleDrawnEvent and RectangularDrawnEvent in the same stack.
And stack in your code will look something like
public Stack<IProgramAction> ProgramStack { get; set; }
I am pretty sure something like this has been asked before, but I haven't been able to find it. Anyway, I am making a simple game animation with two moving objects (halloween themed). The objects bounce off the walls when they hit them, but I also need an image to be displayed when the two objects hit eachother. I have tried multiple ways, but none of them work. They either have no effect or raise an error. Anyway, here is the last thing I tried:
public PumpkinCheckCollisionPumpkin(GameTime gameTime)
{
if (pumpkin1.BoundingBox.Intersects(pumpkin2.BoundingBox))
{
pumpkinCollide = True;
Draw(gameTime);
}
I then tried passing the that bool (which I set to false earlier) to the draw section, but it did not work. The above method is called within the Update method.
I tried having the draw method invoked in the Update (GameTime gameTime) part, but that didn't work either. How do I trigger another image to be displayed in addition to what is already is displayed when my two objects collide? (also, that public method was originally private but made it public so another tactic I tried might work(didn't work)).
The answer is pretty simple, never directly call the Draw function.
In this case, I would set a class level state variable that holds the fact that a collision graphic should be drawn on the next draw call, which can then happen.
You erase every time you draw anyways, so even if the call did work correctly, the next Draw call (which will happen really soon) would erase it. For the same reason, don't unset the flag after the Draw call happens, because it will get erased faster than your players can see it. You need to keep it on the screen for some time.
You could do this by setting a variable that holds the time when the flag was set, then checking it against the current time until enough "visible" time has passed. This would then clear the "show collision" flag, and the graphic would no longer draw.
Just let the framework handle the timing of that call, and let the state you set drive what is drawn.
Okay, so here we go. I'm attempting to make an application, using XNA as the base because of its renderer. One of the things that is necessary in this project is to open a new window (as a dialog), in which is embedded a separate XNA render panel. I'm using this as an interactive preview panel, so I absolutely need XNA to render in there. However, it seems XNA is not very well equipped to do this. I have tried various things myself, but to no avail (either producing errors and not rendering correctly, or rendering in the wrong aspect ratio, etc.). Normally, I would post code here, but since I have had such little luck, there isn't much to post.
My application currently consists of an XNA application embedded within a Form, and I have a button to open the preview panel, which in theory should pop up as a Form Dialog, containing the XNA renderer, to allow me to draw the preview. I have been trying this for several hours, and got nowhere, so I'm asking for a bit of help here.
Thanks, anyway.
EDIT: Okay, I've made a little progress, but I have 2 problems. Firstly, any textures drawn with a sprite batch appear the right dimensions, but filled with solid black. Also, when I open the dialog, and then close it, and close the application, I get an AccessViolationException. I strongly suspect the two errors are linked in some way.
Here is my code initialising the preview dialog. (a is a custom class that essentially consists of a LinkedList of Texture2D objects).
animPrev = new AnimationPreview(a);
animPrev.Show();
My AnimationPreview class is an extension of the Form class, and contains a PreviewControl object, which is an extension of the GraphicsDeviceControl found in the XNA Winforms sample. Note that my main form extends the XNA Game class, for various reasons.
The PreviewControl object is set up like this:
protected override void Initialize()
{
sb = new SpriteBatch(GraphicsDevice);
Application.Idle += delegate { Invalidate(); };
}
And the Draw method contains:
protected override void Draw()
{
GraphicsDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.Violet);
if (frame != null)
{
sb.Begin();
sb.Draw(Image, Vector2.Zero, Color.White);
sb.End();
}
}
This clears the background of the form violet, as expected, and draws a black box of the same size as Image. This is not expected. Hopefully someone can help me out here.
NOTE: An acceptable alternative would be to convert XNA Texture2D objects to System.Drawing.Image objects. However, I am using XNA 3.1, so I can't just save the texture to a stream and reload it.
Actually, after having tried this, it's a bit dodgy, and very slow, so I'd rather not do it this way.
Did you take a look at the following official tutorials / samples?
XNA WinForms Series 1: Graphics Device
XNA WinForms Series 2: Content Loading
They should explain everything in my opinion. You even find downloadable source for the samples.
I'm quite new in XNA C# and I would like to know how do I create a model in XNA C# that will blink every second. I'm trying to make an invulnerability effect for my model.
Currently, my own idea is that I will set the visible of my model to false and true every second.
Thanks.
EDIT: I cannot find any model.visible = false in XNA C#??
Your idea is fine, but you'll need to track whether it should be visible or not yourself, and only draw it when it's visible. Every object gets explicitly redrawn by your code every frame; so simply don't draw it when it shouldn't be visible.
There is no built-in way to do this (that I know of); it wouldn't make much sense if there were, since you'd be calling a drawing function on invisible objects. Not drawing invisible objects in the first place makes more sense.
To get the blinking to work, you'll need to track how much time has elapsed since the last time the visibility was flipped, and toggle the visibility when that time exceeds one second. For example, in your Update() method, you'd have something like this:
if (gameTime.TotalGameTime.TotalMilliseconds >= nextBlinkTime) {
modelVisibility = !modelVisibility;
nextBlinkTime = gameTime.TotalGameTime.TotalMilliseconds + 1000;
}
For more complex scenarios (e.g. multiple models need visibility toggled, etc.), I suggest you abstract this behaviour away into a reusable class.