So I'm pretty new to XNA and C# in general but I'm running into a problem here.
I'm just making this very basic "soccer game" and I have a collision event that when the player runs into the ball, the ball should stay in front of the player while they move around and what not.
But as soon as I run into the rectangle, the ball moves a little bit, but then the rectangle stays where it was and doesn't follow the ball..
Here's what I have..
Vector2 soccerBallPosition = new Vector2(0,0);
Update()
soccerBallBounds = new Rectangle(588, 338, 24, 24);
if (blueTeamCenter.blueTeamCenterBounds.Intersects(soccerBallBounds))
{
soccerBallPosition = new Vector2(blueTeamCenter.BTCmDirection.X + 32, blueTeamCenter.BTCmDirection.Y);
}
Draw()
spriteBatch.Draw(soccerBall, soccerBallBounds, null, Color.White, 0, soccerBallPosition, SpriteEffects.None, 0);
It may be that the snippet is incomplete but I can't pinpoint where the soccerBallBounds move to the new position.
Yous should initialize soccerBallBounds as
soccerBallBounds = new Rectangle(0, 0, 24, 24);
Before checking for collisions call
soccerBallBounds.Offset((int)soccerBallPosition.x,(int)soccerBallPosition.y ). This way your soccerBallBounds will be always updated with the latest ball position.
Check Rectangle.Offset for more information.
Related
I'm developing a 3D application in OpenGL and I want to rotate the objects with the mouse like in AutoCad, SolidEdge or another CAD program. By the way, I'm totally new in 3D programing and OpenGl.
I've tried with GL.Rotate but as far as I know its complicated and not very attratctive for the user because one rotation around one axis affect the others. So I've been searching and I found the quaternions. I thought I understood how they work but when I run the app the GLControl that Im using is totally white. Also In the debugging mode I've seen that the Matrix "Mat" is full with NaN and I think that that's the problem. The AngX and AngY are the angles of rotation that I change in the mousemove
This is what I've done:
The main loop:
Mat = Matrix4d.Identity; //Global
Vector3d vect1 = new Vector3d(0, -1, 0);
Vector3d vect2 = new Vector3d(-1, 0, 0);
QuatRot1 = new Quaterniond(vect1, AngX);//Global
QuatRot2 = new Quaterniond(vect2, AngY);//Global
QuatRot1.Normalize();
QuatRot2.Normalize();
Quaterniond.Multiply(QuatAcc, QuatRot1);
Quaterniond.Multiply(QuatAcc, QuatRot2);
Matrix4d.CreateFromQuaternion(ref QuatAcc, out Mat);// I think the problem is here
AngX = 0;
AngY = 0;
GL.MultMatrix(ref Mat);
The mousemove:
if (WheelPress)
{ //mouse1 previous mouse position
//mouse0 current mouse position
AngY = 0.1f * (mouse1.X - mouse0.X);
AngX = 0.1f * (mouse1.Y - mouse0.Y);
Cursor.Current = Cursors.Hand;
glControl1.Refresh();
}
PS.I don't know if it's important but im working with OpenTK
I have been trying to accomplish this for quite some time with no success; I've looked at several relevant questions here on StackOverflow with no success; I've also followed 6 different tutorials that ALL followed pretty much the same process:
Build the vertices: -1, -1, 0, -1, 1, 0, 1, 1, 0, and 1, -1, 0.
Build the indices: 0, 1, 2, 0, 2, 3.
Create the Vertex and Index buffers.
Clear the RenderTargetView.
Set the current Vertex and Pixel shaders.
Update the constant buffers if you have any.
Render the quad (see below).
Rinse and repeat 4 - 8.
Now, the reason this is driving me up the wall is because I can render far more advanced objects such as:
Spheres
3D Lines
Fans
My code for creating the quad is pretty much the same as everyone else's:
public class Quad {
private void SetVertices() {
float width = Rescale(Size.Width, 0, Application.Width, -1, 1);
float height = Rescale(Size.Height, 0, Application.Height, -1, 1);
vertices = new Vertex[] {
new Vertex(new Vector3(-width, -height, 0), Vector3.ForwardLH, Color.White),
new Vertex(new Vector3(-width, height, 0), Vector3.ForwardLH, Color.White),
new Vertex(new Vector3(width, height, 0), Vector3.ForwardLH, Color.White),
new Vertex(new Vector3(width, -height, 0), Vector3.ForwardLH, Color.White)
}
indices = new int[] { 0, 1, 2, 0, 2, 3 };
vertexBuffer = Buffer.Create(Device3D, BindFlags.VertexBuffer, vertices);
vertexBinding = new VertexBufferBinding(vertexBuffer, Utilities.SIzeOf<Vertex>(), 0);
indexBuffer = Buffer.Create(Device3D, BindFlags.IndexBuffer, indices);
indexCount = indices.Length;
}
public void Render() {
if (shaderResourceView != null)
context3D.PixelShader.SetShaderResource(0, shaderResourceView);
context3D.PixelShader.SetSampler(0, samplerState);
context3D.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;
context3D.InputAssembler.SetVertexBuffers(0, vertexBinding);
context3D.InputAssembler.SetIndexBuffer(indexBuffer, Format.R32_UInt, 0);
context3D.DrawIndexed(totalIndexCount, 0, 0);
}
}
Notes
I am using a right handed coordinate system (for some reason the previous developer hardwired Vector3.ForwardLH into some places that I now cannot get rid of yet); if that helps any and I cannot currently convert to a left handed coordinate system.
Am I missing something here? Why am I unable to render a basic quad?
If you feel more information is needed feel free to let me know and I will add it on request.
When rendering with Direct3D 11, you need to know the all the state. You do not mention what your BlendState, DepthStencilState, or RasterState settings are here which is a likely reason you aren't getting the results you want.
If the DepthStencilState is such set use the Z-Buffer, then the fact that your vertices have a 0 for the Z means they are going to get culled. You can set a depth/stencil state without Z writes or Z tests, and you should definitely turn off Z writes when drawing 2D stuff anyhow. You can also pass something like 0.5 for the Z value for your vertices which is fairly common for 2D drawing with 3D APIs.
If you backface culling enabled in the RasterState, then the winding order of your vertices could result in them being skipped. You can play with different winding orders, or disable culling.
It also really matters what your Vertex Shader and Pixel Shader are here. You don't show the code for setting your shaders or shader constants, and you don't show the HLSL.
You should seriously consider using the SharpDX Toolkit SpriteBatch class for efficient quad rendering or looking at their source for it.
I know you are using SharpDX an C#, but you might find it useful to see the DirectX Tool Kit for DX11 tutorial on drawing 2D shapes.
I am trying to make my opengl program emit balls from a cube. There are two types of balls - a small blue one and a larger orange one. The balls should fall due to gravity. However at the moment it only seems to emit one of each ball and thats it.
I have tried drawing the balls inside a loop, as follows:
for (int i = 0; i < 100; i = i + 1)
{
Matrix4 mSphereOrange = Matrix4.CreateScale(mOrangeRadius) * Matrix4.CreateTranslation(mOrangePosition);
SetUniformVariables(0.19125f, 0.0735f, 0.054f, 1, 0.647f, 0f, 0.256777f, 0.137622f, 0.086014f, 0.5f);
GL.UniformMatrix4(uModelLocation, true, ref mSphereOrange);
GL.BindVertexArray(mVAO_IDs[2]);
GL.DrawElements(BeginMode.Triangles, mSphereModelUtility.Indices.Length, DrawElementsType.UnsignedInt, 0);
Matrix4 mSphereBlue = Matrix4.CreateScale(mBlueRadius) * Matrix4.CreateTranslation(mBluePosition);
SetUniformVariables(0, 0.1f, 0.06f, 0.0f, 0.50980392f, 0.50980392f, 0.50196078f, 0.50196078f, 0.50196078f, 10f);
GL.UniformMatrix4(uModelLocation, true, ref mSphereBlue);
GL.BindVertexArray(mVAO_IDs[2]);
GL.DrawElements(BeginMode.Triangles, mSphereModelUtility.Indices.Length, DrawElementsType.UnsignedInt, 0);
}
Can anyone see why this may not be working? Or suggest a better way to create an emitter?
Any help would be much appreciated,
Lucy
I'm sure that the problem is related with for loop. You create simultaneously 100 orange spheres and 100 blue spheres at the same position.
(Cross post from Gamedevs)
I'm working with Monogame to do a 2d sprite engine. I've gotten it work pretty well where I can move lots of sprites around the screen with the effects and positions that I want.
Last night I tried to add a feature and I can't quite get it to work right.
I'm trying to create permanent trails that the moving sprites can leave behind. So I have a mostly transparent PNG with some white lines on it called "streak". The idea is that I set up a new Texture2D surface (called streakoverlay) and I draw the streaks on to it.
I switch back to the back buffer and draw: The background, the streakoverlay, and finally the sprite on top of it. The streaks should build up over time. It almost works, but the trouble I have is that streakOverlay seems to clear itself every time. How I'd like it to behave would be the same behaviour as having the graphics display without this line GraphicsDevice.Clear(Color.White); - everything would just pile up in it.
Instead it resets back to the Purple transparent color that is the default for that texture. Any suggestions? Here's the core piece of the rendering engine:
GraphicsDeviceManager graphics;
RenderTarget2D streakOverlay;
SpriteBatch spriteBatch;
private Texture2D bkg;
private Texture2D prototype;
private Texture2D streak;
//Initialize
graphics = new GraphicsDeviceManager(this);
GraphicsDevice.Clear(Color.Transparent);
streakOverlay = new RenderTarget2D(GraphicsDevice, 200,200);
//Load Content
bkg = Content.Load<Texture2D>("bkg"); //Background image
prototype = Content.Load<Texture2D>("prototype"); //Prototype sprite that moves around
streak = Content.Load<Texture2D>("blueStreak"); //Trails being left by Prototype sprite
graphics.GraphicsDevice.SetRenderTarget(streakOverlay);
GraphicsDevice.Clear(Color.Transparent); //Attempt to make the streakoverlay is fully transparent.
graphics.GraphicsDevice.SetRenderTarget(null);
//Draw
Random r = new Random();
graphics.GraphicsDevice.SetRenderTarget(streakOverlay); //Switch to drawing to the streakoverlay
spriteBatch.Begin();
//Draw some streaks that should accumulate
spriteBatch.Draw(streak, new Vector2(r.Next(0, 200), r.Next(0, 200)), null, Color.White, 0f, new Vector2(25, 25), 1f, SpriteEffects.None, 1f);
spriteBatch.End();
//Switch back to drawing on the back buffer.
graphics.GraphicsDevice.SetRenderTarget(null);
spriteBatch.Begin();
spriteBatch.Draw(bkg, new Rectangle(0, 0, 2000, 2000), Color.White); //Draw our background
spriteBatch.Draw(streakOverlay, new Vector2(0, 0), Color.White); //Put the overlay on top of it
spriteBatch.Draw(prototype, new Vector2(_spritePrototype.getX, _spritePrototype.getY), null, Color.White, DegreeToRadian(rotationSprite), new Vector2(25, 25), .5f, SpriteEffects.None, 0f); //Draw the sprite that's moving around.
spriteBatch.End();
base.Draw(gameTime);
You need to use the extended constructor for RenderTarget2D that takes 4 parameters and specify PreserveContents. The assumption is that render targets are often reused and so when it is set it gets cleared automatically unless this flag is set.
i have this problem when my Sprite rotation origin is fixed at top left corner of window (same with sprite.Draw and sprite.Draw2D)
Either way if i change rotation center it's still at top left. I need sprite to rotate around its Z axis.
Edit:
I have tried this:
hereMatrix pm = Matrix.Translation(_playerPos.X + 8, _playerPos.Y + 8, 0);
sprite.Transform = Matrix.RotationZ(_angle) * pm;
sprite.Draw(playerTexture, textureSize, new Vector3(8, 8, 0), new Vector3(_playerPos.X, _playerPos.Y, 0), Color.White);
But it does not seem to works well...
When you draw it, is it in the correct place?
I believe that the multiplication order is reversed, and that you shouldn't be transforming by the players position in the transform.
// shift centre to (0,0)
sprite.Transform = Matrix.Translation(-textureSize.Width / 2, -textureSize.Height / 2, 0);
// rotate about (0,0)
sprite.Transform *= Matrix.RotationZ(_angle);
sprite.Draw(playerTexture, textureSize, Vector3.Zero,
new Vector3(_playerPos.X, _playerPos.Y, 0), Color.White);
Edit
You could also use the Matrix.Transformation method to get the matrix in one step.
I've got the solution for you, it's a simple method that you can use everytime you want to draw a sprite.
With this method you will be able to rotate the sprite with your desired rotation center.
public void drawSprite(Sprite sprite, Texture texture, Point dimension, Point rotationCenter, float rotationAngle, Point position)
{
sprite.Begin(SpriteFlags.AlphaBlend);
//First draw the sprite in position 0,0 and set your desired rotationCenter (dimension.X and dimension.Y represent the pixel dimension of the texture)
sprite.Draw(texture, new Rectangle(0, 0, dimension.X, dimension.Y), new Vector3(rotationCenter.X, rotationCenter.Y, 0), new Vector3(0, 0, 0), Color.White);
//Then rotate the sprite and then translate it in your desired position
sprite.Transform = Matrix.RotationZ(rotationAngle) * Matrix.Translation(position.X, position.Y, 0);
sprite.End();
}