The classes look like this:
Game
has-a Player
Player
has-a SpriteInstance
SpriteInstance
has-a List<SpriteInstance>
Each render step, Game calls Draw() on Player. Player calls draw() on SpriteInstance. And draw() looks like this:
public void draw(SpriteBatch spriteBatch, Vector2 offset = default(Vector2), float rotation = 0f)
{
spriteBatch.Draw(texture, offset + pos, null, Color.White, rot+rotation, sprite.origin, 1f, SpriteEffects.None, z);
foreach (var child in children)
{
child.draw(spriteBatch, offset + pos, rotation + rot);
}
}
My expected output is being able to see both the SpriteInstance on the screen, and each texture from each child of SpriteInstance, but my actual output is just the SpriteInstance and none of the children. I have tried using a debugger, but it shows that the child's draw() function is definitely called. And since spriteBatch is a magical black box that's as far as I can go...
Is there something wrong about passing spriteBatch around? Am I passing it by value somehow when it should be passed by reference?
edit: here are all the draw functions
Game
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spriteBatch.Begin();// sortMode: SpriteSortMode.FrontToBack);
player.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
Player
public void Draw(SpriteBatch spriteBatch)
{
sprite.draw(spriteBatch);
}
edit2:
Bringing the spriteBatch.draw() calls out into the foreach loop does make it display, but I don't know what the difference is... it is also not a proper fix.
Try this and let me know if it works.
public void draw(SpriteBatch spriteBatch, Vector2 offset = default(Vector2), float rotation = 0f)
{
spriteBatch.Begin(); //Starts the drawing loop
spriteBatch.Draw(texture, offset + pos, null, Color.White, rot+rotation, sprite.origin, 1f, SpriteEffects.None, z);
foreach (var child in children)
{
child.draw(spriteBatch, offset + pos, rotation + rot);
}
spriteBatch.End(); // This is for ending the drawing loop.
}
If that doesn't work I would like to see your main class, and a copy of the output you are getting when you run the application. Please also list any errors that occur.
Related
Currently in my game i want trying to move my object towards both x axis and y axis.As I also wanted to put it into center ,I have put a camera.Here is my Camera code-
public class Camera
{
public Matrix transform;
public Viewport view;
public Vector2 origin;
Vector2 baseScreenSize = new Vector2(1136, 720);
float horScaling ;
float verScaling ;
Vector3 screenScalingFactor ;
public Camera(Viewport newView)
{
view = newView;
horScaling = view.Width / baseScreenSize.X;
verScaling = view.Height / baseScreenSize.Y;
screenScalingFactor = new Vector3(horScaling, verScaling, 1);
}
public void update(GameTime gt, ball pl)
{
origin = new Vector2(pl.Position.X + (pl.ballRectangle.Width / 2) - 400, 0);
transform = Matrix.CreateScale(1,1,0) *
Matrix.CreateTranslation(new Vector3(-origin.X, -origin.Y, 0));
}
}
and in Game1.cs file as usual in begin statement i am putting this-
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null, cm.transform*globalTransformation);
ba.Draw(spriteBatch, Color.White);
spriteBatch.End();
Here ba is the object of ball,its just have moving x and y functionalities.
In a separate begin,end statement ,I am drawing rest all of the objects-
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null, globalTransformation);
spriteBatch.Draw(mainMenu, new Vector2(0, 0), Color.White);
spriteBatch.Draw(mainMenu1, new Vector2(450, 100), Color.White);
spriteBatch.End();
Here Have applied globaltransformation to acheive independent screen resolution(similar codes like in Camera.cs).
Rest of the objects are working as expected,But intersections of camera object and rest of the objects is not working as expected.
I guess this is due to resolution independency is not applied to Camera object(I am not sure).I have tried lot of codes after searching internet,but none of them is working as expected.
In a simple words-I want to clone this game-
https://play.google.com/store/apps/details?id=com.BitDimensions.BlockyJump
If you see main player is moving along x and y axis,but due to camera its in constant position,but the obstacles are not in camera,How to acheive the intersection between obejct which is in camera draw and objects which are not in camera in this case
Request all to help,I am stuck here from long time...
Never thought this will be this much of easy...Searched all over internet,in
most of the codes they were saying we need to inverse the camera transform.
But this is not the case.As from beginning I was saying my problem is intersection between camera object and non camera object,here is the answer-
First of all we need to find the positions of camera object to form a world space rectangle
Vector2 hj = Vector2.Transform(ba.Position, cm.transform);
Rectangle leftRectangleT1 =
new Rectangle((int)hj.X, (int)hj.Y, ba.tex.Width, ba.tex.Height);
Here ba is the camera object,we need to transform it to camera transform like above codes.
To get transform of ba in case pixel intersection,here is the codes-
Matrix ballTransform = Matrix.CreateTranslation(new Vector3(hj.X, hj.Y, 0.0f));
Thats it you have ball rectangle which is camera object to intersect with real world objects(non camera objects)
I don't understand your question per say, but from what I gathered, you want the camera to follow the target's position, and you also want independent screen resolutions?
Well, for the independent screen resolution, simply create a screen resolution handler that renders the scene to a RenderTarget2D as defined by your sizes. Then draw that to the screen.
For the camera movement. Try adjusting the camera's position to follow the target's position with an offset and slerp interpolation to prevent stuttering and smooth action.
void Update(float gameTime) {
Vector3 camTransform = Camera.Position + cameraTarget;
Vector3 newCameraPosition = Vector3.Slerp(cameraPosition, camTransform, 0.2f);
Camera.Position = newCameraPosition;
}
For your intersection problem try something along this
private bool intersects(rectangle1, rectangle2) {
return rectangle1.x >= rectangle2.x &&
rectangle1.y >= rectangle2.y &&
rectangle1.y <= rectangle2.y + rectangle2.h &&
rectangle1.x <= rectangle2.x + rectangle2.w;
}
private void checkIntersections(gameObjects[]) {
foreach (var obj in gameobjects) {
if (intersects(obj.rectangle, camera.rectangle){
handleIntersections(camera, obj);
}
}
}
Is it possible to set the position of a sprite to the exact same position of another sprite which is being moved.
So I want to set the "sprite.position" to a the same position that my class Character is in:
Character.cs:
class Character
{
Texture2D texture;
public Vector2 position;
Vector2 velocity;
public Character(Texture2D newTexture, Vector2 newPosition)
{
texture = newTexture;
position = newPosition;
}
public void Update(GameTime gameTime)
{
position += velocity;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
}
}
Game1.cs:
public class Game1 : Microsoft.Xna.Framework.Game
{
Bullet bullet;
Character player;
protected override void Initialize()
{
allSprites = new List<ISprite>();
allSpriteObstakels = new List<ISprite>();
bullet.position = Character.position; // not working
base.Initialize();
}
}
As the comments have suggested, when you say "it's not working" you need to be clear about what "not working" actually means. For example, are you getting a compile error? Are you getting a runtime exception? Is the game running but it isn't doing what you expect (logical error)?
That said, here's my best guess as to what might be going on:
I don't know if the code above is complete but the bullet and player are not instantiated anywhere. You need to "new" the instances before you use them.
You are using the "bullet.position" where bullet is an instance, but then you're using "Character.position" where Character is a class. Did you intend to use "player.position" instead?
This code will only run once, which means the bullet will be set to the same position as the character. If you intend for the bullet position to always be the same as the character, then you need to continually re-assign the bullet.position value every frame.
But the most important thing is to learn to ask questions so that the community here can help you out.
I'm reading the book "Learning XNA 4.0", and I'm in the object oriented design part. I'm having a weird problem with the collision of 2 rectangles.
I have a list of automateSprite and a Player class both derived from the class Sprite.
In the update method I'm checking the play and the aotomatedSprite rectangles are touching each other, now when I got over the list I have a string called touching that represents the collision.
My problem is the veriable touching, only change if the player Sprite touch the last automateSprite in the list.
The code that the book offer for testing is to do Game.Exit() if any collison was found.
That work on every automatedSprite in the list, but when I change it to my simple test, it acts like I only check the last item from a list of 4 automatedSprite.
here is the code:
string touching = "";
public override void Update(GameTime gameTime)
{
// TODO: Add your update code here
player.Update(gameTime, Game.Window.ClientBounds);
foreach (Sprite sprite in spriteList)
{
sprite.Update(gameTime, Game.Window.ClientBounds);
if (sprite.collisionRect.Intersects(player.collisionRect))
touching = "touching";
else
touching = "not touching";
}
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
spriteBatch.DrawString(font, touching, Vector2.Zero, Color.Red);
player.Draw(gameTime, spriteBatch);
foreach (Sprite sprite in spriteList)
{
sprite.Draw(gameTime, spriteBatch);
}
spriteBatch.End();
base.Draw(gameTime);
}
Edit-------------------------------------------------------------------------
solution:
I ask it in the game devlopment section and I got an answer.
I had to have a break; in the foreach loop so it will not keep going after the it found a collison.
It is because your code constantly overwrites the touching variable, so in the end only the last result is presented in it.
Before the foreach, reset the touching variable, with touching = ""; and extend the if like this:
if (sprite.collisionRect.Intersects(player.collisionRect) || touching == "touching")
This way you will get "touching" if any of the sprites are touching your players sprite.
i just try draw a simple 3d model(many model (.fbx) tested) with basicEffect in xna 4.0 , and there is no other object like 2d spritebatchs or text or ...
but it does not shown correctly , i searched it and did some solution but no one work
like set
graphics.GraphicsDevice.BlendState = BlendState.Opaque;
graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
although i did not draw anything else ! and what is funny i already work with 3d model without problem !
here is my draw code and a result screenshot
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
graphics.GraphicsDevice.BlendState = BlendState.Opaque;
graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
foreach (ModelMesh mesh in m_Model.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
BasicEffect effect = (BasicEffect)meshPart.Effect;
effect.View = Matrix.CreateLookAt(new Vector3(0, 100, 1000), Vector3.Zero, Vector3.Up);
effect.World = bones[mesh.ParentBone.Index] * (Matrix.CreateWorld(Vector3.Zero, Vector3.Right, Vector3.Up));
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.0001f, 1000000f);
effect.EnableDefaultLighting();
}
mesh.Draw();
}
base.Draw(gameTime);
}
ty for your time
The near clip value in your projection Matrix is most likely causing this. Try setting it to 1.0f instead of 0.0001f. If that doesn't solve the problem completely, bring the far clip down to something like 10000f.
edit - noticing that your camera is over 1000 units away from your model, you can even set the near clip to 5f or 10f to gain depth read precision if needed.
Its the problem of depth buffer, you are using the spritebrite to draw something which changes your default depth buffer off.
Make it on before drawing 3d model mesh.
After calling SpriteBatch.End(), add this code:
device.DepthStencilState = DepthStencilState.Default;
I am having some issues with my mouse coordinates in XNA - the 0x0 is arbitrarily near (but not in) the top left corner of my screen.
I am running the game in a windowed mode right now, but the coordinates are based off the screen, not the game window (even though the XNA documentation tells me it should be otherwise)
Thanks in advance!
Here's the code:
namespace TheGame
{
class Mousey
{
static public Vector2 pos;
static private Texture2D tex;
static public MouseState mouseState;
static public MouseState previousState;
//static public Mousey()
//{
//}
static public void Update()
{
previousState = mouseState;
mouseState = Mouse.GetState(); //Needed to find the most current mouse states.
pos.X = mouseState.X; //Change x pos to mouseX
pos.Y = mouseState.Y; //Change y pos to mouseY
}
//Drawing function to be called in the main Draw function.
static public void LoadContent(ContentManager thecontent)
{
tex = thecontent.Load<Texture2D>("mousey");
}
static public void Draw(SpriteBatch batch) //SpriteBatch to use.
{
batch.Draw(tex, pos, Color.White); //Draw it using the batch.
}
static public bool LBP()
{
if (mouseState.LeftButton == ButtonState.Pressed && previousState.LeftButton == ButtonState.Released)
{
return true;
}
else
{
return false;
}
}
}
}
In game.cs:
//sets the windows mouse handle to client bounds handle
Mouse.WindowHandle = Window.Handle;
private IntPtr intPtr;
public MouseControle(int w, int h, IntPtr intPtr)
{
screenwidth = w;
screenheight = h;
this.intPtr = intPtr;
Mouse.WindowHandle = intPtr;
}
This works for me ;)
To use this, I add this to my game-component using that class:
mouse = new MouseControle(((Game1)Game).setscreen.width,
((Game1)Game).setscreen.height,
((Game1)Game).Window.Handle);
Hope this helps sombody :D
Did you try something simpler like this?
protected override void Draw( GameTime gameTime )
{
graphics.GraphicsDevice.Clear( Color.CornflowerBlue );
base.Draw( gameTime );
MouseState current_mouse = Mouse.GetState();
Vector2 pos = new Vector2(current_mouse.X, current_mouse.Y);
batch.Draw(tex, pos, Color.White);
}
There may be some time between draw and update, due to the way timing works in XNA, maybe is this the cause of the perceived pixel offset?
And... are you sure you "configured" your sprite batch correctly? Coordinates are relative to game window, so the documentation say.
Another thing: Why are you using static fields? I really don't like this choice, an anti-pattern. Use class fields, not static fields.
Also... i guess you are drawing a mouse icon, right? consider that XNA start to draw the texture from the specified point, are you sure the texture is well shaped with the top-left point as your mouse arrow end?
I found a nice example here you may like: http://azerdark.wordpress.com/2009/07/08/displaying-cursor-xna/
Consider also that you can enable and disable the normal windows OS mouse cursor with IsMouseVisible = true;
Your draw call is not offsetting the texture at all. If the "pointer" part of your image isn't in the 0,0 position (top left) of your Texture, the positioning will seem off.
Add a Console.WriteLine(pos); to your update to see the position it is drawing to. Remember to remove this after your debugging because writeline will kill your performance.
Try one of the overloaded SpriteBatch.Draw() calls which factor in an "origin" which lets you decide which point of the texture should be drawn at the position. In the following code tweak the Vector 2 based upon how your texture is drawn.
batch.Draw(tex, pos, null, Color.White, 0.0f, new Vector2(10, 10), SpriteEffects.None, 0.0f);