My goal is to move a picturebox back and forth. My issue is how to do this.
I have written the following:
int x = enemy.Location.X;
int y = enemy.Location.Y;
enemy.Location = new Point(x+-1, y);
This moves the picturebox off-screen, left. After moving left, I'd like it to move right, so that it moves back and forth - in a continuous loop.
The noob that I am, I tried:
if (x < 40)
enemy.Location = new Point(x - -100, y);
else if (x > 400)
enemy.Location = new Point(x - 5, y);
This proves unsuccessful - the box doesn't seem to move on reaching pixel 40.
Is there a simple solution that you can prod me towards, or have I dug an early grave for myself?!
I should specify: I am writing in C# per college assignment requirements.
Cheers.
When moving left, when the x location reaches 0, change direction and move right.
When moving right, you need to use the width of the screen minus the width of your picturebox.
System.Windows.SystemParameters.PrimaryScreenWidth
edit:
Or better yet, use the width of your form minus the width of the picturebox. Then it will still work if its not maximized.
Setup a variable that toggles between negative and positive values to make it go left and right. You toggle the direction by multiplying by -1. Then you simply add that variable to the current X value like this:
private int direction = -1; // this can be values other than 1 to make it jump farther each move
private void timer1_Tick(object sender, EventArgs e)
{
int x = enemy.Location.X + direction;
if (x <= 0)
{
direction = -1 * direction;
x = 0;
}
else if (x >= this.ClientRectangle.Width - enemy.Width)
{
direction = -1 * direction;
x = this.ClientRectangle.Width - enemy.Width;
}
enemy.Location = new Point(x, enemy.Location.Y);
}
Related
I'm struggling to figure out why the below function is only ever moving my mouse from 0, 0 screen coords, to my final destination, even though Cursor.Position is returning the correct screen coords. If anybody could enlighten me i'd be most grateful.
public void MoveAndClick(int x, int y, int steps)
{
Point start = Cursor.Position;
PointF iterPoint = start;
PointF slope = new PointF(x - start.X, y - start.Y);
slope.X = slope.X / steps;
slope.Y = slope.Y / steps;
for(int i=0; i<steps; i++)
{
iterPoint = new PointF(iterPoint.X + slope.X, iterPoint.Y + slope.Y);
inputSim.Mouse.MoveMouseTo(iterPoint.X, iterPoint.Y);
Thread.Sleep(10);
}
inputSim.Mouse.MoveMouseTo(x, y);
inputSim.Mouse.RightButtonDown();
inputSim.Mouse.RightButtonUp();
}
Taken from https://stackoverflow.com/a/913703/2014393
DOH! Always stop working when you're sleepy and go to bed.
The InputSimulator library requires that you translate coordinates like so:
int startX = 65535 * Cursor.Position.X / Screen.PrimaryScreen.Bounds.Width;
int startY = 65535 * Cursor.Position.Y / Screen.PrimaryScreen.Bounds.Height;
I was converting the end coordinates but completely forgot to translate the starting coordinates, derp.
FlaUI allows for the mouse to move smoothly. Here is the Mouse class in FlaUI for reference.
Trying to make a simple bacteria-killing game using WinForm in C#, but the bacteria (I am using Panel for the time being) doesn't seem to move around at random.
Specifically, the problem I am having is, the bacteria tries to move towards the upper left corner and move around there only. Ideally, the bacteria needs to move around the rectangle range evenly, but I am not sure how to achieve that.
Look at the gif file below.
As you can see the red Panel moves around the upper left corner only. How can I get it to move everywhere evenly and randomly?
Here is my code:
private Panel _pnlBacteria; //Panel representing a piece of bacteria
private Random r = new Random(); //For randomly-generated values
private int _prevX; //Stores the previous X location
private int _prevY; //Stores the previous Y location
public Form1()
{
InitializeComponent();
_pnlBacteria = new Panel();
/* Get more property assignments to this._pnlBacteria (omitted) */
//Bacteria's start position is also randomly selected
_prevX = r.Next(50, 300);
_prevY = r.Next(50, 500);
}
//Timer runs every 100 seconds changing the location of the bacteria
private void TmrMoveBacteria_Tick(object sender, EventArgs e)
{
int x, y;
//Get random values for X and Y based on where the bacteria was previously
//and move randomly within ±10 range. Also it cannot go off the screen.
do
{
x = r.Next(_prevX - 10, _prevX + 10);
y = r.Next(_prevY - 10, _prevY + 10);
}
while ((y <= 0) || (y >= 500) || (x <= 0) || (x >= 300));
//Save the new location to be used in the next Tick round as previous values
_prevX = x;
_prevY = y;
//Apply the actual location change to the bacteria panel
_pnlBacteria.Top = y;
_pnlBacteria.Left = x;
}
I tried changing the +10 to +12, leaving -10 as it is, but now this only made the bacteria move to the bottom right corner only. I am at a loss.
Can anyone please help?
If you read the documentation of Random.next(int,int) you'll find the the lower bound is inclusive and the upper bound is exclusive, that's why -10 and +11 works.
A slightly different way to tackle this might be to choose a random direction and a random distance to travel in that direction. This will allow more movement over the form if we increase the maximum distance the bacteria can travel before changing direction.
We can also "weight" the randomness of the distance so that shorter distances are chosen more often. This will add more variety and randomness to the movement pattern, while still allowing a few long sprints to another location.
Here's an example that you can copy/paste into a new form project implementing this idea. You can play with the settings for maxDistance (the furthest distance allowed before changing direction) and stepDistance (the distance travelled on each iteration of the Timer). A smaller stepDistance will result in smoother, but slower movement. I've made it pretty small, so I've also decreased the Interval property of the Timer to speed it up.
You'll notice I also added a method to validate that the direction is valid, so that the bacteria doesn't run off the screen. I created an enum to represent directions, which made it easy to check for movement in a particular direction (i.e. if the enum value contains "North" and we're too close to the top, then it's an invalid direction - this covers "North", "NorthWest", and "Northeast" directions).
Edit: I moved the creation of the "weighted distances" list to the constructor, and modified it to select exponentially fewer items rather than linearly fewer items.
Hope it makes sense:
public partial class Form1 : Form
{
// Program Settings and Controls
private readonly Panel pnlBacteria; // Panel representing a piece of bacteria
private readonly Random random = new Random(); // For randomly-generated values
private readonly Timer tmrMoveBacteria; // Timer used for bacteria movement
private readonly int bacteriaSize = 20; // Stores the size for our bacteria
private const int maxDistance = 50; // The maximum number of moves allowed in the same direction.
private const int stepDistance = 3; // The distance to travel on each iteration of the timer. Smaller number is slower and smoother
private readonly List<int> weightedDistances; // Contains a weighted list of distances (lower numbers appear more often than higher ones)
// Bacteria state variables
private Direction direction; // Stores the current direction bacteria is moving
private int distance; // Stores the distance remaining to travel in current direction
// Represents possible directions for bacteria to move
private enum Direction
{
North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest
}
public Form1()
{
InitializeComponent();
// Initialize our weighted differences array so that 1 is
// chosen most often and maxDistance is chosen the least often
weightedDistances = new List<int>();
for (var i = 0; i < maxDistance; i++)
{
var weight = maxDistance / (i + 1);
for (var j = 0; j <= weight; j++)
{
weightedDistances.Add(i + 1);
}
}
// Give life to the bacteria
pnlBacteria = new Panel
{
BackColor = Color.Red,
Width = bacteriaSize,
Height = bacteriaSize,
Left = random.Next(0, ClientRectangle.Width - bacteriaSize),
Top = random.Next(0, ClientRectangle.Height - bacteriaSize)
};
Controls.Add(pnlBacteria);
// Start bacteria movement timer
tmrMoveBacteria = new Timer {Interval = 10};
tmrMoveBacteria.Tick += TmrMoveBacteria_Tick;
tmrMoveBacteria.Start();
}
/// <summary>
/// Sets the direction and distance fields to valid values based on the
/// current bacteria position, direction, and remaining distance
/// </summary>
private void UpdateDirectionAndDistance()
{
// Get all directions
var validDirections = Enum.GetValues(typeof(Direction)).Cast<Direction>();
// Remove invalid directions (based on the bacteria position)
if (pnlBacteria.Top < bacteriaSize) validDirections =
validDirections.Where(dir => !dir.ToString().Contains("North"));
if (pnlBacteria.Right > ClientRectangle.Width - bacteriaSize) validDirections =
validDirections.Where(dir => !dir.ToString().Contains("East"));
if (pnlBacteria.Left < bacteriaSize) validDirections =
validDirections.Where(dir => !dir.ToString().Contains("West"));
if (pnlBacteria.Bottom > ClientRectangle.Height - bacteriaSize) validDirections =
validDirections.Where(dir => !dir.ToString().Contains("South"));
// If we're supposed to keep on moving in the same
// direction and it's valid, then we can exit
if (distance > 0 && validDirections.Contains(direction)) return;
// If we got here, then we're setting a new direction and distance
distance = weightedDistances[random.Next(weightedDistances.Count)];
var directions = validDirections.Where(d => d != direction).ToList();
direction = directions[random.Next(directions.Count)];
}
/// <summary>
/// Executes on each iteration of the timer, and moves the bacteria
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TmrMoveBacteria_Tick(object sender, EventArgs e)
{
// Ensure direction and distance are valid
UpdateDirectionAndDistance();
// Move the bacteria
var dirStr = direction.ToString();
if (dirStr.Contains("North")) pnlBacteria.Top -= stepDistance;
if (dirStr.Contains("East")) pnlBacteria.Left += stepDistance;
if (dirStr.Contains("South")) pnlBacteria.Top += stepDistance;
if (dirStr.Contains("West")) pnlBacteria.Left -= stepDistance;
distance--;
}
}
The left and right arguments of r.Next are inclusive and exclusive respectively.
x = r.Next(_prevX - 10, _prevX + 10);
y = r.Next(_prevY - 10, _prevY + 10);
So the probability space of this code is a 19x19 square off center of (_prevX,_prevY) to its upper left. This means displacement is more likely towards the upper left.
If we use 11s on the right, then the probability space is a 20x20 square centered at (_prevX,_prevY). The bacteria will move more evenly. Its average displacement within its probability square is zero, so there's not a single favored direction. But the diagonal directions will be favored since diagonal displacement is the greatest on average. This may or may not be important depending on the situation.
If we use radius and direction as explained by Rufus L, then we can generate a more "natural" circular probability space. That's why it's the preferred approach.
The problem is that you are moving the object back and forth because the range is prev -+10;
x = r.Next(_prevX - 10, _prevX + 10);
y = r.Next(_prevY - 10, _prevY + 10);
you should add a direction flag for yval and xval, set it with certain probability p(less then 1/2) , when the flag is on go right/up, when its off go left/down ,
if (forwardx){
x = r.Next(_prevX , _prevX + 10);
}
else {
x = r.Next(_prevX - 10, _prevX );
}
if (forwardy){
y = r.Next(_prevY , _prevY + 10);
}
else{
y = r.Next(_prevY - 10 , _prevY );
}
forwardx = r.Next(10) == 1; //p = 0.1
forwardy = r.Next(10) == 1;
Good luck!
You should use the size of your panel.height - size of your square.height same for length instead of constants this way if the screen size changes your game will still work.
_prevX = r.Next(bateriaSize, this.Width-bacteriaSize); //this.Width Gets you the of form
_prevY = r.Next(bateriaSize, this.Height-bacteriaSize); //This.Height gets you the height of form
I'm trying to move an object in a matrix (an array with [x,y]) using a line drawing algorithm, to help you understand what I mean I'm trying to make an object move like this:
But instead of going "in line" it goes like this:
I opened another question about this problem here, and you told me to use a line drawing algorithm, which I did, but I still can't make it move in that order.
A little bit about the code (I'm giving you some 'background' so you won't be confused): The Location variable contains a location on the matrix, it has x and y, which can be accessed like this:
Location loc = new Location(x,y);//Declaring a new location
int row = loc.Row;//Gets the x value (Row)
int col = loc.Col;//Gets the y value (Column)
The Direction variable contains a direction, there are 5 directions:
Direction.NORTH;
Direction.SOUTH;
Direction.EAST;
Direction.WEST;
Direction.NOTHING; //This direction means to stay at the same place, or not move
I think it's obvious what each of them means.
The command game.Destination(myPirate, direction); calculates where the object ends up on the next turn(returns a location).
Now here is the code that I got:
public static Direction NextDirection(Game game,Pirate myPirate,Location EndLocation)
{
List<Direction> westEast = new List<Direction>() { Direction.EAST, Direction.WEST };
List<Direction> northSouth = new List<Direction>() { Direction.NORTH, Direction.SOUTH };
int startX = myPirate.Loc.Row;
int startY = myPirate.Loc.Col;
int endX = EndLocation.Row;
int endY = EndLocation.Col;
if (startX == endX && startY == endY) return Direction.NOTHING; //If its alredy on spot return the location of the pirate;
int dx = endX - startX;
int dy = endY - startY;
if (dx == 0) //The X of the end is the same as the x of the start, need to move only on the y axis;
{
return MyBot.GetBestDirection(game, myPirate, EndLocation);
}
if (dy==0) //The Y of the end is the same as the y of the start, need to move only on the x axis;
{
return MyBot.GetBestDirection(game, myPirate, EndLocation);
}
int slope = dy / dx;
Location destination;
double distance = MyBot.Distance(myPirate.Loc, EndLocation);
if (slope > 1 || slope < -1)
{
double distance2;
foreach (Direction dir in northSouth) //In here the algoritem decides whats the best direction (north or south);
{
destination = game.Destination(myPirate, dir);
distance2 = MyBot.Distance(destination, EndLocation);
if (distance2 < distance) return dir;
}
game.Debug("Couldnt find a good direction, going by the default dirction algorithem.");
return MyBot.GetBestDirection(game, myPirate, EndLocation);
}
else
{
double distance2;
foreach (Direction dir in westEast)//In here the algoritem decides whats the best direction (west or east);
{
destination = game.Destination(myPirate, dir);
distance2 = MyBot.Distance(destination, EndLocation);
if (distance2 < distance) return dir;
}
game.Debug("Couldnt find a good direction, going by the default dirction algorithem.");
return MyBot.GetBestDirection(game, myPirate, EndLocation);
}
}
On some parts in the code above I'm also using parts from the MyBot class, here are these parts:
public static Direction GetBestDirection(Game game, Pirate myPirate, Location loc)//ADD: If the destination is not passable get another direction;
{
double distance = Distance(myPirate.Loc, loc);
List<Direction> allDirections = new List<Direction>() { Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST, Direction.NOTHING };
Location destination;
foreach (Direction dir in allDirections)
{
destination = game.Destination(myPirate, dir);
double distance2 = Distance(destination, loc);
if (distance2 < distance && game.IsPassable(destination)) return dir;
}
return Direction.NOTHING;
}
The 'object' I told you about is called myPirate in the code, and it can only move in one direction each turn. the code run again in each turn until it gets to the target.
How can I make this program work right? What is wrong with my code?
You should compute the slope as a float or double, not as an int. When you use integer division, 1/2 is 0, and of course when the slope is 0 you are moving to the right. This means if you go from (0,0) to (20,10) you would have to start with 10 (1,0) steps if you are using integer division, and that is not the best behavior.
If you set a fixed threshold for the (floating point) slope, such as if the slope is less than 1.0 then go right, then you will not follow a line closely at all because you will move due right until you get to a point where the slope is greater than the threshold. So, don't use a fixed threshold.
A quick-and-dirty method is to randomize the threshold so that it causes you to move in the right direction on average. I'll assume dx>0 and dy>0. You can handle the other quadrants by symmetry. To move in the right direction on average, you can choose a random integer from [0,dx+dy-1]. If it is less than dx, then take a step in the x direction. If it is greater than or equal to dx, take a step in the y direction. Equivalently, choose a random double in [0,1] and if it is lower than dx/(dx+dy), take a step in the x direction, otherwise take a step in the y direction.
If you don't like the randomization, then you can derandomize this. Instead of picking a fixed threshold, you can choose a pseudo-random function of (dx,dy,x,y). For example, you could compare dx/(double)(dx+dy) with (2^((dx+3*dy)%28) mod 29)/29.0. This sets the threshold from 1/29 to 28/29 in a roughly uniform manner.
Edit: Here is some untested code.
// assume dx>0, dy>0
int linearMod28 = (dx + 3*dy) % 28; // 0 through 27
int pseudorandomMod29 = (1 << linearMod28) % 29; // 1 through 28
double threshold = pseudorandomMod29/29.0; // 1/29 through 28/29
if (dx/(double)(dx+dy) < threshold)
// take a step in the x direction
else
// take a step in the y direction
I'm drawing a Circle made of 360 FillPie. Each FillPie color is taken from a List. I want to return a string that says at which degree is the mouse and how much is the value of the list to put it on a tooltip.
List<int> datiDisco = new List<int>();
public void Paint (Graphics grafica)
{
try
{
for (int i = 0; i < datiDisco.Count; i++)
{
Brush penna = new SolidBrush(Color.FromArgb(255, ScalaGrigi(valori[i]), ScalaGrigi(valori[i]), ScalaGrigi(valori[i])));
grafica.FillPie(penna, 0, 0, 400, 400, i, 1.0f);
}
}
catch
{
}
}
until here the code is working and i managed to draw the circle with the correct color.Now i can't figure out how i can take the coordinate of each fillpie that i have drawn. Can someone help me?
Figuring out which pie segment the mouse cursor lies in is a simple application of trigonometry, specifically an application of the inverse tangent (aka arctangent or atan).
As a quick reminder for those who've encountered this before, or as a lesson for those who haven't, let's look quickly at the tangent function. Trigonometry deals with the geometry of right triangles, and by definition a right triangle has two sides and a hypotenuse. The hypotenuse is a special name for the side of the triangle opposite the right (90° or π/2) angle. The other two sides are helpfully just called sides.
The tangent function's value is the ratio of the side opposite an angle to the side adjacent to that angle. The arctangent is the angle whose tangent is equal to that ratio. Because of the symmetry of the function we need to calculate the angle, and then add or subtract an offset depending on the quadrant to extract the 'real' angle. In diagram form this looks like:
The tangent function has discontinuities at several points, namely when the adjacent side's length is 0 (90° and 270°), so we'll have to treat those points specially.
OK, enough math, now on to the practical application.
For this demo, create a new C# WinForms project, and on the default Form1 add a PictureBox.
First, since I don't have your color generation function, I use the following list of values and helper function:
List<int> values = Enumerable.Range(0, 360).ToList();
int Rescale(int x) => (int)(((double)x / 360.0) * 255.0);
In the constructor hook up a couple events, and set some properties:
public Form1()
{
InitializeComponent();
this.pictureBox1.BorderStyle = BorderStyle.Fixed3D;
this.pictureBox1.Size = new Size(50, 50);
this.Size = new Size(450, 450);
this.DoubleBuffered = true;
this.Paint += Form1_Paint;
this.MouseMove += Form1_MouseMove;
}
To paint the circle I use a slightly modified version of your OnPaint handler:
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
for (int i = 0; i < values.Count; i++)
{
Brush b = new SolidBrush(Color.FromArgb(255, Rescale(values[i]), 0, 0));
e.Graphics.FillPie(b, 0, 0, 400, 400, (float)i, 1.0f);
}
}
In the MouseMove event is where we do most of the heavy lifting:
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
this.pictureBox1.Location = new Point(e.X + 5, e.Y - 5);
int segment = (int)GetAngle(new Rectangle(0, 0, 400, 400), e.Location);
this.pictureBox1.BackColor = Color.FromArgb(255, Rescale(segment), 0, 0);
}
You may notice that since there are 360 wedges are in increments of a degree, I just truncated the angle. If you need more precision, or you decide to use segments greater than 1 degree, then you could use various rounding algorithms to round the angle to the nearest section of the pie.
At last, we're ready to implement the GetAngle function. First we calculate the center of the circle, because everything is relative to that.
int cx = (rect.Width + rect.X) / 2;
int cy = (rect.Height + rect.Y) / 2;
Next calculate the difference between the mouse's position and the center of the rectangle. (I've inverted the y coordinate to line up with 'standard' Cartesian coordinates, to make things easier, and match the coordinates you'd see in a math textbook.)
float x = pTo.X - cx;
float y = (cy - pTo.Y);
Next check for the arctangent's undefined points (and a couple of shortcuts we can take):
if ((int)x == 0)
{
if (y > 0) return 270;
else return 90;
}
else if ((int)y == 0)
{
if (x > 0) return 0;
else return 180;
}
Calculate the internal angle:
float ccwAngle = (float)Math.Atan(Math.Abs(y) / Math.Abs(x));
And map that angle to the appropriate quadrant:
if (x > 0 && y > 0)
{
}
else if (x < 0 && y > 0)
{
ccwAngle = (float)Math.PI - ccwAngle;
}
else if (x < 0 && y < 0)
{
ccwAngle = ccwAngle + (float)Math.PI;
}
else if (x > 0 && y < 0)
{
ccwAngle *= -1f;
}
Convert the angle from degrees to radians and normalize (make sure it's between 0° and 360°)
ccwAngle *= (float)(180 / Math.PI);
while (ccwAngle > 360) ccwAngle -= 360;
while (ccwAngle < 0) ccwAngle += 360;
Finally convert the counter-clockwise angle we needed to do the math into the clockwise angle that GDI uses, and return the value:
return 360f - ccwAngle;
All that together produces the final result:
(The code above is also available as a complete example in this gist)
I've been racking my brain trying to figure out how to animate an effect. This is related to a question I asked on math.stackexchange.com.
https://math.stackexchange.com/questions/91120/equal-division-of-rectangles-to-make-total/
As a side note, I didn't implement the drawing algorithm that was defined on the question above -- instead using my own in order to change the perspective to make it look more condensed.
I've been able to draw a stationary 3d style effect, but I am having trouble wrapping my brain around the logic to make the lines below look like they are coming towards you.
My code is as follows,
List<double> sizes = new List<double>();
private void Form1_Load(object sender, EventArgs e)
{
for (int y = 1; y < 10; y++)
{
double s = ((240 / 2) / y) / 4;
sizes.Add(s);
}
sizes.Add(0);
}
int offset = 0;
private void button1_Click(object sender, EventArgs e)
{
Bitmap b = new Bitmap(320, 480);
Graphics g = Graphics.FromImage(b);
Color firstColor = Color.DarkGray;
Color secondColor = Color.Gray;
Color c = firstColor;
int yOffset = 0;
for(int i = 0; i < sizes.Count; i++)
{
c = (i % 2 == 0) ? firstColor : secondColor;
int y = (int)Math.Round(b.Height - yOffset - sizes[i]);
int height = (int)Math.Round(sizes[i]);
g.FillRectangle(new SolidBrush(c), new Rectangle(0, y + offset, b.Width, height + offset));
yOffset += (int)sizes[i];
}
this.BackgroundImage = b;
offset+=1;
}
Each button click should cause the rectangles to resize and move closer. However, my rectangles aren't growing as they should. My logic draws fine, but simply doesn't work as far as moving goes.
So my question is:
Is there an existing algorithm for this effect that I am not aware of, or is this something pretty simple that I'm over thinking? Any help in correcting my logic or pointing me in the right direction would be very appreciated.
Interesting...
(video of the answer here: http://youtu.be/estq62yz7v0)
I would do it like that:
First, drop all RECTANGLE drawing and draw your effect line by line. Like so:
for (int y=start;y<end;y++)
{
color = DetermineColorFor(y-start);
DrawLine(left, y, right, y, color);
}
This is of course pseudo-code not to be troubled with GDI+ or something.
Everything is clear here, except on how to code DetermineColorFor() method. That method will have to return color of the line at specified PROJECTED height.
Now, on the picture, you have:
you point of view (X) - didn't know how to draw an eye
red line (that's your screen - projection plane)
your background (alternating stripes at the bottom)
and few projecting lines that should help you devise the DetermineColorFor() method
Hint - use triangle similarity to go from screen coordinates to 'bar' coordinates.
Next hint - when you are in 'bar' coordinates, use modulo operator to determine color.
I'll add more hints if needed, but it would be great if you solved this on your own.
I was somehow inspired by the question, and have created a code for the solution. Here it is:
int _offset = 0;
double period = 20.0;
private void timer1_Tick(object sender, EventArgs e)
{
for (int y = Height / 3; y < Height; y++)
{
using (Graphics g = CreateGraphics())
{
Pen p = new Pen(GetColorFor(y - Height / 3));
g.DrawLine(p, 0, y, Width, y);
p.Dispose();
}
}
_offset++;
}
private Color GetColorFor(int y)
{
double d = 10.0;
double h = 20.0;
double z = 0.0;
if (y != 0)
{
z = d * h / (double)y + _offset;
}
double l = 128 + 127 * Math.Sin(z * 2.0 * Math.PI / period);
return Color.FromArgb((int)l, (int)l, (int)l);
}
Experiment with:
d - distance from the eye to the projection screen
h - height of the eye from the 'bar'
period - stripe width on the 'bar'
I had a timer on the form and event properly hooked. Timer duration was 20ms.
Considering that you're talking here about 2D rendering, as much as I understodd, to me it seems that you're gonna to reenvent the wheel. Cause what you need, IMHO; is use Matrix Transformations already available in GDI+ for 2D rendering.
Example of aplying it in GDI+ : GDI+ and MatrixTranformations
For this they use System.Drawing.Drawing2D.Matrix class, which is inside Graphics.
The best ever 2D rendering framework I ever used is Piccolo2D framework which I used with great success in big real production project. Definitely use this for your 2D rendering projects, but first you need to study it little bit.
Hope this helps.