Using WinForms to Draw Ellipses Continuously while Preserving a Rectangle - c#

I am doing an exercise from my book on WinForms, inheritance, interfaces and abstract classes. The exercise is to create couple of balls moving in random directions and having obstacles of shapes like a box interact with the balls.
The thought process in the book was that there is a Ball class and another class that is called Engine to handle the creations of the ellipses. My job is to create the obstacles and have them interact with the balls.
This are the requirements
All obstacles should be treated the same w.r.t. the engine; perhaps by using an interface. Do not use fully abstract classes
All obstacles should share as much code as possible, but only code that makes sense to share; use abstract classes if necessary to avoid inheriting methods that do not make sense or empty methods.
The Ball and Engine, class where given.
Position :
public class Position
{
public float X, Y;
public Position(float x, float y)
{
X = x; Y = y;
}
}
Vector :
public class Vector
{
public float X, Y;
public Vector(float x, float y)
{
X = x; Y = y;
}
}
Ball :
public class Ball
{
static Pen Pen = new Pen(Color.Black);
Position Position;
Vector Speed;
float Radius;
static Random Random = new Random();
public Ball(float x, float y, float radius)
{
Position = new Position(x,y);
var xd = Random.Next(1, 6);
var yd = Random.Next(1, 6);
if (Random.Next(0, 2) == 0) xd = -xd;
if (Random.Next(0, 2) == 0) yd = -yd;
Speed = new Vector(xd,yd);
Radius = radius;
}
public void Draw(Graphics g)
{
g.DrawEllipse(Pen,Position.X - Radius, Position.Y - Radius, 2 * Radius, 2 * Radius);
}
public void Move()
{
Position.X += Speed.X;
Position.Y += Speed.Y;
}
}
Engine :
public class Engine
{
MainForm Form = new MainForm();
Timer Timer = new Timer();
List<Ball> Balls = new List<Ball>();
Redbox RBox = new Redbox(); //My added code
Random Random = new Random();
public void Run()
{
Form.Paint += Draw;
Timer.Tick += TimerEventHandler;
Timer.Interval = 1000/25;
Timer.Start();
Application.Run(Form);
}
private void Form_Paint(object sender, PaintEventArgs e)
{
throw new NotImplementedException();
}
void TimerEventHandler(Object obj, EventArgs args)
{
if (Random.Next(100) < 25)
{
var ball = new Ball(400, 300, 10);
Balls.Add(ball);
}
foreach (var ball in Balls)
{
ball.Move();
}
Form.Refresh();
}
void Draw(Object obj, PaintEventArgs args)
{
foreach (var ball in Balls)
{
ball.Draw(args.Graphics);
}
RBox.Draw(args.Graphics); //Testing
}
}
And this is the interface I created :
interface IObstacles
{
void Draw(Graphics g);
}
class Redbox : IObstacles
{
public void Draw(Graphics g)
{
Pen Pen = new Pen(Color.Red);
Random Random = new Random();
Position Position = new Position(Random.Next(100, 700), Random.Next(100, 700));
var width = Random.Next(30, 100);
var height = Random.Next(30, 100);
g.DrawRectangle(Pen, Position.X , Position.Y, width, height);
}
}
I am stuck figuring out how would my one (for now) rectangle would be drawn without it being refreshed every time. I might sound like an idiot, but I am fairly new. The result that I get is same rectangle appearing and disappearing with the same tick. I have also noticed that the Ball class creates and stores new "balls" in the list, but I cant do the same I think because of my interface implementation. I am creating interface for all the Obstacles as they are the same but with different shape. I might be wrong in my implementation but it sound logical to me at least.
Any help would be appreciated, as I am newbie in C#.

Using Jimi's Suggestios :
It turns out that he was right the randomness declared in Draw wasn't the right solution and it caused like he said for the obstacles to be redrawn every time with random position. This is all fixed by moving them outside I also modified the class so that it was possible to chose where the position of the box would be drawn.
I am posting the answer so that others that stumble on this can have a look on how I solved my problem thanks to Jimi's solution.
Interface :
interface IObstacles
{
void Draw(Graphics g);
}
class Redbox : IObstacles
{
Pen Pen = new Pen(Color.Red);
Random Random = new Random();
Position Position;
float width;
float height;
public Redbox(float x, float y)
{
Position = new Position(x, y);
width = Random.Next(30, 100);
height = Random.Next(30, 100);
}
public void Draw(Graphics g)
{
g.DrawRectangle(Pen, Position.X , Position.Y, width, height);
}
}
Engine :
public class Engine
{
MainForm Form = new MainForm();
Timer Timer = new Timer();
List<Ball> Balls = new List<Ball>();
List<IObstacles> RBox = new List<IObstacles>();
Random Random = new Random();
public void Run()
{
Form.Paint += Draw;
Timer.Tick += TimerEventHandler;
Timer.Interval = 1000/25;
Timer.Start();
Application.Run(Form);
}
private void Form_Paint(object sender, PaintEventArgs e)
{
throw new NotImplementedException();
}
void TimerEventHandler(Object obj, EventArgs args)
{
if (Random.Next(100) < 25)
{
var ball = new Ball(400, 300, 10);
Balls.Add(ball);
}
if (RBox.Count() < 2)
{
RBox.Add(new Redbox(100 * Random.Next(1, 8), 100 * Random.Next(0, 6)));
}
foreach (var ball in Balls)
{
ball.Move();
}
Form.Refresh();
}
void Draw(Object obj, PaintEventArgs args)
{
foreach (var ball in Balls)
{
ball.Draw(args.Graphics);
}
foreach (var rbox in RBox)
{
rbox.Draw(args.Graphics);
}
}
}
If there are still issues or some suggestion that anyone would like to add feel free to comment.

Related

How to make a shape move with the arrow keys?

using System.Drawing;
using System.Windows.Forms;
public partial class Form1 : Form
{
int vx = 5;
int vy = 5;
int bx = 0;
int by = 50;
int px = 93;
public Form1()
{
InitializeComponent();
timer1.Interval = 100;
timer1.Start();
}
public class Ball
{
public int X;
public int Y;
public int W;
public int H;
public Ball(int x, int y, int w, int h)
{
X = x;
Y = y;
W = w;
H = h;
}
}
public class Paddle
{
public int X;
public int Y;
public int W;
public int H;
public Paddle(int x, int y, int w, int h)
{
X = x;
Y = y;
W = w;
H = h;
}
}
public class Brick
{
public int X;
public int Y;
public int W;
public int H;
public Brick(int x, int y, int w, int h)
{
X = x;
Y = y;
W = w;
H = h;
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
int[] brickxs = { 0, 51, 102, 153, 204, 255, 306, 357, 408, 459, 510, 561, 612, 663, 714, 765 };
int bc = 0;
SolidBrush blueBrush = new SolidBrush(Color.Blue);
Ball b = new Ball(55, 55, 25, 25);
Paddle p = new Paddle(93, 377, 130, 30);
Brick br = new Brick(20, 20, 51, 20);
br.X = 0;
while (bc < 16)
{
br.X = brickxs[bc];
System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
System.Drawing.Graphics formGraphics;
formGraphics = this.CreateGraphics();
formGraphics.FillRectangle(myBrush, new Rectangle(br.X, 0, 49, 20));
myBrush.Dispose();
formGraphics.Dispose();
bc = bc + 1;
}
Rectangle ball = new Rectangle(bx, by, b.W, b.H);
Rectangle paddle = new Rectangle(px, p.Y, p.W, p.H);
//Rectangle brick = new Rectangle(br.X, br.Y, br.W, br.H);
e.Graphics.FillEllipse(blueBrush, ball);
e.Graphics.FillRectangle(blueBrush, paddle);
//e.Graphics.FillRectangle(blueBrush, brick);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Right)
{
px += 5;
}
}
private void MoveTimer_Tick(object sender, EventArgs e)
{
Invalidate();
}
private void timer1_Tick(object sender, EventArgs e)
{
bx = bx + vx;
by = by + vy;
if (px <= 0)
{
px = 0;
}
if (px >= 771)
{
px = 771;
}
WallCollision();
floorandCeilingCollision();
Invalidate();
}
public void WallCollision()
{
if (bx >= 771)
{
vx = -5;
}
if (bx <= 0)
{
vx += 5;
}
}
public void floorandCeilingCollision()
{
if (by >= 420)
{
vy = -5;
}
if (by <= 0)
{
vy = 5;
}
}
}
I am creating a game and I need some help.
In my code have classes for each of the parts of the game: the ball, paddle and bricks. The array positions the bricks.
I want to move the paddle (which just a rectangle) left and right with the arrow keys. I tried to use the key down method but it did not work.
Could you suggest any solutions or point out anything that I left out?
Personally, I use e.KeyCode instead of e.KeyData, try this first.
Make sure your Form is focused, and not a picturebox or something else you might have in the game. Because you try to call the KeyDown event for your Form, not for a control inside your Form.
I never used a Paint event, are you sure it is called? It might be the case that your game registeres the movement but never shows the changes to you. I usually have a separate method for drawing and I call it every time there is a change, you should try this too.
If nothing works, try debugging. Set a break point in your KeyDown method to see if it is called. If it does, set it in the Paint method. This one will surely be called once, at runtime, but if you click "Continue" on that time and try to move your object. If it is not called any other time, then here is your answer :)
Please update me with what you find after trying this things, and ask me what to do next if you get stuck or simply don't know what else there is to do :)

winforms c#. I draw the line in code, how can I add event hover to it? [duplicate]

My program can draw lines using canvas.Drawline(). How to click line and change this color (select line)?
private List<Point> coordFirst = new List<Point>();
private List<Point> coordLast = new List<Point>();
public Graphics canvas;
private void Form1_Load(object sender, EventArgs e)
{
canvas=panel1.CreateGraphics();
}
Coordinate line stored in coordFirs & coodLast.
Here is a suitable Line class:
class Line
{
public Color LineColor { get; set; }
public float Linewidth { get; set; }
public bool Selected { get; set; }
public Point Start { get; set; }
public Point End { get; set; }
public Line(Color c, float w, Point s, Point e)
{ LineColor = c; Linewidth = w; Start = s; End = e; }
public void Draw(Graphics G)
{ using (Pen pen = new Pen(LineColor, Linewidth)) G.DrawLine(pen, Start, End); }
public bool HitTest(Point Pt)
{
// test if we fall outside of the bounding box:
if ((Pt.X < Start.X && Pt.X < End.X) || (Pt.X > Start.X && Pt.X > End.X) ||
(Pt.Y < Start.Y && Pt.Y < End.Y) || (Pt.Y > Start.Y && Pt.Y > End.Y))
return false;
// now we calculate the distance:
float dy = End.Y - Start.Y;
float dx = End.X - Start.X;
float Z = dy * Pt.X - dx * Pt.Y + Start.Y * End.X - Start.X * End.Y;
float N = dy * dy + dx * dx;
float dist = (float)( Math.Abs(Z) / Math.Sqrt(N));
// done:
return dist < Linewidth / 2f;
}
}
Define a List for the lines, probably at class level:
List<Line> lines = new List<Line>();
Here is how you can initialize it with a few lines:
for (int i = 0; i < 20; i++) lines.Add(new Line(Color.Black, 4f,
new Point(R.Next(panel1.Width), R.Next(panel1.Height)),
new Point(R.Next(panel1.Width), R.Next(panel1.Height))));
Here is the result of clicking on a crossing:
Whenever you add, change or remove a line you need to make the Panel reflect the news by triggering the Paint event:
panel1.Invalidate();
Here is the Paint event of the Panel:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
foreach (Line L in lines) L.Draw(e.Graphics);
}
In the MouseClick event you do the test:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
foreach(Line L in lines)
L.LineColor = L.HitTest(e.Location) ? Color.Red : Color.Black;
panel1.Invalidate();
}
To avoid flicker don't use the basic Panel class as it isn't doublebuffered. Instead use either a PictureBox or a Label (with AutoSize=false) or a doublebuffered Panel subclass:
class DrawPanel : Panel
{ public DrawPanel () { DoubleBuffered = true; } }
Notes:
There is no such thing as a 'Line' in WinForms, only pixels of various colors. So to select a line you need to store it's two endpoints' coordinates and then find out if you have hit it when clicking.
The above example shows how to do it in math.
Instead one could test each line by drawing it onto a bitmap and test the pixel the mouse has clicked. But drawing those bitmaps would have to do math behind the scenes as well and also allocate space for the bitmaps, so the math will be more efficient..
Yes the Line class looks a little long for such a simple thing a s a line but look how short all the event codes now are! That's because the responsiblities are where they belong!
Also note the the first rule of doing any drawing in WinForms is: Never cache or store a Grahics object. In fact you shouldn't ever use CreateGraphics in the first place, as the Graphics object will never stay in scope and the graphics it produces will not persist (i.e. survive a Minimize-maximize sequence)..
Also note how I pass out the e.Graphics object of the Paint event's parameters to the Line instances so they can draw themselves with a current Graphics object!
To select thinner lines it may help to modify the distance check a little..
The Math was taken directly form Wikipedia.
You can change the color of everything on click. By using click event of particular object.
I give you an example for button. If you click on button then panal’s color will be change. You can modify the code as per your requirement.
private List<Point> coordFirst = new List<Point>();
private List<Point> coordLast = new List<Point>();
public Graphics canvas;
private void Form1_Load(object sender, EventArgs e)
{
canvas = panel1.CreateGraphics();
}
private void panel1_Click(object sender, EventArgs e)
{
panel1.BackColor = Color.Blue;
}
private void nonSelectableButton3_Click(object sender, EventArgs e)
{
panel1.BackColor = Color.BurlyWood;
}

Is there a way to avoid writing duplicate code in C#?

I would like to insert more balls into the form. However, in order to allow it to bounce I have to code the same algorithm over and over again for different ball. May I know is there any way I can do it without writing it over and over again? The codes I have are as below.
int bBA1; //The x axis from the upper left corner
int bBA2; //The y axis from the upper left corner
int spdBBA1; //The change of x
int spdBBA2; //The change of y
public StartGame()
{
InitializeComponent();
}
private void StartGame_Load(object sender, EventArgs e)
{
//Loads the ball on the screen at bottom of the window
bBA1 = this.ClientSize.Width / 5; //The x axis the ball is loaded at
bBA2 = this.ClientSize.Height - 10; //The y axis the ball is loaded at
spdBBA1 = 1; //The speed of the ball of y
spdBBA2 = 1; //The speed of the ball of x
}
private void StartGame_Paint_1(object sender, PaintEventArgs e)
{
//This is the inner paint color of the circle that is 10 by 10
e.Graphics.FillEllipse(Brushes.Blue, bBA1, bBA2, 10, 10);
//This is the outline paint color of the circle that is 10 by 10
e.Graphics.DrawEllipse(Pens.Blue, bBA1, bBA2, 10, 10);
}
private void timer1_Tick(object sender, EventArgs e)
{
bBA2 = bBA2 + spdBBA2;
bBA1 = bBA1 + spdBBA1;
if (bBA2 < 0)
{
spdBBA2 = -spdBBA2; //If y is less than 0 then it changes direction
}
else if (bBA1 < -5)
{
spdBBA1 = -spdBBA1;
}
else if (bBA2 + 10 > this.ClientSize.Height)
{
// If y + 10, the radius of the circle is greater than the
// form width then we change direction
spdBBA2 = -spdBBA2;
}
else if (bBA1 + 10 > this.ClientSize.Width)
{
spdBBA1 = -spdBBA1;
}
this.Invalidate();
}
Thank you.
Yes you can! This is one of the many cool features of object oriented programming.
Create a Ball class. When you start the game create all the balls you need and store them in a list. From there you can use foreach loops to modify the properties of each of your Ball objects.
public class Ball
{
public int speedX { get; private set; }
public int speedY { get; private set; }
public int positionX { get; private set; }
public int positionY { get; private set; }
public Ball(int speedX, int speedY, int positionX, int positionY)
{
this.speedX = speedX;
this.speedY = speedY;
this.positionX = positionX;
this.positionY = positionY;
}
public int setSpeedX(int newSpeed)
{
this.speedX = newSpeed;
}
//Add any other setters you need.
}
Now you have a blueprint for any balls you need to create. Then in your game you can do something like this:
public class StartGame
{
public List<Ball> ballList { get; private set; }
public StartGame()
{
this.ballList = new List<Ball>();
InitializeComponent();
}
private void StartGame_Load(object sender, EventArgs e)
{
//Add any balls you need here.
ballList.add(new Ball(5, 10, 1, 1));
ballList.add(new Ball(2, 17, 2, 9));
ballList.add(new Ball(4, 12, 7, 5));
}
private void StartGame_Paint_1(object sender, PaintEventArgs e)
{
//This foreach loop will run through all the balls in ballList
foreach(Ball ball in ballList)
{
e.Graphics.FillEllipse(Brushes.Blue, ball.positionX, ball.positionY, 10, 10);
e.Graphics.DrawEllipse(Pens.Blue, ball.positionX, ball.positionY, 10, 10);
}
}
}
I wasn't 100% sure how your game worked so I made some guesses with the variables but I hope you get the idea.
I would look at using a foreach and the list to store them all
Start by creating a ball class and, on start-up, create all the balls you want (at least that you need for the time being) and save that to the list, then just use a foreach loop to change anything you want with the ball(s).

Move a control in a circle at runtime?

I know you can change a control's x/y location at runtime and I can use a timer to move it up/down/left/right/diagonally but how can you programatically move it in a circle?
For example, if I had a PictureBox control at the 12 o'clock position on my main form, can I move that picture box in a circle, finishing at its start position, on a button click?
Use sinus and cosinus functions.
Look at that for example.
A concrete C# example exists here.
In case that the link will not exist some day, here is the source code for drawing 25 increasing radius circles on a form:
void PutPixel(Graphics g, int x, int y, Color c)
{
Bitmap bm = new Bitmap(1, 1);
bm.SetPixel(0, 0, Color.Red);
g.DrawImageUnscaled(bm, x, y);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics myGraphics = e.Graphics;
myGraphics.Clear(Color.White);
double radius = 5;
for (int j = 1; j <= 25; j++)
{
radius = (j + 1) * 5;
for (double i = 0.0; i < 360.0; i += 0.1)
{
double angle = i * System.Math.PI / 180;
int x = (int)(150 + radius * System.Math.Cos(angle));
int y = (int)(150 + radius * System.Math.Sin(angle));
PutPixel(myGraphics, x, y, Color.Red);
}
}
myGraphics.Dispose();
}
Result:
I've written a small class deriving from PictureBox which should let you achieve your result easily enough. Everytime you call RotateStep its location will change accordingly. Angle and speed are expressed in radians, distance in pixels.
class RotatingPictureBox : PictureBox
{
public double Angle { get; set; }
public double Speed { get; set; }
public double Distance { get; set; }
public void RotateStep()
{
var oldX = Math.Cos(Angle)*Distance;
var oldY = Math.Sin(Angle)*Distance;
Angle += Speed;
var x = Math.Cos(Angle)*Distance - oldX;
var y = Math.Sin(Angle)*Distance - oldY;
Location += new Size((int) x, (int) y);
}
}
Sample usage:
public Form1()
{
InitializeComponent();
var pictureBox = new RotatingPictureBox
{
Angle = Math.PI,
Speed = Math.PI/20,
Distance = 50,
BackColor = Color.Black,
Width = 10,
Height = 10,
Location = new Point(100, 50)
};
Controls.Add(pictureBox);
var timer = new Timer {Interval = 10};
timer.Tick += (sender, args) => pictureBox.RotateStep();
timer.Start();
}

Make an object move towards another objects position

What I have currently is two objects that can be played though nav keys and the other one with wasd. The point is to get the 3rd object and score a point, and it randoms a new pos after catching it, which works.
Now... I want the npc2 to not longer be controlled by human, and create a method for it to move on its own TOWARDS the scoring object. How would I possibly do to achieve this? Im new to c# :)
FORM.cs below
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace SPEL
{
public partial class Form1 : Form
{
npc npc1 = new npc();
npc npc2 = new npc();
sten ste1 = new sten();
int poang1 = 0;
int poang2 = 0;
private _keyControl cc = new _keyControl();
public Form1()
{
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
InitializeComponent();
// Hantera tangentbordet
#region captute evenents
this.KeyDown += new System.Windows.Forms.KeyEventHandler(cc.addKey);
this.KeyUp += new System.Windows.Forms.KeyEventHandler(cc.delKey);
#endregion
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
npc1.Rita(e.Graphics);
npc2.Rita(e.Graphics);
ste1.Draw(e.Graphics);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//MessageBox.Show(e.KeyData.ToString());
}
private void timer1_Tick(object sender, EventArgs e)
{
//spelare 1
this.Text = cc.keyStr;
if (cc.getKey("Right"))
{
npc1.Flytta("Right");
this.Invalidate();
}
if (cc.getKey("Left"))
{
npc1.Flytta("Left");
this.Invalidate();
}
if (cc.getKey("Up"))
{
npc1.Flytta("Up");
this.Invalidate();
}
if (cc.getKey("Down"))
{
npc1.Flytta("Down");
this.Invalidate();
}
//Spelare 2
if (cc.getKey("D"))
{
npc2.Flytta("Right");
this.Invalidate();
}
if (cc.getKey("A"))
{
npc2.Flytta("Left");
this.Invalidate();
}
if (cc.getKey("W"))
{
npc2.Flytta("Up");
this.Invalidate();
}
if (cc.getKey("S"))
{
npc2.Flytta("Down");
this.Invalidate();
}
if (npc1.checkkoll().IntersectsWith(ste1.checkkoll()))
{
poang1++;
ste1.randomxy(this.Width -30, this.Height -30);
}
if (npc2.checkkoll().IntersectsWith(ste1.checkkoll()))
{
poang2++;
ste1.randomxy(this.Width -30, this.Height -30);
}
}
private void timer2_Tick(object sender, EventArgs e)
{
if (this.BackColor == Color.Red)
this.BackColor = Color.Blue;
else
this.BackColor = Color.Red;
}
private void flytta_Tick(object sender, EventArgs e)
{
}
}
}
}
And here's my movement class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace SPEL
{
class npc
{
private Bitmap strid;
private Point pt;
public npc()
{
strid = new Bitmap("hej.gif");
pt.X = 20;
pt.Y = 20;
}
public void Rita(Graphics f)
{
Rectangle re = new Rectangle(pt.X, pt.Y, strid.Width, strid.Height);
f.DrawImage(strid, re);
}
public Rectangle checkkoll()
{
Rectangle re = new Rectangle(pt.X, pt.Y, strid.Width, strid.Height);
return re;
}
public void Flytta(string dir)
{
if (dir == "Left")
{
pt.X = pt.X - 2;
}
if (dir == "Right")
{
pt.X = pt.X + 2;
}
if (dir == "Up")
{
pt.Y = pt.Y - 2;
}
if (dir == "Down")
{
pt.Y = pt.Y + 2;
}
}
}
}
I do understand that it's much to ask for, but i'd be more than thankful if you could help me!
Try something like this
public void FlyttaMot(int x, int y, float speed)
{
float tx = x - pt.X;
float ty = y - pt.Y;
float length = Math.Sqrt(tx*tx + ty*ty);
if (length > speed)
{
// move towards the goal
pt.X = (int)(pt.X + speed* tx/length);
pt.Y = (int)(pt.Y + speed* ty/length);
}
else
{
// already there
pt.X = x;
pt.Y = y;
}
}
Call it from your timer tick code in Form.cs like this for example.
npc2.FlyttaMot(200, 200, 0.5f);
I based this on linear algebra. Take a look at this video for example. The (tx,ty) is the vector in which direction the npc should go. Dividing with the length of the vector gives us a vector of length 1. I multiply this with a speed parameter so you can adjust the speed of the npc.
The easiest and most accurate way, is to rely on vector geometry.
Define class
public class Vector2 {
public float x {get;set;};
public float y {get;set;};
public Vector2(float a_x, float a_y, float b_x, float b_y)
{
x = b_x - a_x;
y = b_y - a_y;
}
//calculate vector length
public float Length {
get {
return Math.Sqrt((x * x) + (y * y));
}
}
public void SetVectorLength(float desiredLength){
double r = desiredLength/ this.Length;
this.x *= r;
this.y *= r;
}
}
this is just a set of functions for this case, but you can add others, plenty of them need for various parts of your calculations.
After what you have to do is just, calculate next position of your vertex toward the directional vector.
//hypothetical X coordinate
float x_coord = 1.34f;
//move towards the vector
var vector = new Vector2(10, 10, 20, 20);
//set vector move step
vector.SetLength(0.1f);
var movedX = x_coord + vector.x;
Repeat: this is just hypothetical example, you need to work on this. It's hard to put in small answer all related vector geometry stuff.

Categories