How to animate a simple shape moving vertically? - c#

So, I have a rectangle "rectangle1", at 160,160.
I want it to move smoothly to cordinates 160,30, with a duration of about 1 second. (time delay)
I've figured out that some basic code to move the shape is
rectangle1.Location = new Point(160,30);
However, when I tried doing a for loop with
rectangle1.Location = new Point(160, rectangle1.Location.Y - 100);
it just moved there instantly. Which I should have expected really. Same occurred with
int count = 0;
while(count != 300)
{
rectangle1.Location = new Point(160, rectangle1.Location.Y -1);
count += 2;
}
So, I assume I need some sort of clock / timer loop, that moves it by x pixels every x milliseconds. Not sure how to do this, so help would be appreciated.
Also, I'm going to be animating two other rectangles horizontally, which will then move up at the same time/speed as rectangle1. I think I'll have to "delay" rectangle1's movement until they are in position, correct?
Thanks.
PS: I've googled a fair bit, but since I'm not entirely sure what I'm looking for, it wasn't very fruitful.

If you need smooth movements, it's great to use timers, threads, backgroundworkers.
Here is what you need to do. Assuming you have the code that increment/decrement x,y points for the shape.
Steps:
set timer interval to for e.g. 100
set an integer int count=0; *
in timer_tick event do the moving work
private void timer1_Tick(object sender, EventArgs e)
// no need to use your while loop anymore :))
{
If(count< 300) //set to your own criteria
{
//e.g. myrect.location=new point(x,y);
// rectangle1.Location = new Point(160, rectangle1.Location.Y -1);
}
count += 2;
}

Related

How Can I Improve The Look Of This Transition?

I am trying to translate two buttons down and off-screen after one is clicked. I have it working, but it is very choppy. How can I make this transition more fluid?
-I am using Microsoft Visual Studio 2015
-The language I am using is c#
Here is my transition code:
private void timer1_Tick(object sender, EventArgs e)
{
int speed_increase = 100;
if(sleep_button.Top <= 800 || calibrate_button.Top <= 800)
{
sleep_button.Top += speed_increase;
calibrate_button.Top += speed_increase;
}
}
I have my timer interval set to 1ms too, just because I am aware the larger interval the choppier it becomes. I have been looking all day for a button transition tutorial and found none. And if this isn't possible can somebody sent me a tutorial for button fade outs? Thanks everyone
Your timing choice is off. 1ms is too granular. Try something around the 20ms mark, this will cause your code to run 50 times per second, which is rather closely aligned with common refresh rates of around 50hz.
How far do the buttons need to scroll? How long should it take?
Assume X is the distance to scroll, and Y is the time in seconds. The number of iterations is Y * 50 (50 times per second), and the distance per step is X / Y.
X = 200 pixels.
Y = 2 seconds.
Distance per step is:
X / (Y * 50)
200 / (2 * 50)
200 / 100
== 2
If you want to scroll 200 pixels over 2 seconds, you want to add 2 to the Y position of each button on each iteration.
I hope that makes sense.
How about hiding it altogether?
private void timer1_Tick(object sender, EventArgs e)
{
sleep_button.Visible = false;
calibrate_button.Visible = false;
}

Smoother transition moving cursor with a coordinates given

In a .NET C# program, I have to simulate the "mouse" cursor movement with coordinates received in the events of a external controller.
I did get to move the cursor depending on these coordinates.
Is there any possibility to move the cursor of a smoother way between two points?, because when I have 2 away points there is like a "jump" with the cursor.
Thanks in advance.
Edit: Added code, this function is launched each time new coordinates are received (aprox. each 20-30 ms)
//...
private void MoveCursor (int x, int y){
//Added checkup for avoiding noise between closer points
if (Math.Abs(Cursor.Position.X - x)>10 || Math.Abs(Cursor.Position.Y - y)>10){
Cursor.Position = new Point(x,y)
}
}
//...
In addition to my comment, here is a simple solution (syntax untested) that I use in one of my software and that I suggest you to test to see if it fits your needs :
Point _targetPosition;
Point _currentPosition;
private void MoveCursor (int x, int y){
_targetPosition = new Point(x,y);
_currentPosition += (_targetPosition - _currentPosition)*0.08f;
Cursor.Position = _currentPosition;
}
Basically, I maintain a target position which is the last coordinate received. I move the cursor only by a fraction (here 8% of the distance between the current position and the target).
It very efficiently smooths the movement of the mouse but lead to imprecision and a delay that may not be acceptable for brutal movement or changes of direction.
A factor of 8% give good results in my case considering 60 updates/seconds but that factor need to be adapted to your data.
Finally inspired by #Ndech solution I could solve my problem.
I've divided the solution into 2 parts:
This is the event which is raised by my gaze controller (each 20ms aprox). I discard closer points to avoid "jumps" due to the way as gaze controller works.
private void MoveCursorEvent (object sender, GazePointEventArgs e){
if (Math.Abs(Cursor.Position.X - e.X) > 40 || Math.Abs(Cursor.Position.Y - e.Y) > 40){
MoveCursor((int)e.X, (int)e.Y);
}
}
Copying current values of X,Y point of the cursor in a primitive variable since Cursor.Position could change during the process (Check if the first time…) Adding to previous point, average distance between previous point and current point with a weight of 15%. And Updating Cursor.Position with the new position calculated.
//Declare position variables
int previousX = 0;
int previousY = 0;
private void MoveCursor (int newX, int newY){
//If first time, set.
if (previousX == 0)
previousX = newX;
if (previousY == 0)
previousY = newY;
//Calculate new position
previousX = (int)(((newX - previousX) /2) * 0.15f);
previousY = (int)(((newY - previousY) /2) * 0.15f);
//Update position
Cursor.Position = new Point (previousX, previousY);
}

Displaying moving pieces in my chess game lags, what can I do about it?

First time I ever ask a question here so correct me if I´m doing it wrong.
Picture of my chess set:
Every time I move a piece it lags for about 1 second. Every piece and tile has an Image and there is exactly 96 Images. Every time I move a piece it clears everything with black and then update the graphics.
In the early stages of the chess I didn't have any Images and used different colors instead and only a few pieces there was no noticeable lag and the piece moved in an instant.
public void updateGraphics(PaintEventArgs e, Graphics g, Bitmap frame)
{
g = Graphics.FromImage(frame);
g.Clear(Color.Black);
colorMap(g);
g.Dispose();
e.Graphics.DrawImageUnscaled(frame, 0, 0);
}
The function colorMap(g) looks like this:
private void colorMap(Graphics g)
{
for (int y = 0; y < SomeInts.amount; y++)
{
for (int x = 0; x < SomeInts.amount; x++)
{
//Tiles
Bundle.tile[x, y].colorBody(g, x, y);
//Pieces
player1.colorAll(g);
player2.colorAll(g);
}
}
}
The colorAll function executes every pieces colorBody(g) function which look like this:
public void colorBody(Graphics g)
{
//base.colorBody() does the following: body = new Rectangle(x * SomeInts.size + SomeInts.size / 4, y * SomeInts.size + SomeInts.size / 4, size, size);
base.colorBody();
if (team == 1)
{
//If its a white queen
image = Image.FromFile("textures/piece/white/queen.png");
}
if (team == 2)
{
//If its a black queen
image = Image.FromFile("textures/piece/black/queen.png");
}
g.DrawImage(image, body);
}
and finaly the function that moves the piece:
public void movePiece(MouseEventArgs e)
{
for (int y = 0; y < SomeInts.amount; y++)
{
for (int x = 0; x < SomeInts.amount; x++)
{
if (Bundle.tile[x, y].body.Contains(e.Location))
{
//Ignore this
for (int i = 0; i < queens.Count; i++)
{
Queen temp = queens.ElementAt<Queen>(i);
temp.move(x, y);
}
//Relevant
player1.move(x, y);
player2.move(x, y);
}
}
}
}
Thank you for reading all this! I could make a link to the whole program if my coding examples is not enough.
You're calling Image.FromFile in every refresh, for every image - effectively reloading every image file every time from disk.
Have you considered loading the images once, and storing the resulting Images somewhere useful? (say, an array, Image[2,6] would be adequate)
Why do you redraw the board each time? Can't you just leave the board where it is and display an image with transparent background over it? That way you have one image as a background (the board), plus 64 smaller images placed over the board in a grid and just change the image being displayed on each move.
That way, you can let windows handle the drawing...
Also, load the images of the pieces at the start of the application.
In addition to not calling Image.FromFile() inside updateGraphics() (which is definitely your biggest issue), you shouldn't be attempting to redraw the entire board every on every call to updateGraphics() - most of the time, only a small portion of the board will be invalidated.
The PaintEventArgs contains an parameter, ClipRectangle, which specifies which portion of the board needs redrawing. See if you can't figure out which tiles intersect with that rectangle, and only redraw those tiles :)
Hint: Write a function Point ScreenToTileCoords(Point) which takes a screen coordinate and returns which board-tile is at that coordinate. Then the only tiles you need to redraw are
Point upperLeftTileToBeDrawn = ScreenToTileCoords(e.ClipRectangle.Left, e.ClipRectangle.Top);
Point lowerRightTileToBeDrawn = ScreenToTileCoords(e.ClipRectangle.Right - 1, e.ClipRectangle.Bottom- 1);
Also, make sure your control is double-buffered, to avoid tearing. This is much simpler than #Steve B's link in the comments above states; assuming this is a UserControl, simply set
this.DoubleBuffered = true;
Well, what about this:
Do not clear the whole board but only those parts that need to be cleared.
Alternative:
Update to WPF - it moves drawing to the graphics card - and just move pieces around, in a smart way (i.e. have a control / object for every piece).

when I connect for example 14 points with lines and try to move them its moving very very slow what's making it to move that slow?

This is the paint event:
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
SolidBrush brush;
Pen p=null;
Point connectionPointStart;
Point connectionPointEnd;
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
brush = new SolidBrush(Color.Red);
p = new Pen(brush);
for (int idx = 0; idx < wireObject1._point_X.Count; ++idx)
{
Point dPoint = new Point((int)wireObject1._point_X[idx], (int)wireObject1._point_Y[idx]);
dPoint.X = dPoint.X - 5; // was - 2
dPoint.Y = dPoint.Y - 5; // was - 2
Rectangle rect = new Rectangle(dPoint, new Size(10, 10));
g.FillEllipse(brush, rect);
}
for (int i = 0; i < wireObject1._connectionstart.Count; i++)
{
int startIndex = wireObject1._connectionstart[i];
int endIndex = wireObject1._connectionend[i];
connectionPointStart = new Point((int)wireObject1._point_X[startIndex], (int)wireObject1._point_Y[startIndex]);
connectionPointEnd = new Point((int)wireObject1._point_X[endIndex], (int)wireObject1._point_Y[endIndex]);
p.Width = 4;
g.DrawLine(p, connectionPointStart, connectionPointEnd);
moveCounter++;
textBox1.Text = moveCounter.ToString();
}
}
On the loop in the bottom I'm running over the _connectionstart List which is type of int.
I added a int variable I called it moveCounter to see how many time its calling this loop and drawing the lines.
If I'm adding two points over the pictureBox1 connect them with one line then drag one of the points around its moving smooth. Same thing with 3 connected points and with 7 connected points but when I'm getting to 9-10 points connected with many lines and try to move it drag it around or any point that is not connected everything is moving very very slow and as much as I add a new connected line between two points its getting slower.
So the problem can be a bug with my loop's in the paint event or that in the move event its doing so many time pictureBox1.refresh();
So I added a timer enabled it true in the designer and set it to 30 milliseconds. In the move event I raise a flag and in the timer tick event I check if the flag is on I make a pictureBox1.refresh(); and reset back the flag. The idea is that when I move the points or the connected points it will do it each 30 milliseconds.
But it didn't solve the problem. Still when I have 9-10 points connected with many lines between them everything is getting very slow.
This is the picturebox1 mouse move event:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (mouseMove == true)
{
mouseDrag = true;
Point NewPoint = e.Location;
wireObject1.MovePoint(selectedIndex, NewPoint, NewPoint); // when moving a point dragging the other point is vanished deleted. To check why !
label1.Text = "{X = " + NewPoint.X + "}" + " " + "{Y = " + NewPoint.Y + "}";
refreshFlag = true;
timer2.Start();
}
else
{
label19.Text = "{X = " + e.X + "}" + " " + "{Y = " + e.Y + "}";
}
}
timer2 is another timer I added just to see how many times it moved in 5 seconds. So if timer1 set to 30 milliseconds I should see after 5 seconds something about 150 moves.
So in timer1 tick event I did:
private void timer1_Tick(object sender, EventArgs e)
{
if (refreshFlag == true)
{
pictureBox1.Refresh();
refreshFlag = false;
}
}
I was sure the timer1 idea should solve the problem but it didn't. So I wonder where the problem is maybe i did something wrong with the loop's in the paint event ?
The List _connectionstart contain indexes for example if I have two points connected with one line and I clicked on one point and drag this point around which make the line the be longer or shorter then in _connectionstart for example I have one place/cell [0] which contain index 0
In the List _point_X I have for example now two cells place in [0] 120.0 and in [1] 180.0 which are the points coordinates same for the _point_Y List.
Now the question is where is the problem ? A bug in the paint event ? Something with the move event ? I can't figure out why its getting so slow when it have 9-10 points connecting with a lot of lines between them.
For example I tested now with two points connected with a line I moved one point around which stretch the line longer or shorter and after 5 seconds the result was 160 moves counted then after another 5 seconds it was 323 and so on. So it seems to be working the timer1 and the 30 milliseconds or I'm wrong?
First, a few tweaks for the application:
Did You try to run the logic separated from drawing? => For example, an "updateData()" method and a "draw()" method? Also I would recommend to use the DoubleBuffer.
Second, if the performance is bad for a larger set of data (when You add more points), than Your algorithm is not efficient enough. If drawing a polygon is what You want, first update the vertex coordinates and then call Graphics.DrawPolygon

Best way to move an image across part of the screen?

I have a Silverlight WP7 app and an image on my page that I want to appear to slide across the screen. What is the best way of doing this? I wrote this real quick but the UI doesn't update until the entire method is done.
private void SpinImg(Image img, double left) {
for(int i = 1; i <= 10000; i++) {
img.Margin = new Thickness(left, img.Margin.Top + 1, 0, 0);
if(img.Margin.Top > 314) {
//move it to the top
img.Margin = new Thickness(left, -105, 0, 0);
}
int wait = 1000 / i;
Thread.Sleep(wait);
}
}
Use a Storyboard - this is hardware-acceleratable, and all occurs on the Render thread, so you'll see much better performance than trying to update position directly over and over.
Storyboard has the advantage of being time-based instead of frame-based, so it's easy to declare "I want the image to move from to in 0.5 seconds" and it will just happen.
Thread.Sleep will freeze ALL UI processing, use Dispatcher class.

Categories