Консультация № 191414
02.10.2017, 09:50
0.00 руб.
0 5 1
Здравствуйте! Прошу помощи в следующем вопросе:
OpenGl. Отталкивание шариков друг от друга. и При растягивании окна не изменяется размер шариков.
Можете объяснить что где и как происходит в программе (комментарии):
Код:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Tao.OpenGl;
using Tao.FreeGlut;
using Tao.Platform;
using System.Threading;



namespace Balls
{
public partial class Form1 : Form
{

static Random random = new Random();

public Form1()
{
InitializeComponent();
AnT.InitializeContexts();
}

public class Color
{
public double Red { get; set; }
public double Green { get; set; }
public double Blue { get; set; }

public Color(double red = 0, double green = 0, double blue = 1)
{
Red = red;
Green = green;
Blue = blue;
}
}

class Sphere
{
public double Radius { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public Color Color{ get; set; }

public Tuple<double, double> SpeedVector = new Tuple<double, double>(1, 1);

public Sphere(Color color, double Radius = 2, double X = 0, double Y = 0, double Z = 0)
{
this.Radius = Radius;
this.X = X;
this.Y = Y;
this.Z = Z;
Color = new Color(color.Red, color.Green, color.Blue);
}
}

class BounceSpheres
{

public double SizeScreen = 10;

// отношения сторон окна визуализации
// для корректного перевода координат мыши в координаты,
// принятые в программе


public Tao.Platform.Windows.SimpleOpenGlControl AnT;

public void ReloadMatrix()
{
Gl.glViewport(0, 0, AnT.Width, AnT.Height);
// настройка проекции
Gl.glMatrixMode(Gl.GL_PROJECTION);
//очистка матрицы
Gl.glLoadIdentity();

Glu.gluOrtho2D(0.0, (double)AnT.Width / SizeScreen, 0.0, (double)AnT.Height / SizeScreen);

//Glu.gluPerspective(45, (float)AnT.Width / (float)AnT.Height, 0.1, 200);

// установка объектно-видовой матрицы
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();

Gl.glEnable(Gl.GL_DEPTH_TEST);
Gl.glEnable(Gl.GL_COLOR_MATERIAL);


}



public BounceSpheres(Tao.Platform.Windows.SimpleOpenGlControl glControl)
{
AnT = glControl;

// инициализация Glut
Glut.glutInit();

Glut.glutInitDisplayMode(Glut.GLUT_RGB | Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH);

// очистка окна
Gl.glClearColor(255, 255, 255, 1);

ReloadMatrix();
}

public Sphere Ball1 = new Sphere(new Color(0, 0, 255), 6, 12 , 14);
public Sphere Ball2 = new Sphere(new Color(0, 255, 0), 2 ,23,20);

public void DrawSphere(Sphere sphere, Sphere sphere2)
{

Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glLoadIdentity();

CheckSphereCollision(sphere, sphere2);

Gl.glColor3d(sphere.Color.Red, sphere.Color.Green, sphere.Color.Blue);

Gl.glClearColor(255, 255, 255, 1);
Gl.glPushMatrix();

Gl.glTranslated(sphere.X + sphere.SpeedVector.Item1, sphere.Y + sphere.SpeedVector.Item2, sphere.Radius);
sphere.X += sphere.SpeedVector.Item1;
sphere.Y += sphere.SpeedVector.Item2;

Gl.glRotated(140 + sphere.X, 1, 1, 0 );

//Glut.glutSolidSphere(1,32,32);
Glut.glutWireSphere(sphere.Radius, 64, 64);
Gl.glPopMatrix();


Gl.glPushMatrix();
Gl.glColor3d(sphere2.Color.Red, sphere2.Color.Green, sphere2.Color.Blue);
Gl.glTranslated(sphere2.X + sphere2.SpeedVector.Item1, sphere2.Y + sphere2.SpeedVector.Item2, sphere2.Radius);
sphere2.X += sphere2.SpeedVector.Item1;
sphere2.Y += sphere2.SpeedVector.Item2;

Gl.glRotated(10 + sphere.Y , 1, 1, 0 );

//Glut.glutSolidSphere(1,32,32);
Glut.glutWireSphere(sphere2.Radius, 64, 64);
Gl.glPopMatrix();

Gl.glFlush();
AnT.Invalidate();

}


void CheckSphereCollision(Sphere sphere1, Sphere sphere2)
{
double R = (sphere1.X - sphere2.X) * (sphere1.X - sphere2.X) + (sphere1.Y - sphere2.Y) * (sphere1.Y - sphere2.Y);
if (sphere1.Radius * sphere1.Radius + sphere2.Radius * sphere2.Radius + 2* sphere1.Radius * sphere2.Radius >=R + 30)
{
sphere1.SpeedVector = new Tuple<double, double>(-sphere1.SpeedVector.Item1, -sphere1.SpeedVector.Item2);
sphere2.SpeedVector = new Tuple<double, double>(-sphere2.SpeedVector.Item1, -sphere2.SpeedVector.Item2);
}

if (sphere1.X + sphere1.Radius >= (AnT.Width / SizeScreen + 1) || (sphere1.X - sphere1.Radius + 3) <= 0)
sphere1.SpeedVector = new Tuple<double, double>(-sphere1.SpeedVector.Item1, sphere1.SpeedVector.Item2);
if (sphere1.Y + sphere1.Radius >= (AnT.Height / SizeScreen) + 3 || sphere1.Y - sphere1.Radius - 2.9 <= 0)
sphere1.SpeedVector = new Tuple<double, double>(sphere1.SpeedVector.Item1, -sphere1.SpeedVector.Item2);

if (sphere2.X + sphere2.Radius >= (AnT.Width / SizeScreen -2) || (sphere2.X - sphere2.Radius - 1) <= 0)
sphere2.SpeedVector = new Tuple<double, double>(-sphere2.SpeedVector.Item1, sphere2.SpeedVector.Item2);
if (sphere2.Y + sphere2.Radius >= (AnT.Height / SizeScreen) - 1 || sphere2.Y - sphere2.Radius - 4 <= 0)
sphere2.SpeedVector = new Tuple<double, double>(sphere2.SpeedVector.Item1, -sphere2.SpeedVector.Item2);

}
}

BounceSpheres spheres;

private void Form1_Load(object sender, EventArgs e)
{
//AnT.Height = this.Height;
//AnT.Width = this.Width;



AnT.Size = this.Size;
spheres = new BounceSpheres(AnT);
spheres.Ball1.SpeedVector = new Tuple<double, double>(0.5, 0.5);
spheres.Ball2.SpeedVector = new Tuple<double, double>(2, 2);

TimerRender.Start();
}


private void RenderTimer_Tick(object sender, EventArgs e)
{
//spheres.DrawSphere(spheres.Ball1);
spheres.DrawSphere(spheres.Ball1, spheres.Ball2);
}

private void Form1_SizeChanged(object sender, EventArgs e)
{
this.AnT.Size = this.Size;
// spheres.AnT = this.AnT;
spheres.ReloadMatrix();
}
}
}

Обсуждение

давно
Советник
400484
472
02.10.2017, 10:03
общий
Адресаты:
Добрый день,
многоуважаемый, а где вы изменяете размер шариков, при изменение размера окна??? Я этого не нашел.
Может есть смысл добавить метод ResizeRedraw() или Size() для обработки изменения размера окна. В нем и изменять радиус шара пропорциональна увеличению размера окна.
давно
Посетитель
399158
228
02.10.2017, 10:04
общий
они и не должны изменяться. все работает правильно, вы можете просто комментарии написать что и где происходит?
давно
Советник
400484
472
02.10.2017, 10:29
общий
Добавил комментарии. Что-то еще пояснить?
Код:
// подключение классов
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Tao.OpenGl;
using Tao.FreeGlut;
using Tao.Platform;
using System.Threading;

namespace Balls
{
// создание класса окна
public partial class Form1 : Form
{
// получение рандомного числа
static Random random = new Random();
// конструктор окна
public Form1()
{
InitializeComponent();
AnT.InitializeContexts();
}
// класс цвета шара
public class Color
{
// переменные цвета
public double Red { get; set; }
public double Green { get; set; }
public double Blue { get; set; }
// конструктор цвета
public Color(double red = 0, double green = 0, double blue = 1)
{
Red = red;
Green = green;
Blue = blue;
}
}
// класс сфера
class Sphere
{
// переменные шара
public double Radius { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public Color Color { get; set; }
public Tuple<double, double> SpeedVector = new Tuple<double, double>(1, 1);
// конструктор сферы
public Sphere(Color color, double Radius = 2, double X = 0, double Y = 0, double Z = 0)
{
this.Radius = Radius;
this.X = X;
this.Y = Y;
this.Z = Z;
Color = new Color(color.Red, color.Green, color.Blue);
}
}
// класс взаимодействия сфер
class BounceSpheres
{

public double SizeScreen = 10;
// отношения сторон окна визуализации
// для корректного перевода координат мыши в координаты,
// принятые в программе
public Tao.Platform.Windows.SimpleOpenGlControl AnT;
// метод изменения координат рабочего окна на координаты окна программы
public void ReloadMatrix()
{
Gl.glViewport(0, 0, AnT.Width, AnT.Height);
// настройка проекции
Gl.glMatrixMode(Gl.GL_PROJECTION);
//очистка матрицы
Gl.glLoadIdentity();
Glu.gluOrtho2D(0.0, (double)AnT.Width / SizeScreen, 0.0, (double)AnT.Height / SizeScreen);
//Glu.gluPerspective(45, (float)AnT.Width / (float)AnT.Height, 0.1, 200);

// установка объектно-видовой матрицы
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();
Gl.glEnable(Gl.GL_DEPTH_TEST);
Gl.glEnable(Gl.GL_COLOR_MATERIAL);

}

// конструктор класса
public BounceSpheres(Tao.Platform.Windows.SimpleOpenGlControl glControl)
{
AnT = glControl;
// инициализация Glut
Glut.glutInit();
Glut.glutInitDisplayMode(Glut.GLUT_RGB | Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH);
// очистка окна
Gl.glClearColor(255, 255, 255, 1);
ReloadMatrix();
}
// создание 2 шаров
public Sphere Ball1 = new Sphere(new Color(0, 0, 255), 6, 12, 14);
public Sphere Ball2 = new Sphere(new Color(0, 255, 0), 2, 23, 20);
// метод вывода на экран сферы
public void DrawSphere(Sphere sphere, Sphere sphere2)
{
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glLoadIdentity();
CheckSphereCollision(sphere, sphere2);
Gl.glColor3d(sphere.Color.Red, sphere.Color.Green, sphere.Color.Blue);
Gl.glClearColor(255, 255, 255, 1);
Gl.glPushMatrix();

Gl.glTranslated(sphere.X + sphere.SpeedVector.Item1, sphere.Y + sphere.SpeedVector.Item2, sphere.Radius);
sphere.X += sphere.SpeedVector.Item1;
sphere.Y += sphere.SpeedVector.Item2;
Gl.glRotated(140 + sphere.X, 1, 1, 0);

//Glut.glutSolidSphere(1,32,32);
Glut.glutWireSphere(sphere.Radius, 64, 64);
Gl.glPopMatrix();

Gl.glPushMatrix();
Gl.glColor3d(sphere2.Color.Red, sphere2.Color.Green, sphere2.Color.Blue);
Gl.glTranslated(sphere2.X + sphere2.SpeedVector.Item1, sphere2.Y + sphere2.SpeedVector.Item2, sphere2.Radius);
sphere2.X += sphere2.SpeedVector.Item1;
sphere2.Y += sphere2.SpeedVector.Item2;
Gl.glRotated(10 + sphere.Y, 1, 1, 0);
//Glut.glutSolidSphere(1,32,32);
Glut.glutWireSphere(sphere2.Radius, 64, 64);
Gl.glPopMatrix();
Gl.glFlush();
AnT.Invalidate();
}
// метод столкновения сфер
void CheckSphereCollision(Sphere sphere1, Sphere sphere2)
{
double R = (sphere1.X - sphere2.X) * (sphere1.X - sphere2.X) + (sphere1.Y - sphere2.Y) * (sphere1.Y - sphere2.Y);
if (sphere1.Radius * sphere1.Radius + sphere2.Radius * sphere2.Radius + 2 * sphere1.Radius * sphere2.Radius >= R + 30)
{
sphere1.SpeedVector = new Tuple<double, double>(-sphere1.SpeedVector.Item1, -sphere1.SpeedVector.Item2);
sphere2.SpeedVector = new Tuple<double, double>(-sphere2.SpeedVector.Item1, -sphere2.SpeedVector.Item2);
}
if (sphere1.X + sphere1.Radius >= (AnT.Width / SizeScreen + 1) || (sphere1.X - sphere1.Radius + 3) <= 0)
sphere1.SpeedVector = new Tuple<double, double>(-sphere1.SpeedVector.Item1, sphere1.SpeedVector.Item2);
if (sphere1.Y + sphere1.Radius >= (AnT.Height / SizeScreen) + 3 || sphere1.Y - sphere1.Radius - 2.9 <= 0)
sphere1.SpeedVector = new Tuple<double, double>(sphere1.SpeedVector.Item1, -sphere1.SpeedVector.Item2);
if (sphere2.X + sphere2.Radius >= (AnT.Width / SizeScreen - 2) || (sphere2.X - sphere2.Radius - 1) <= 0)
sphere2.SpeedVector = new Tuple<double, double>(-sphere2.SpeedVector.Item1, sphere2.SpeedVector.Item2);
if (sphere2.Y + sphere2.Radius >= (AnT.Height / SizeScreen) - 1 || sphere2.Y - sphere2.Radius - 4 <= 0)
sphere2.SpeedVector = new Tuple<double, double>(sphere2.SpeedVector.Item1, -sphere2.SpeedVector.Item2);
}
}
// экземпляр класса
BounceSpheres spheres;
// метод происходит до первоначального отображения формы
private void Form1_Load(object sender, EventArgs e)
{
//AnT.Height = this.Height;
//AnT.Width = this.Width;

AnT.Size = this.Size;
spheres = new BounceSpheres(AnT);
spheres.Ball1.SpeedVector = new Tuple<double, double>(0.5, 0.5);
spheres.Ball2.SpeedVector = new Tuple<double, double>(2, 2);
TimerRender.Start();
}
// метод перерисовки по таймеру
private void RenderTimer_Tick(object sender, EventArgs e)
{
//spheres.DrawSphere(spheres.Ball1);
spheres.DrawSphere(spheres.Ball1, spheres.Ball2);
}
// метод проверки изменения размера окна
private void Form1_SizeChanged(object sender, EventArgs e)
{
this.AnT.Size = this.Size;
// spheres.AnT = this.AnT;
spheres.ReloadMatrix();
}
}
}
давно
Посетитель
399158
228
04.10.2017, 09:36
общий
Спасибо
давно
Советник
400484
472
04.10.2017, 09:46
общий
это ответ
Здравствуйте, Посетитель - 399158!
// подключение классов
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Tao.OpenGl;
using Tao.FreeGlut;
using Tao.Platform;
using System.Threading;
namespace Balls
{
// создание класса окна
public partial class Form1 : Form
{
// получение рандомного числа
static Random random = new Random();
// конструктор окна
public Form1()
{
InitializeComponent();
AnT.InitializeContexts();
}
// класс цвета шара
public class Color
{
// переменные цвета
public double Red { get; set; }
public double Green { get; set; }
public double Blue { get; set; }
// конструктор цвета
public Color(double red = 0, double green = 0, double blue = 1)
{
Red = red;
Green = green;
Blue = blue;
}
}
// класс сфера
class Sphere
{
// переменные шара
public double Radius { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public Color Color { get; set; }
public Tuple<double, double> SpeedVector = new Tuple<double, double>(1, 1);
// конструктор сферы
public Sphere(Color color, double Radius = 2, double X = 0, double Y = 0, double Z = 0)
{
this.Radius = Radius;
this.X = X;
this.Y = Y;
this.Z = Z;
Color = new Color(color.Red, color.Green, color.Blue);
}
}
// класс взаимодействия сфер
class BounceSpheres
{
public double SizeScreen = 10;
// отношения сторон окна визуализации
// для корректного перевода координат мыши в координаты,
// принятые в программе
public Tao.Platform.Windows.SimpleOpenGlControl AnT;
// метод изменения координат рабочего окна на координаты окна программы
public void ReloadMatrix()
{
Gl.glViewport(0, 0, AnT.Width, AnT.Height);
// настройка проекции
Gl.glMatrixMode(Gl.GL_PROJECTION);
//очистка матрицы
Gl.glLoadIdentity();
Glu.gluOrtho2D(0.0, (double)AnT.Width / SizeScreen, 0.0, (double)AnT.Height / SizeScreen);
//Glu.gluPerspective(45, (float)AnT.Width / (float)AnT.Height, 0.1, 200);
// установка объектно-видовой матрицы
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();
Gl.glEnable(Gl.GL_DEPTH_TEST);
Gl.glEnable(Gl.GL_COLOR_MATERIAL);
}
// конструктор класса
public BounceSpheres(Tao.Platform.Windows.SimpleOpenGlControl glControl)
{
AnT = glControl;
// инициализация Glut
Glut.glutInit();
Glut.glutInitDisplayMode(Glut.GLUT_RGB | Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH);
// очистка окна
Gl.glClearColor(255, 255, 255, 1);
ReloadMatrix();
}
// создание 2 шаров
public Sphere Ball1 = new Sphere(new Color(0, 0, 255), 6, 12, 14);
public Sphere Ball2 = new Sphere(new Color(0, 255, 0), 2, 23, 20);
// метод вывода на экран сферы
public void DrawSphere(Sphere sphere, Sphere sphere2)
{
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glLoadIdentity();
CheckSphereCollision(sphere, sphere2);
Gl.glColor3d(sphere.Color.Red, sphere.Color.Green, sphere.Color.Blue);
Gl.glClearColor(255, 255, 255, 1);
Gl.glPushMatrix();
Gl.glTranslated(sphere.X + sphere.SpeedVector.Item1, sphere.Y + sphere.SpeedVector.Item2, sphere.Radius);
sphere.X += sphere.SpeedVector.Item1;
sphere.Y += sphere.SpeedVector.Item2;
Gl.glRotated(140 + sphere.X, 1, 1, 0);
//Glut.glutSolidSphere(1,32,32);
Glut.glutWireSphere(sphere.Radius, 64, 64);
Gl.glPopMatrix();
Gl.glPushMatrix();
Gl.glColor3d(sphere2.Color.Red, sphere2.Color.Green, sphere2.Color.Blue);
Gl.glTranslated(sphere2.X + sphere2.SpeedVector.Item1, sphere2.Y + sphere2.SpeedVector.Item2, sphere2.Radius);
sphere2.X += sphere2.SpeedVector.Item1;
sphere2.Y += sphere2.SpeedVector.Item2;
Gl.glRotated(10 + sphere.Y, 1, 1, 0);
//Glut.glutSolidSphere(1,32,32);
Glut.glutWireSphere(sphere2.Radius, 64, 64);
Gl.glPopMatrix();
Gl.glFlush();
AnT.Invalidate();
}
// метод столкновения сфер
void CheckSphereCollision(Sphere sphere1, Sphere sphere2)
{
double R = (sphere1.X - sphere2.X) * (sphere1.X - sphere2.X) + (sphere1.Y - sphere2.Y) * (sphere1.Y - sphere2.Y);
if (sphere1.Radius * sphere1.Radius + sphere2.Radius * sphere2.Radius + 2 * sphere1.Radius * sphere2.Radius >= R + 30)
{
sphere1.SpeedVector = new Tuple<double, double>(-sphere1.SpeedVector.Item1, -sphere1.SpeedVector.Item2);
sphere2.SpeedVector = new Tuple<double, double>(-sphere2.SpeedVector.Item1, -sphere2.SpeedVector.Item2);
}
if (sphere1.X + sphere1.Radius >= (AnT.Width / SizeScreen + 1) || (sphere1.X - sphere1.Radius + 3) <= 0)
sphere1.SpeedVector = new Tuple<double, double>(-sphere1.SpeedVector.Item1, sphere1.SpeedVector.Item2);
if (sphere1.Y + sphere1.Radius >= (AnT.Height / SizeScreen) + 3 || sphere1.Y - sphere1.Radius - 2.9 <= 0)
sphere1.SpeedVector = new Tuple<double, double>(sphere1.SpeedVector.Item1, -sphere1.SpeedVector.Item2);
if (sphere2.X + sphere2.Radius >= (AnT.Width / SizeScreen - 2) || (sphere2.X - sphere2.Radius - 1) <= 0)
sphere2.SpeedVector = new Tuple<double, double>(-sphere2.SpeedVector.Item1, sphere2.SpeedVector.Item2);
if (sphere2.Y + sphere2.Radius >= (AnT.Height / SizeScreen) - 1 || sphere2.Y - sphere2.Radius - 4 <= 0)
sphere2.SpeedVector = new Tuple<double, double>(sphere2.SpeedVector.Item1, -sphere2.SpeedVector.Item2);
}
}
// экземпляр класса
BounceSpheres spheres;
// метод происходит до первоначального отображения формы
private void Form1_Load(object sender, EventArgs e)
{
//AnT.Height = this.Height;
//AnT.Width = this.Width;
AnT.Size = this.Size;
spheres = new BounceSpheres(AnT);
spheres.Ball1.SpeedVector = new Tuple<double, double>(0.5, 0.5);
spheres.Ball2.SpeedVector = new Tuple<double, double>(2, 2);
TimerRender.Start();
}
// метод перерисовки по таймеру
private void RenderTimer_Tick(object sender, EventArgs e)
{
//spheres.DrawSphere(spheres.Ball1);
spheres.DrawSphere(spheres.Ball1, spheres.Ball2);
}
// метод проверки изменения размера окна
private void Form1_SizeChanged(object sender, EventArgs e)
{
this.AnT.Size = this.Size;
// spheres.AnT = this.AnT;
spheres.ReloadMatrix();
}
}
}
5
Спасибо большое
Форма ответа