If i have a class where it display font and images that contains its own draw function that has SpriteBatch.Being and .End
And i have another function that iterates draw function 1000 of times!
My question is that will those 2 lines of code slow down the performance:
spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);
spriteBatch.End();
Where the alternative is to have another class that manages the draw function without repeating those 2 lines of codes 1000s of times.
#Daniel G and #RaZeR RawByte have a point. But lets say you want to draw your (lets say) ships on map with neon effect, and all the bullets pixelarated. That means you'll have 2 types of SpriteBatch.Start(). It's better to draw those 2 classes separately inside the class in witch they'll be used (lets say Level.cs).You'll most likely have just 1 instance of Level.cs.
So, instead of having
public void Draw(SpriteBatch sp)
{
SpriteBatch.Begin(*whatever effect you want*);
SpriteBatch.Draw(*draw however you want*);
SpriteBatch.End();
}
In every instance of Ship.cs and Bullet.cs, have them have functions like this:
public void Draw(SpriteBatch sp)
{
SpriteBatch.Draw(*draw however you want*);
}
And in Level's function Draw(SpriteBatch sp) put
public void Draw(SpriteBatch sp)
{
// Draw all ships
SpriteBatch.Begin(*whatever effects you want for ships*);
foreach(Ship s in shipList)
s.Draw(sp);
SpriteBatch.End();
// Draw all bullets
SpriteBatch.Begin(*whatever effects you want for bullets*);
foreach(Bullet b in bulletList)
b.Draw(sp);
SpriteBatch.End();
}
And in Game1.cs, when drawing level, simply send it the spriteBatch variable, like this: myLevel.Draw(spriteBatch);, without calling spriteBatch.Begin() in Draw of Game1.cs
I would not recommend to call Begin and End for every draw call. SpriteBatch puts your draw calls into an queue, so your drawing code will be interpreted as fast as possible (you can sort sprites by their depth, or by texture, for example - SpriteBatch will do all the dirty work).
You should call Begin and End only when you begin and end all of your 2D drawing, or when you change SortMode, etc.
Only call spritebatch begin and end if you are going to draw, but if your method that's drawing is inside a begin and end block, then you don't need it. I suggest making a "draw" method for your class, then in the Game1.Draw method you can call that method, instead of calling it inside a custom class. Game1.Draw is the place to call spritebatch.begin and end, not in a custom class. Hope this helps!
Related
Good day everyone.
I'm trying to draw the text "Pass Complete!" to screen with this code:
spriteBatch.DrawString(font, "PASS COMPLETE!", new Vector2(30, 130), Color.White);
Which does fire off the proper IF statement. However, how do I go about then removing that text from the screen? I'm really not sure at all where to go on from here and my instructor wants me to google the answer or find it in textbook. I have been all over my XNA textbook and I have found no outlet to removing that text.
Thanks for any and all help.
Update:
protected override void Draw(GameTime gameTime)
I have the IF statement included in here. Basically it checks collision with p_Receiver and if it the bool checks out, it draws the DrawString. Should I maybe be looking at this from a different angle?
Final:
I went ahead with the following as the answer and it's working better then before. :)
if (PassInfo == 3) {
(timer code)
(IF timer not "used up" then run the draw)
Working good for now.
I appreciate it.
I'm doing this by function that add text with some parameters into generic list. and then i update and draw items from that list. in pseudo code:
function addText(text,position,duration)
texts.add(new t(text,position,duration))
end function
function updateText()
for each t as text in texts.findall(where t.active)
t.duration -= 1
if t.duration < 0 then t.active = false
next
end function
function drawText()
for each t as text in texts.findall(where t.active)
//draw it
next
end function
so by this you can add unlimited number of texts on different position and duration on screen.
A lot of games redraw the entire window / screen each time through the draw cycle so there's a distinct chance that the solution to removing it is simply to stop drawing it.
i.e. have your if condition not draw the text when it is no longer required.
If, on the other hand, you've some more complex drawing logic that only draws portions of the window / screen that need updating then you'll need to include logic to redraw that part of the screen that contained the text once it is no longer needed.
I've always had issues with classes, and I'm not sure if this is possible.
I'm trying to create a class with an identifiable name.
I realize that that isn't clear, but my overall goal is to create a grid-like game and each square in the grid would be a member in the class.
So for example, I would have a class called square and say in my code
square(16,47).isdead = true;
Basically, I want to know if it is possible to create a class where I can differentiate between at least a hundred different squares.
Also, not sure if this matters, but I am using sprite kit.
Several ways to do what you want, I would prefer the below method.
C style two dimensional array:
Square * squares[10][10];
And you encapsulate that in a class called SquareManager with a method:
-(Square*) aSquareManager squareX:(short)x Y:(short)y;
If you specifically want the access pattern described in your question you can use (credit goes to arturgrigor):
#define square(x, y) [aSquareManager squareX:x Y:y]
Then you can access all of your squares this way:
if ([aSquareManager squareX:16 Y:47].isdead==true) [self showSkullForSquare:[aSquareManager squareX:16 Y:47]];
A different approach would be that a square has x and y properties:
Square.h
#property short y;
#property short x;
And then you put them all into an array, and when you need a square you search through the array.
for(Square * aSquare in squares) {
if(aSquare.x==anXValue && aSquare.y==anYValue) {
return aSquare;
}
}
Functions like these are much quicker than you think.
I have created a single player game using iOS + Cocos2d + Chipmunk and I'm looking for a solution that demonstrates how to attach multiple collision shapes to a single rigid body. I have a target that has an irregular shape (a car) that I need to detect collisions for. The target (car) is seen by the player from a side view and other objects may impact the target from multiple directions, not just from the front or the rear. The shape is such that I am unable to use a single cpPolyShape and achieve a realistic collision effect. Two cpPolyShapes (rectangular) stacked on top of each other, with the bottom rectangle being larger should do the trick.
Can someone provide a example of how this can be achieved?
I read the Chipmunk docs about cpShape, http://code.google.com/p/chipmunk-physics/wiki/cpShape, and it states that 'You can attach multiple collision shapes to a rigid body' in the very bottom of the page in the notes section, but no example is provided.
I currently have a working, functional project and am trying to make some final adjustments to improve game play.
When you call cp*ShapeNew(), the first parameter is the body to attach it to. Simple make more than one shape that share the same body. There is no trick.
You can add the method
In the .h file add the prototype
static int FunctionName (cpArbiter *arb, cpSpace *space, void *unused);
Now in the .m file add the code as
cpSpaceAddCollisionHandler(<space name>, <cpCollisionType of body a >, <cpCollisionType of body b>, <cpCollisionBeginFunc name>, <cpCollisionPreSolveFunc preSolve>, <cpCollisionPostSolveFunc postSolve>, <cpCollisionSeparateFunc separate>, <void *data>);
static int FunctionName(cpArbiter *arb, cpSpace *space, void *unused)
{
cpShape *a, *b; cpArbiterGetShapes(arb, &a, &b);
printf("\n Collision Detected");
return 1;
}
Note:- Don't Forget to give the collision type of both Body.
I'm using SlimDX for a Direct3D 10 apps. In the apps I've loaded 2 to more mesh, with images loaded as texture and using a fx code for shader. The code was modified from SlimDX's sample "SimpleModel10"
I move the draw call, shader setup code into a class that manage 1 mesh, shader (effect) and draw call. Then I initialize 2 copy of this class, then call the draw function one after another.
The output, no matter how I change the Z position of the mesh, the one being draw later will always stay on top. Later, when I use PIX to debug the draw call, I found out that the 2nd mesh doesn't have depth while the first one does. I've tried with 3 meshes, 2nd and 3rd one will not have depth too. The funny thing is all of then are instantiated from the same class, using the same draw call.
What could have cause such problem?
Following is part of the code in the draw function of the class, I've omitted the rest as it's lengthy involved a few classes. I keep the existing OnRenderBegin() and OnRenderEnd() of the sample:
PanelEffect.GetVariableByName("world").AsMatrix().SetMatrix(world);
lock (this)
{
device.InputAssembler.SetInputLayout(layout);
device.InputAssembler.SetPrimitiveTopology(PrimitiveTopology.TriangleList);
device.InputAssembler.SetIndexBuffer(indices, Format.R32_UInt, 0);
device.InputAssembler.SetVertexBuffers(0, binding);
PanelEffect.GetTechniqueByIndex(0).GetPassByIndex(0).Apply();
device.DrawIndexed(indexCount, 0, 0);
device.InputAssembler.SetIndexBuffer(null, Format.Unknown, 0);
device.InputAssembler.SetVertexBuffers(0, nullBinding);
}
Edit: After much debugging and code isolation, I found out the culprit is Font.Draw() in my DrawString() function
internal void DrawString(string text)
{
sprite.Begin(SpriteFlags.None);
string[] texts = text.Split(new string[] {"\r\n"}, StringSplitOptions.None);
int y = PanelY;
foreach (string t in texts)
{
font.Draw(sprite, t, new System.Drawing.Rectangle(PanelX, y, PanelSize.Width, PanelSize.Height), FontDrawFlags.SingleLine, new Color4(Color.Red));
y += font.Description.Height;
}
sprite.End();
}
Comment out Font.Draw solve the problem. Maybe it automatically set some states which causes the next Mesh draw to discard depth. Looking into SlimDX's source code now.
After much debugging in PIX, this is the conclusion.
Calling Font.Draw() will automatically set DepthEnable to false and DepthFunction to D3D10_COMPARISON_NEVER, that's after comparing PIX's detail on the OutputMerger of before and after calling Font.Draw
Solution
Context10_1.Device.OutputMerger.DepthStencilState = depthStencilState;
Put that before the next Mesh draw call fixed the problem.
Previously I only set the DepthStencilState in the OnRenderBegin()
I'd like to send my view vector to an ID3D10Effect variable in order to calculate specular lighting. How do I send a vector or even just scalar values to the HLSL from the running DirectX program? I want to do something like
render() {
//do transformations
D3DXMatrix view = camera->getViewMatrix();
basicEffect.setVariable(viewVector, view);
//render stuff
}
Use GetVariableByName to get an interface to the named variable in the HLSL. Call AsVector (Note the documentation at this point is wrong. It returns a pointer!) on the returned interface to get a vector variable interface and then call SetFloatVector.
In your effect, you should have something like:
cbuffer {
float4x4 viewMatrix;
}
Then in your render function, before binding the effect:
D3DXMatrix view = camera->getViewMatrix();
basicEffect->GetVariableByName("viewMatrix")->AsMatrix()->SetMatrix((float*) &view);
As with most effect attribute handles, I would suggest 'caching' the pointer to the variable. Storing the matrix variable in another pointer outside of your render loop, like:
ID3D10EffectMatrixVariable* vmViewMatrix = basicEffect->GetVariableByName("viewMatrix")->AsMatrix();
And then setting the variable turns into:
vmViewMatrix->SetMatrix((float*) &view);