Horrible Flickering drawing in C# - c#

Anyone have any suggestions on how to stop this drawing from flickering? I have tried each double buffering solution, stopped using .CreateGraphics, moved all of my functions all over the place, nothing has worked.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Math
{
public partial class Form1 : Form
{
static Random rand = new Random();
ProblemBox[] problems = new ProblemBox[20];
#region Types
public enum Type
{
Basic, Algebric, Triginomic
}
public class Problem
{
public Type type;
public String problem, answer;
public Boolean isTrue;
public Problem(Type type, String problem, String answer, Boolean isTrue)
{
this.type = type;
this.problem = problem;
this.answer = answer;
this.isTrue = isTrue;
}
}
class ProblemBox
{
public Rectangle rect;
public Problem problem;
public ProblemBox(Problem problem)
{
rect = new Rectangle(0, 309, 244, 30);
this.problem = problem;
}
public void move()
{
rect.Y -= 1;
}
public void draw(Graphics g)
{
g.FillRectangle(Brushes.DarkGray, rect);
g.DrawString(problem.problem + "=" + problem.answer, new Font("Times New Roman", 12.0f), Brushes.DarkBlue, new PointF(rect.X + 5, rect.Y + 5));
}
}
#endregion
public Problem CreateProblem() {
char op = '+';
int a = rand.Next(20), b = rand.Next(20), c;
switch (rand.Next(4)) {
case 2:
c = a - b;
op = '-';
break;
case 3:
c = a * b;
op = '*';
break;
case 4:
c = a / b;
op = '/';
break;
default:
c = a + b;
op = '+';
break;
}
bool isTrue = rand.Next(2) == 1;
if (!isTrue) {
c += 1 + (10 - rand.Next(20));
}
return new Problem(Type.Basic, String.Concat(a + ""+op +""+ b), String.Concat(c), isTrue);
}
public Form1()
{
InitializeComponent();
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
problems[0] = new ProblemBox(CreateProblem());
}
private void panel1_Paint(object sender, PaintEventArgs e)//Tick
{
ProblemBox temp = null;
if (problems[0].rect.Y < 279)
{
temp = new ProblemBox(CreateProblem());
}
for (int i = 0; i < 20; i++)
{
if (temp != null)
{
ProblemBox temp2 = problems[i];
problems[i] = temp;
temp = temp2;
}
if (problems[i] != null)
{
problems[i].move();
problems[i].draw(e.Graphics);
}
}
Thread.Sleep(20);
DrawingPanel.Invalidate();
}
}
}

It's not a good idea to have
Thread.Sleep(20);
DrawingPanel.Invalidate();
inside Paint method. Try to avoid them and behavior may dramatically improved.

As Tigran already said, you problem is what you do not finishing repaint, which could be easily solve with something like:
(new Thread(() =>
{
Thread.Sleep(20);
this.BeginInvoke((MethodInvoker)delegate { DrawingPanel.Invalidate(); });
})).Start();
However, flickering can also occurs due to slow repainting (or rather say - not fast enough). Solution in that case if pretty simple - do not draw onto screen directly (use doublebuffering).
If you need some functionality from standard component, then you must create your own component and call it appropriately. Using Panel for something what has nothing to do for what Panel is intended for - is bad.
Here is a good starter:
[System.ComponentModel.DesignerCategory("Code")]
public class MyControl : PictureBox
{
public MyControl()
{
SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
// ...
}
}

Related

Exception of type 'System.StackOverflowException' was thrown.'

Why this? This is my code.
This is my "Kwadrat" class
public class Kwadrat : FormView
{
public int X {get;set;}
public int Y {get;set;}
public Kwadrat Parent { get; set; }
public void pozycja()
{
X = Parent.X;
Y = Parent.Y;
}
}
In this line visual Studio show me a error
Kwadrat k1 = new Kwadrat();
This is FormView.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
namespace ObjectMoving
{
public partial class FormView : Form
{
enum Position
{
Left, Right, Up, Down
};
private int NUMBER_OF_SQUARES=20;
private int SQUARE_SIZE=15;
Point _start = new Point(30,30);
private Position _objPosition;
Kwadrat k1 = new Kwadrat();
Kwadrat k2 = new Kwadrat();
private Kwadrat k3 = new Kwadrat();
List<Rectangle> Snake = new List<Rectangle>();
Losowanie l1=new Losowanie();
public FormView()
{
InitializeComponent();
_objPosition = Position.Down;
k1.X = 30;
k1.Y = 60;
k2.Parent = k1;
k2.X = 30;
k2.Y = 45;
k3.Parent = k2;
k3.X = 30;
k3.Y = 30;
l1.losowa();
}
private void FormView_Paint(object sender, PaintEventArgs e)
{
for (int i = 0; i <= NUMBER_OF_SQUARES; i++)
{
//rysowanie lini horyzontalnych
e.Graphics.DrawLine(new Pen(Brushes.Red),
_start.X,
_start.Y + SQUARE_SIZE * i,
_start.X + SQUARE_SIZE * NUMBER_OF_SQUARES,
_start.Y + SQUARE_SIZE * i);
//Rysowanie lini wertykalnych
e.Graphics.DrawLine(new Pen(Brushes.Brown),
_start.X + SQUARE_SIZE * i,
_start.Y,
_start.X + SQUARE_SIZE * i,
_start.Y + SQUARE_SIZE * NUMBER_OF_SQUARES);
}
e.Graphics.FillRectangle((Brushes.Aqua), k1.X, k1.Y, SQUARE_SIZE, SQUARE_SIZE);
e.Graphics.FillRectangle((Brushes.Aqua), k2.X, k2.Y, SQUARE_SIZE, SQUARE_SIZE);
e.Graphics.FillRectangle((Brushes.Aqua), k3.X, k3.Y, SQUARE_SIZE, SQUARE_SIZE);
e.Graphics.FillRectangle((Brushes.Red),l1.RandomNumber, l1.RandomNumber2, SQUARE_SIZE, SQUARE_SIZE);
//foreach (Rectangle Object in Snake)
//{
// e.Graphics.FillRectangle(new SolidBrush(Color.Aqua), k3.X, k3.Y, SQUARE_SIZE, SQUARE_SIZE);
//}
}
//odswiezanie
public void tmrMoving_Tick(object sender, EventArgs e)
{
//kolizja();
k3.pozycja();
k2.pozycja();
if (_objPosition == Position.Right)
{
k1.X += 15;
}
else if (_objPosition == Position.Left)
{
k1.X -= 15;
}
else if (_objPosition == Position.Up)
{
k1.Y -= 15;
}
else if (_objPosition == Position.Down)
{
k1.Y += 15;
}
if (k1.X < 29)
{
tmrMoving.Enabled = false;
tmrMoving.Stop();
MessageBox.Show("Wyjechales poza plansze");
Application.Exit();
}
else if (k1.X > 315)
{
tmrMoving.Enabled = false;
tmrMoving.Stop();
MessageBox.Show("Wyjechales poza plansze");
Application.Exit();
}
else if(k1.Y<29)
{
tmrMoving.Enabled = false;
tmrMoving.Stop();
MessageBox.Show("Wyjechales poza plansze");
Application.Exit();
}
else if (k1.Y > 315)
{
tmrMoving.Enabled = false;
tmrMoving.Stop();
MessageBox.Show("Wyjechales poza plansze");
Application.Exit();
}
Invalidate();
}
//ruch strzalkami
private void FormView_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Left)
{
// s1.Sprawdzenie();
_objPosition = Position.Left;
}
else if (e.KeyCode == Keys.Right)
{
_objPosition = Position.Right;
}
else if (e.KeyCode == Keys.Up)
{
_objPosition = Position.Up;
}
else if (e.KeyCode == Keys.Down)
{
_objPosition = Position.Down;
}
}
//public void kolizja()
//{
// if (k1.X == l1.RandomNumber && k1.Y == l1.RandomNumber2)
// {
// l1.losowa();
// Snake.Add(new Rectangle(k3.X, k3.Y, 15, 15));
// }
//}
}
}
The problem you have here is a flavour of "circular reference".
Your Kwadrat class is based on FormView, which means that whenever you create a new instance of Kwadrat, for example, the line you've called out where k1 is constructed, this means that the following happens:
We're creating a new instance of Kwadrat, so lets call its constructor
It inherits from FormView, so lets call its constructor and set its member variables, etc,..
We're in FormView, it needs an instance of Kwadrat, called K1, lets create that
Right now we loop back to "1" and then repeat forever, which is why you're receiving the StackOverflowException that you are. In this instance, the fact that the class we're looking at contains a property called Parent that is typed as itself is a "red herring" as it's not the cause of the error, though if you ever ended up with an instance of Kwadrat where Parent was set to self (e.g.instance.Parent = instance;) you'd potentially see the same error if an attempt was made to traverse the hierarchy of parents for that instance.

Resize image included in button when resize

I have a button with an included image and a text :
When I resize my application, I resize the label to fit with the new button's height but the image is not resized :
I saw a solution is to set image to BackgroundImage but it does not match the design of my button :
this.buttonClose.Dock = System.Windows.Forms.DockStyle.Fill;
this.buttonClose.Image = ((System.Drawing.Image)(resources.GetObject("buttonClose.Image")));
this.buttonClose.Name = "buttonClose";
this.buttonClose.Size = new System.Drawing.Size(482, 28);
this.buttonClose.Text = "Close";
this.buttonClose.TextAlign = ContentAlignment.MiddleRight;
this.buttonClose.TextImageRelation = TextImageRelation.ImageBeforeText;
this.buttonClose.UseVisualStyleBackColor = true;
this.buttonClose.Click += new System.EventHandler(this.buttonClose_Click);
if you want to automatically resize the application use this method
create class called resize
and paste this code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace YOUR APPLICATION NAMESPACE
{
public class ClassResize
{
List<System.Drawing.Rectangle> AryControlsStorage = new List<System.Drawing.Rectangle>();
private bool ShowRowHeader=false;
private Form form { get; set; }
private float FontSize { get; set; }
private System.Drawing.SizeF FormSize { get; set; }
public ClassResize(Form FForm)
{
form = FForm;
FormSize = FForm.ClientSize;
FontSize = FForm.Font.Size;
}
private static IEnumerable<Control> GetAllControls(Control c)
{
return c.Controls.Cast<Control>().SelectMany(item=>
GetAllControls(item)).Concat(c.Controls.Cast<Control>()).Where(control=>
control.Name !=string.Empty);
}
public void GetInitialSize()
{
var _Controls = GetAllControls(form);
foreach (Control control in _Controls)
{
AryControlsStorage.Add(control.Bounds);
if (control.GetType() == typeof(DataGridView))
DGColumnAdjust(((DataGridView)control), ShowRowHeader);
}
}
public void Resize()
{
double FormRatioWidth = (double)form.ClientSize.Width / (double)FormSize.Width;
double FormRatioHeight=(double)form.ClientSize.Height / (double)FormSize.Height;
var _Controls = GetAllControls(form);
int Postion = -1;
foreach(Control control in _Controls)
{
Postion += 1;
System.Drawing.Size _ControlsSize = new System.Drawing.Size((int)(AryControlsStorage[Postion].Width * FormRatioWidth),
(int)(AryControlsStorage[Postion].Height * FormRatioHeight));
System.Drawing.Point _ControlsPoint = new System.Drawing.Point((int)(AryControlsStorage[Postion].X * FormRatioWidth),
(int)(AryControlsStorage[Postion].Y * FormRatioHeight));
control.Bounds = new System.Drawing.Rectangle(_ControlsPoint, _ControlsSize);
if (control.GetType() == typeof(DataGridView))
DGColumnAdjust(((DataGridView)control),ShowRowHeader);
//control.Font = new System.Drawing.Font(form.Font.FontFamily,
//(float)(((Convert.ToDouble(FontSize) * FormRatioWidth) / 1.5) + ((Convert.ToDouble(FontSize) * FormRatioHeight) / 1.5)));
}
}
private void DGColumnAdjust(DataGridView dgv, bool _showRowHeader)
{
int intRowHeader = 0;
const int Hscrolbarwidth = 5;
if (_showRowHeader)
{
intRowHeader = dgv.RowHeadersWidth;
}
else
{
dgv.RowHeadersVisible = false;
}
for (int i = 0; i < dgv.ColumnCount; i++)
{
if (dgv.Dock == DockStyle.Fill)
dgv.Columns[i].Width = ((dgv.Width - intRowHeader) / dgv.ColumnCount);
else
dgv.Columns[i].Width = ((dgv.Width - intRowHeader - Hscrolbarwidth) / dgv.ColumnCount);
}
}
}
}
and call this class in you form
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;
using Common;
using System.Data.SqlClient;
namespace YOUR NAMESPACE
{
public partial class FORMNAME: Form
{
ClassResize Form;
public FORMNAME()
{
InitializeComponent();
Form = new ClassResize(this);
}
}
}
this will automatically resize your all controls in forms
Finally found a solution, maybe not the best but working fine :
private Dictionary<Button, Image> dicButtonsBaseImage = new Dictionary<Button, Image>();
private void SetImageButton(Button btn, Image img)
{
// Initiate image for button
btn.Image = img;
// set method dor sizeChanged
btn.SizeChanged += Control_SizeChanged;
// Save image associated for this button
if (!dicButtonsBaseImage.ContainsKey(btn))
dicButtonsBaseImage.Add(btn, img);
else
dicButtonsBaseImage[btn] = img;
// Init image size
resizeImageSize(btn);
}
private void Control_SizeChanged(object sender, EventArgs e)
{
Control c = sender as Control;
if (c != null)
{
Button b = sender as Button;
if (b != null)
{
resizeImageSize(b);
}
}
}
private static void resizeImageSize(Button b)
{
if (b.Image != null && dicButtonsBaseImage.ContainsKey(b))
{
// Set a margin (top/bot) to 8px
if (b.Height - 8 < dicButtonsBaseImage[b].Height)
{
int newHeight = b.Height - 8;
if (newHeight <= 0)
newHeight = 1;
Image img = new Bitmap(dicButtonsBaseImage[b], new Size(dicButtonsBaseImage[b].Width, newHeight));
b.Image = img;
}
else
{
b.Image = dicButtonsBaseImage[b];
}
}
}

Coloring text using reflection

I'm trying to make a simple text editor that colors text in real time. I also must use DLL and Reflection for this.
I want to color the text while user typing. For that reason I have a checkbox. If it checked the text will be colored while user is typing (Real Time).
I've wrote a DLL file to do that.
Anyway, I'm very new to reflection thing.
The question:
I would want to ask you guys for your professional advice whether what I've wrote can be called "using reflection" or not? and if it's not, can point me what is wrong?
Here is my code (I've removed many things from it so the code will reflect the question but there might be leftovers)
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Reflection;
namespace Editor
{
public class MainForm : Form
{
//Declaration of Controls
private RichTextBox EditRichTextBox;
private CheckBox chkBox;
private int flag = 0;
private Button[] PlugButton;
public string[] PluginNames;
private int NumofPlugins;
public MainForm()
{
//Initialization of Controls
this.EditRichTextBox = new RichTextBox();
this.ErrorTextBox = new RichTextBox();
this.chkBox = new CheckBox();
//Form
this.ClientSize = new Size(700, 500);
this.Name = "MainForm";
this.Text = "C# Editor";
//EditRichTextBox
this.EditRichTextBox.Location = new Point(20, 20);
this.EditRichTextBox.Name = "EditRichTextBox";
this.EditRichTextBox.Size = new Size(this.Width - 150, 300);
this.EditRichTextBox.AcceptsTab = true;
this.EditRichTextBox.Multiline = true;
//Controls on the Form
this.Controls.Add(this.ButtonCompilelib);
this.Controls.Add(this.ButtonCompile);
this.Controls.Add(this.ButtonRun);
this.Controls.Add(this.EditRichTextBox);
this.Controls.Add(this.ErrorTextBox);
this.Controls.Add(this.chkBox);
//CheckBox
this.chkBox.Location = new Point(600,300);
this.chkBox.Name = "chkBox";
this.chkBox.Text = "Color";
};
//My checkbox handler
this.chkBox.Click += (sender,e) =>
{
if(flag == 0)
{
flag = 1;
MessageBox.Show("Coloring Text");
}
else
flag = 0;
};
//My TextBox handler
this.EditRichTextBox.KeyPress += (sender,e) =>
{
try
{
string tmp = Environment.CurrentDirectory + "\\" + "mydll" + ".dll"; Assembly a = Assembly.LoadFrom(tmp);
Type t = a.GetType("MyPlugIn.colorclass");
MethodInfo mi = t.GetMethod("color");
Object obj = Activator.CreateInstance(t);
Object[] Params = new Object[5];
Params[0] = EditRichTextBox.Text;
Params[1] = EditRichTextBox.Handle;
Params[2] = ErrorTextBox.Handle;
Params[3] = EditRichTextBox;
Params[4] = flag;
mi.Invoke(obj, Params);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
};
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MainForm());
}
}
}
And this is the DLL file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace MyPlugIn
{
public class colorclass
{
public void color(string Text, Object Hndl_Text, Object Hndl_Err, RichTextBox box,int flag)
{
if (flag == 1)
{
int start = box.TextLength;
int end = box.TextLength;
//Textbox may transform chars, so (end-start) != text.Length
box.Select(start, end - start);
{
box.SelectionColor = Color.Blue;
}
box.SelectionLength = 0; // clear
}
}
}
}
Yes, your code uses Reflection. These lines are an example:
Type t = a.GetType("MyPlugIn.colorclass");
MethodInfo mi = t.GetMethod("color");
Object obj = Activator.CreateInstance(t);
Whether is the best approach or not, or whether it's necessary for this task, it's a different topic.

Why aren't the buttons in my C# Application working?

I am doing this lab out of a book on my own, and I made an application in which sharks are racing. There is a radio button that should update a label on the right dynamically, as well as a button that actually starts the race. Everything used to work and then I renamed a few things, and now nothing works.
Screenshot of application:
image http://cl.ly/f08f4e22761464e0c2f3/content
Form Class:
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 project1
{
public partial class Game : Form
{
private Shark[] sharks;
private Guy[] guys;
private Guy selectedGuy;
public Game()
{
InitializeComponent();
Random moreRandom = new Random();
int start = myTrack.Location.X;
int finish = myTrack.Width - 65;
sharks = new Shark[4]
{
new Shark() {myRandom = moreRandom, myPictureBox = myShark1, myPBStart = start, trackLength = finish},
new Shark() {myRandom = moreRandom, myPictureBox = myShark2, myPBStart = start, trackLength = finish},
new Shark() {myRandom = moreRandom, myPictureBox = myShark3, myPBStart = start, trackLength = finish},
new Shark() {myRandom = moreRandom, myPictureBox = myShark4, myPBStart = start, trackLength = finish}
};
guys = new Guy[3]
{
new Guy() {myName="Joe", cash=50, myRadioButton=rbGuy1, myLabel=labelBet1},
new Guy() {myName="Bob", cash=75, myRadioButton=rbGuy2, myLabel=labelBet2},
new Guy() {myName="Al", cash=45, myRadioButton=rbGuy3, myLabel=labelBet3}
};
selectedGuy = guys[0];
rbGuy1.Tag = guys[0];
rbGuy2.Tag = guys[1];
rbGuy3.Tag = guys[2];
updateGui();
}
private void myChanged(object sender, EventArgs e)
{
selectedGuy = getSelectedGuy(sender);
betterLabel.Text = selectedGuy.myName;
}
private void betAmountValue(object sender, EventArgs e)
{
updateMin();
}
private void Bet_Click(object sender, EventArgs e)
{
int bet = (int) betAmount.Value;
int myFish = (int) sharkNumber.Value;
selectedGuy.placeBet(bet, myFish);
updateGui();
}
private void raceBtn_Click(object sender, EventArgs e)
{
betBtn.Enabled = false;
bool noWinner = true;
while(noWinner)
{
for (int dogFish = 0; dogFish < sharks.Length; dogFish++)
{
Application.DoEvents();
if(sharks[dogFish].Swim())
{
showWinner(dogFish);
collectBets(dogFish);
noWinner = false;
}
}
}
updateGui();
betBtn.Enabled = true;
}
private void showWinner(int fish)
{
MessageBox.Show(string.Format("Winner Winner People Dinner! \nShark {0} won!", fish + 1));
}
private void collectBets(int fish)
{
for (int guyNumber = 0; guyNumber < guys.Length; guyNumber++)
{
guys[guyNumber].collect(fish + 1);
guys[guyNumber].resetBet();
}
}
private void updateMin()
{
minBetLabel.Text = string.Format("Minimum bet: 5 bucks", betAmount.Value);
}
private Guy getSelectedGuy(object sender)
{
RadioButton rb = (RadioButton)sender;
return (Guy)rb.Tag;
}
private void updateGui()
{
for (int guyNumber = 0; guyNumber < guys.Length; guyNumber++)
{
guys[guyNumber].updateLabels();
}
for (int fish = 0; fish < sharks.Length; fish++)
{
sharks[fish].startPosition();
}
updateMin();
}
}
}
Shark Class:
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace project1
{
public class Shark
{
public int myPBStart; // Where the PictureBox starts
public int trackLength; // How long the racetrack is
public PictureBox myPictureBox = null; // The PictureBox object
public int location = 0; // My location on the racetrack
public Random myRandom; // An instance of Random
public Shark()
{
location = 0;
myPictureBox = new PictureBox();
myRandom = new Random();
trackLength = 100;
myPBStart = 0;
}
public bool Swim()
{
int distance = myRandom.Next(1, 4);
location += distance;
movePB(distance);
return location > trackLength;
}
private void movePB(int distance)
{
Point p = myPictureBox.Location;
p.X += distance;
myPictureBox.Location = p;
}
public void startPosition()
{
location = myPBStart;
Point p = myPictureBox.Location;
p.X = location;
myPictureBox.Location = p;
}
}
}
I can supply more resources if needed, but this is the main gist of it.
Using Visual Studio, make sure of the following:
1) For each radio button, verify the CheckedChanged event is hooked up to your myChanged function.
2) Verify the "Bets" Button.Click event is hooked up to your Bet_Click function.
3) Verify the "Race!" Button.Click event is hooked up to your raceBtn_Click function.
A safe way to rename things is to right click on the variable name, Refactor, Rename. This will ensure any references to the variable are renamed properly
when you renamed them you probably did it by editing the code rather than by changing the control properties.
THe Winforms designer in VS created code for you behind the scenes that wires the invents up. This codes uses the control names. Look for a file called formname_designer.cs. Notice that there are lines that still have the old control names. You can change this code
This is why its a good habit to give controls nice names when you start.
Make sure that the events on your controls are still connected to the correct event handlers in your code. Sometimes when you rename things, this link can get broken.

generated Terrain wouldn't display in directX (C# )

Greetings
I genereated a terrain with this equation:
H(x,y) = (abs(sin(x * y)) + abs(sin(0,2 * x) + sin(0,4 * y)) + abs(cos(0,12 * x) + cos(0,47 * y))) * e^(0.005*(x+y))
Now, this gives me a mix of featuresize, and a nice slope. This works fine, when I plot it using scilab.
I tried to import this in a c# application.
The terrain is created in this code:
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
using System.Collections.Generic;
namespace Kamera_eins
{
public partial class Terrain : Form
{
public double[,] DTM;
string response ;
public Terrain()
{
InitializeComponent();
response = "";
DTM = new double[2048/4,2048/4];
}
public void BoxTheSky()
{
}
public void BoxTheLand()
{
mesh();
surf();
}
public void begin()
{
}
public void mesh()
{
response = "";
int i = new int();
int j = new int();
i = 0;
j = 0;
for (i=0;i<2048/4 ;i++ ) {
for (j=0;j<2048/4 ;j++ ) {
DTM[i,j] = Math.Abs (Math.Sin (j*i)) + Math.Abs(Math.Sin(0.2*i) * Math.Sin(0.4*j) ) + Math.Abs(Math.Cos(0.12* i) * Math.Cos(0.47*j));
DTM[i,j] = Math.Pow(Math.E, (0.012* (i + j)));
}
}
response = "DTM mesh ready";
}
public void surf()
{
}
}
}
This is kept in a file called terrain.cs, and i make this a winform, because i plan to add a simple textbox, where i can later make some sort of realtime log of the process.
Now, there is another file, and in that file, intend to display this terrain. this second file goes as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
namespace Kamera_eins
{
public class viewport : Form
{
public Microsoft.DirectX.Direct3D.Device device = null;
public PresentParameters presentparameter = new PresentParameters();
public bool device_exists;
public bool show;
public int HEIGHT;
public int WIDTH;
public string paintDesc;
private float angle ;
private CustomVertex.PositionColored[] vertices;
public double[,] heightData;
private int[] indices;
private IndexBuffer ib;
private VertexBuffer vb;
private Microsoft.DirectX.DirectInput.Device keyb;
//public
public viewport()
{
this.ClientSize = new System.Drawing.Size(600, 600);
this.Text = "Terrain viewport";
WIDTH = 2048 / 4;
HEIGHT = 2048 / 4;
heightData = new double[HEIGHT,WIDTH];
keyb = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
keyb.SetCooperativeLevel(this, CooperativeLevelFlags.Background | CooperativeLevelFlags.NonExclusive);
keyb.Acquire();
presentparameter.Windowed = true;
presentparameter.SwapEffect = SwapEffect.Discard;
presentparameter.AutoDepthStencilFormat = DepthFormat.D16;
presentparameter.EnableAutoDepthStencil = true;
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
try {
device = new Microsoft.DirectX.Direct3D.Device(0, Microsoft.DirectX.Direct3D.DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentparameter);
device.DeviceLost += new EventHandler(this.InvalidateDeviceObjects);
device.DeviceReset += new EventHandler(this.RestoreDeviceObjects);
device.Disposing += new EventHandler(this.DeleteDeviceObjects);
device.DeviceResizing += new CancelEventHandler(this.EnvironmentResizing);
device_exists = true;
} catch (Exception DirectException) {
device_exists = false;
}
}
private void setcamera()
{
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1f, 50f);
device.Transform.View = Matrix.LookAtLH (new Vector3(0, 0, 100), new Vector3(0, 0, 0) , new Vector3(0,0,1) );
device.RenderState.Lighting = false;
device.RenderState.FillMode = FillMode.WireFrame;
device.RenderState.CullMode = Cull.None;
}
public void declareVertex()
{
vb = new VertexBuffer(typeof(CustomVertex.PositionColored), HEIGHT*WIDTH, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);
vertices = new CustomVertex.PositionColored[HEIGHT*WIDTH];
for (int x=0;x< WIDTH;x++) {
for (int y=0; y< HEIGHT;y++) {
vertices[x + y * WIDTH].Position = new Vector3(x, y, (float)heightData[x,y]);
int r = Convert.ToInt32(205 * heightData[x,y] / 200 );
if(r>254)
r = 254;
vertices[x + y * WIDTH].Color = Color.FromArgb( r , 120 , 120).ToArgb();
}
}
vb.SetData(vertices, 0, LockFlags.None);
}
public void declareIndex()
{
ib = new IndexBuffer(typeof(int), (WIDTH-1)*(HEIGHT-1)*6, device, Usage.WriteOnly, Pool.Default);
indices = new int[(WIDTH-1)*(HEIGHT-1)*6];
for (int x=0;x< WIDTH-1;x++) {
for (int y=0; y< HEIGHT-1;y++) {
indices[(x+y*(WIDTH-1))*6] = (x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+1] = (x+1)+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+2] = x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+3] = (x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+4] = x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+5] = x+(y+1)*WIDTH;
}
}
ib.SetData(indices, 0, LockFlags.None);
}
protected override void Dispose (bool disposing)
{
base.Dispose(disposing);
MessageBox.Show("");
}
protected virtual void InvalidateDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void RestoreDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void DeleteDeviceObjects(object sender, EventArgs e)
{
}
protected virtual void EnvironmentResizing(object sender, CancelEventArgs e)
{
}
public void run()
{
while(this.Created)
{
render();
setcamera();
// optional: loading the height using functional call:
// loadheight();
Application.DoEvents();
}
}
public void render()
{
if (device != null)
{
device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
device.BeginScene();
//display terrain
device.VertexFormat = CustomVertex.PositionColored.Format;
device.SetStreamSource(0, vb, 0);
device.Indices = ib;
device.Transform.World = Matrix.Translation(-HEIGHT/2, -WIDTH/2, 0)*Matrix.RotationZ(angle) ;
device.DrawIndexedPrimitives(PrimitiveType.TriangleFan, 0, 0, WIDTH*HEIGHT, 0, indices.Length/3);
//turn off lights now
device.EndScene();
device.Present();
this.Invalidate();
readkeyboard();
}
}
void readkeyboard()
{
KeyboardState keys = keyb.GetCurrentKeyboardState();
if (keys[Key.Delete])
{
angle+=0.03f;
}
if (keys[Key.Next])
{
angle-=0.03f;
}
}
public void openport()
{
}
protected override void OnPaint(PaintEventArgs e)
{
render();
setcamera();
}
}
}
Now, yet a third file calls the world creation and display:
void MainFormLoad(object sender, EventArgs e)
{
world = new World();
world.setterrain();
}
the surf and box-somthing functions do not yet do anything.
All what i get now, is just a black window (the device.clear(... ) part) - i tried to adjust the camera .. no success
please help, i want to show the terrain in the window ....

Categories