So I'm working on my menu's background and I Draw() a texture there with a rectangle. How would I have the rectangle wait, move up and then down, wait and repeat? I tried the following:
// Update()
if (Rectangle.Y = -16) // My texture is positioned to -16 initially
Rectangle.Y++;
else if (Rectangle.Y = 0)
Rectangle.Y--;
So my game resolution is 1366x768. To have the background texture move up and down I had to make it have a height > 768. I made it 1366x800. Every time the above code is called it should wait 1-2seconds (not yet implemented), move 16 pixels down, wait again and go back 16 pixels up... But that code doesn't work... Could you guide me as to how this is done?
You can do it with Math.Sin, which will give you a smooth transition from -1 to 1. You will have to keep a copy of your rectangle's center Y position.
double time = gameTime.TotalGameTime.TotalSeconds;
Rectangle.Y = centerY + (int)(Math.Sin(time * transitionSpeed) * maxOffset);
You can play with double transitionSpeed to get the best visual effect. int maxOffset is the max amount of offset from centerY.
If you don't want smooth movements, then just do
int speed = 1; // speed of movement
Then in update
if (Rectangle.Y <= -16 || Rectangle.Y >= 0)
speed *= -1; // reverse move direction
Rectangle.Y += speed;
Related
I'm trying to implement a smooth slow down scroll based on the velocity of the user gesture.
I'm using MR.Gestures to handle the pan gesture and obtain the velocity, then I'm running an animation loop to perform the deceleration but it's very jerky and I'm not sure what I can do to make it smooth.
_velocityX = (velocityX / (1000 / SCROLL_INTERVAL));
_velocityY = (velocityY / (1000 / SCROLL_INTERVAL));
I have SCROLL_INTERVAL set to 16 to scroll at roughly 60fps. My _friction variable is currently 0.98f.
In my animation loop I have the following:
var distance = new Point
{
X = 0,
Y = 0
};
if (Math.Abs(_velocityX) > 0)
{
distance.X += _velocityX;
_velocityX *= _friction;
}
if (Math.Abs(_velocityY) > 0)
{
distance.Y += _velocityY;
_velocityY *= _friction;
}
<snip>code here moves the camera by the values in distance.X and distance.Y</snip>
Now, this works but is very jerky and the issue appears to be that it may be moving by 10+ pixels at the start of the animation.
I believe based on this that my approach is incorrect but I can't find anything to help me change the approach.
Is there a better way to do this? Or a way to make this more smooth?
I am facing an issue with Forms Graphics, as this is my first project on it. I'll try to simplify my issue as possible as I can.
I have a code in which, 1. A smaller circle revolves around bigger (// Animation 1) & 2. Drawing rectangle to form a wave line(// Animation 2).
while (true)
{
// Issue line
g.Clear(Color.White);
g.DrawEllipse(pen, mainCircle);
loc = nextPoint(radius, angle, cntr_mainCircle);
innerCircle.X = loc.X - (innerCircle.Width / 2) + mainCircle.X;
innerCircle.Y = loc.Y - (innerCircle.Height / 2) + mainCircle.Y;
//Animation 1
g.DrawEllipse(pen, innerCircle);
//Animation 2
g.DrawLine(pen, cntr_mainCircle.X + 30, cntr_mainCircle.Y + 30, innerCircle.X + innerCircle_lenX / 2, innerCircle.Y + innerCircle_lenY / 2);
g.FillRectangle(Brushes.Red, startIndex, innerCircle.Y + 25, 3, 3);
fg.DrawImage(btm, new PointF(20, 20));
if (angle < 360)
{
angle += 1.0f;
}
else
{
angle = 0;
}
startIndex++;
}
I am getting a problem with line g.Clear(Color.White);. It clears the entire screen, but I requirement is to clear // Animation 1 and not clear // Animation 2
Above code gives below output. The circle animation is correct as intended, but if you see.. there's a small RED rectangle which animates like a wave.. but because of Clear() the wave gets erased.
I need a wave to look like below.(Below output is when I remove the // Issue line or say Clear() function)
My expectation output is as below, i.e Circle animation (// Animation 1) which is clearing screen and doing motion animation & Wave animation (// Animation 2) which should not be clearing previously drawn rectangles.
I need suggestions to correct my code or I am even open for suggestions for applying a new approach if the current code is not upto the standards.
I'm having a little trouble with a texture2d I'm trying to draw in XNA. Basically, I have a power-up "cooldown fill-effect" going on. I have a texture that I'm trying to draw partially as the cooldown decreases. So, for example, at 10% cooldown done I'm drawing only 10% cooldown of of the texture (the bottom), 20% done only 20% of the bottom of the texture, and so on.
The problem I'm having is, when drawing the texture, it keeps wobbling as it fills up.
Note that below, ActiveSkillTexture is my preloaded fill texture. It's size is the size of the fully filled graphic.
InterfaceDrawer.Draw is a method that calls SpriteBatch.Draw, but does some extra stuff beforehand. For all intents and purposes, it's the same as SpriteBatch.Draw.
Scale is my scale factor, it's just a float between 0 and 1.
MyDest is a pre-calculated position for where this texture should draw (from the top-left, as usual).
Here's a snippet of code:
Rectangle NewBounds = ActiveSkillTexture.Bounds;
float cooldown = GetCooldown(ActiveSkillId);
if (cooldown > 0) //cooldown timer
{
//Code that calculated cooldown percent which I'm leaving out
if (percentdone != 1) //the percentage the cooldown is done
{
//code for fill-from bottom --
float SubHeight = ActiveSkillTexture.Height * percentremaining;
float NewHeight = ActiveSkillTexture.Height * percentdone;
NewBounds.Y += (int) SubHeight;
NewBounds.Height = (int) NewHeight;
MyDest.Y += SubHeight * Scale;
}
}
if (ActiveSkillTexture != null)
InterfaceDrawer.Draw(SpriteBatch, ActiveSkillTexture, MyDest, NewBounds, Color, 0.0f, Vector2.Zero, Scale, SpriteEffects.None, 0.0f);
I know you can't see it, but it's basically wobbling up and done as it fills. I tried printing out the values for the destination, the newbounds rectangle, etc. and they all seemed to consistently increase and not "sway", so I'm not sure what's going on. Interestingly enough, if I fill it from the top, it doesn't happen. But that's probably because I don't have to do math to alter the destination position each time I draw it (because it should draw from the top-left corner each time).
Any help would be greatly appreciated. Thanks!
I think this would be easier if you set the Vector2.Origin parameter of your spriteBatch.Draw as the bottom-left of your texture.
In this way you simply increase your sourceRectangle.Height, with something like this:
sourceRectangle.Height = ActiveSkillTexture.Height * percentdone;
without doing that useless math to find the destination position.
I am working on a simple game where you click on square sprites before they disappear. I decided to get fancy and make the squares rotate. Now, when I click on the squares, they don't always respond to the click. I think that I need to rotate the click position around the center of the rectangle(square) but I am not sure how to do this. Here is my code for the mouse click:
if ((mouse.LeftButton == ButtonState.Pressed) &&
(currentSquare.Contains(mouse.X , mouse.Y )))
And here is the rotation logic:
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
RotationAngle += elapsed;
float circle = MathHelper.Pi * 2;
RotationAngle = RotationAngle % circle;
I am new to Xna and programming in general, so any help is appreciated.
Thanks a lot,
Bill
So you're trying to determine if a point is in a rectangle, but when the rectangle is rotated?
The Contains() method will only work if the current rotation is 0 (I guess currentSquare is a rectangle representing the image position without rotation?).
What you will have to do is do the opposite rotation of the image on the mouse coordinates (the mouse coordinates should rotate around the origin of your image), then calculate if the new position is within currentSquare. You should be able to do all of this using vectors.
(Untested)
bool MouseWithinRotatedRectangle(Rectangle area, Vector2 tmp_mousePosition, float angleRotation)
{
Vector2 mousePosition = tmp_mousePosition - currentSquare.Origin;
float mouseOriginalAngle = (float)Math.Atan(mousePosition.Y / mousePosition.X);
mousePosition = new Vector2((float)(Math.Cos(-angleRotation + mouseOriginalAngle) * mousePosition.Length()),
(float)(Math.Sin(-angleRotation + mouseOriginalAngle) * , mousePosition.Length()));
return area.Contains(mousePosition);
}
If you dont need pixel pefect detection you can create bounding sphere for each piece like this.
var PieceSphere = new BoundingSphere()
{
Center =new Vector3(new Vector2(Position.X + Width/2, Position.Y + Height/2), 0f),
Radius = Width / 2
};
Then create another bounding sphere around mouse pointer.For position use mouse coordinates and for radius 1f. Because mouse pointer will be moving it will change its coordinates so you have to also update the sphere's center on each update.
Checking for clicks would be realy simple then.
foreach( Piece p in AllPieces )
{
if ((mouse.LeftButton == ButtonState.Pressed) && p.BoundingSphere.Intersects(MouseBoundingSphere))
{
//Do stuff
}
}
If you are lazy like me you could just do a circular distance check.
Assuming mouse and box.center are Vector2
#gets us C^2 according to the pythagorean Theorem
var radius = (box.width / 2).squared() + (box.height / 2).square
#distance check
(mouse - box.center).LengthSquared() < radius
Not perfectly accurate but the user would have a hard time noticing and inaccuracies that leave a hitbox slightly too large are always forgiven. Not to mention the check is incredibly fast just calculate the radius when the square is created.
I have a simple rectangle-tile collision scheme set up, and it works beautifully.
The only problem is when you start falling off of a ledge. Your speed reaches the point where the change in Y/X each frame is large enough for you to clip into solid objects and glitch about.
Basically my setup is as follows:
To start with, the player's position has its velocity added to it, so the player is now at the place he would be next frame if no collisions happen.
The list below is just a single function, checkIntersectTiles(Vector2 maskPos);
Calculate tiles around the character to check.
Loop through tiles, including those inside the bounding tiles.
Check the player's collision rectangle against each of these tiles.
If there's an intersection, move the largest offending axis out of the tile, then set that axis velocity to 0.
Continue checks.
When you clip into the ground, you jitter around inside, as my algorithm attempts to move you outside the tile that is most colliding with you.
My solution: Check each position from the player's pos, to the player's pos + velocity.
I'm stuck on that bit.
Can anyone give me a hand?
I assume that your code to move the player out of the colliding tile does so in a single step. So if the player collides with a tile you determine that the penetration depth is 5 in the Y direction you immediately adjust the player Y position by -5.
As you suggest, check the player position at each step. So if the Y velocity is 5 then you can adjust the players Y position by 1, check for collision and then repeat 4 more times. See later for calculations handling time stepping. The following is just some basic pseudo code and just in the Y direction.
player.Y += vel;
if (player.CheckCollisions())
{
// handle collision
}
Becomes
for (int i = 0; i < vel; ++i)
{
player.Y += 1;
if (player.CheckCollisions())
{
// handle collision
break;
}
}
That is the simple version if you are not adjusting for ellaped time. If you are, then you rather perform smaller time steps
So
player.Y += vel * elapsedTime;
if (player.CheckCollisions())
{
// handle collision
}
Becomes
float currentTimeStep = 0;
Position startY = player.Y;
while (currentTimeStep < elapsedTime)
{
currentTimeStep = Math.Min(currentTimeStep + stepDelta, elapsedTime); // You need to tune the stepDelta
player.Y = startY + vel * currentTimeStep;
if (player.CheckCollisions())
{
// handle collision
break;
}
}
In the above you will need to tune the time step delta to ensure that you balance performance with accuracy. You might event consider calculating the delta dynamically each frame to ensure that the adjustment is close to 1 pixel.