using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace cForm
{
class xPoint
{
// Собственный статический генератор случайных чисел.
// Используется в конструкторе.
public static Random rnd = new Random();
// Цвет объекта.
public Color xColor;
// Текущая позиция. Относительные значения координат X и Y.
public Point p;
// Обеспечение перемещения. Текущие значения координат могут
// изменяться как по X, так и по Y.
public Point direction;
// Счетчик циклов сохранения выбранного направления.
// Объект на протяжении фиксированного интервала времени может
// сохранять ранее избранное направление движения.
// В течение n.X "тиков" для X в течение n.Y "тиков" для Y.
public Point n;
public xPoint(int X, int Y, int Xn, int Yn)
{
n = new Point(rnd.Next(0, Xn), rnd.Next(0, Yn));
direction = new Point(rnd.Next(-1, 2), rnd.Next(-1, 2));
p = new Point(X, Y);
xColor =
Color.FromArgb(150, rnd.Next(0, 256), rnd.Next(0, 256), rnd.Next(0, 256));
}
// Статический метод. Еще вопрос, где следовало размещать его
// объявление... Определение нового положения амебы.
// Просматривается ВЕСЬ список.
// Ее перемещение ограничивается физическими размерами клиентской области
// окна приложения и определяется по двум координатам (X и Y).
// В каждый момент она может оставаться на месте, либо изменить
// свое положение на один "шаг" по каждой из осей координат
// ("вверх" или "вниз" по оси Y и "вперед" или "назад" по оси X).
public static void setNextPosition(cForm cf, xPoint[] pt)
{
int i;
float xy;
// Итак, определение текущей позиции объекта.
// Просмотр массива...
for (i = 0; i < pt.Length; i++)
{
// Сначала разбираемся со значением координаты X.
// Вычисляем возможную позицию после перемещения объекта.
xy = (float)((pt[i].p.X + pt[i].direction.X) * cf.rPointGet);
// Вполне возможно, что это вполне подходящая позиция.
// И надо всего лишь проверить две вещи:
// 1. не выскочит ли объект за пределы клиентской области окна
// приложения,
// 2. не настало ли время поменять направление движения.
if (
xy < 0 || xy > cf.ClientSize.Width // 1.
||
pt[i].n.X > cf.NX // 2.
)
{
pt[i].n.X = 0; // Обнулили счетчик циклов сохранения выбранного направления.
// Процедура изменения направления перемещения по оси X.
// На ближайшую перспективу объект может переместиться
// вперед: pt[i].direction.X == 1,
// назад: pt[i].direction.X == –1,
// остаться на месте: pt[i].direction.X == 0.
// Главное — это не выйти за пределы клиентской области окна приложения.
pt[i].direction.X = xPoint.rnd.Next(-1, 2);
xy = (float)((pt[i].p.X + pt[i].direction.X) * cf.rPointGet);
if (xy >= 0 && xy <= cf.ClientSize.Width)
{
// Направление выбрано, перемещение произведено.
pt[i].p.X += pt[i].direction.X;
}
else
{
// Выбранное направление движения приводит к выходу объекта
// за пределы клиентской области окна приложения.
// На ближайшие cf.NX тактов объект остается неподвижен по оси X.
pt[i].direction.X = 0;
}
}
else
{
// Осуществили очередное перемещение по оси X.
pt[i].p.X += pt[i].direction.X;
pt[i].n.X++;
}
xy = (float)((pt[i].p.Y + pt[i].direction.Y) * cf.rPointGet);
// Вполне возможно, что это вполне подходящая позиция.
// И надо всего лишь проверить две вещи:
// 1. не выскочит ли объект за пределы клиентской области
// окна приложения,
// 2. не настало ли время поменять направление движения.
if (
xy < 0 || xy > cf.ClientSize.Height // 1.
||
pt[i].n.Y > cf.NY // 2.
)
{
pt[i].n.Y = 0; // Обнулили счетчик циклов сохранения выбранного направления.
// Процедура изменения направления перемещения по оси Y.
// На ближайшую перспективу объект может переместиться
// вверх: pt[i].direction.Y == 1,
// вниз: pt[i].direction.Y == -1,
// остаться на месте: pt[i].direction.Y == 0.
// Главное — это не выйти за пределы клиентской области окна приложения.
pt[i].direction.Y = xPoint.rnd.Next(-1, 2);
xy = (float)((pt[i].p.Y + pt[i].direction.Y) * cf.rPointGet);
if (xy >= 0 && xy <= cf.ClientSize.Height)
{
// Направление выбрано, перемещение произведено.
pt[i].p.Y += pt[i].direction.Y;
}
else
{
// Выбранное направление движения приводит к выходу объекта
// за пределы клиентской области окна приложения.
// На ближайшие cf.NY тактов объект остается неподвижен по оси Y.
pt[i].direction.Y = 0;
}
}
else
{
// Осуществили очередное перемещение по оси Y.
pt[i].p.Y += pt[i].direction.Y;
pt[i].n.Y++;
}
}
}
}
} |
Листинг 17.1. |
| Закрыть окно |