Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Многопоточность и ООП в С#, Новичку 
:(
    Опции темы
headzero
Дата 14.2.2007, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 14.11.2006

Репутация: нет
Всего: 1



Я новичок. Только разбираюсь с ООП в С#.Допустим(чисто теоретически),
что мне нужно создать игру бильярд. Как я понимаю, мне нужно создать класс Ball и чтобы все шарики перемещались по столу одновременно,для каждого обьекта класса Ball т.е для каждого шариканужно выделить отдельный поток? Или можно не создавать потоки? Тогда шарик будут двигаться по очереди?Как вообще релизуется параллелное двмжение объектов в С#?Обьясните.Спасибо.


--------------------
Воображение важнее знания
                                                     (Алберт Эйнштейн)
PM MAIL   Вверх
marcusmae
Дата 14.2.2007, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Во-первых, вычисления не обязательно должны объединяться с их визуализацией. То есть, нет проблемы сначала расчитать всю Вашу физику, а затем прорисовать движение шариков, разве не так? Во-вторых, как только Вы просчитаете их уравнения движения, отрисовку можно делать последовательно, но с достаточно малым шагом по времени.


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
nikitao
Дата 14.2.2007, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кот-программист
***


Профиль
Группа: Завсегдатай
Сообщений: 1206
Регистрация: 30.8.2005
Где: Спб

Репутация: 4
Всего: 26



headzero, просто организовываешь игровой цикл примерно выглядищий так :

Снятие данных пользователя
Вычесление новых координат каждого шарика
Прорисовка сцены.

Потоки юзать не надо. ( для такой задачи ).


--------------------
Жизнь - печальная штука.
PM MAIL ICQ Skype GTalk   Вверх
-Mikle-
Дата 14.2.2007, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 17
Всего: 59



Навскидку такое решение в голову пришло:

Ball  -  класс шарика, содержащий в себе метод по-шагового вычисления
BallPainter - клас, который может отрисовать любой шарик в соответствии с его состоянием (координатами)

Каждый шарик имеет свойства IsStoped (стоит), Strength(сила/скорость), IsLeave (упал в лунку) и т.д., свойства меняются в соответствии с результатами вычислений в DoStep().

Ball.MoveTo(.....) - задает направление движения (не координаты конечной точки шарика) и силу (скорость) движения и устанавливает свойство IsStoped = false

bool Ball.DoStep() - вычисляет следующие координаты шарика, опираясь на реальное время с момента вызова Ball.MoveTo(), возвращает false, если шарик остановился. Этот метод должен как-то взаимодействовать с окружающими шариками и иметь границы стола и точки-лунки, для вычисления движения (методов реализации много). При столкновении с другими шариками, он должен вывать метод MoveTo() у того шарика, с которым столкнулся, передав в качестве параметра свое текущее направление и "силу" движения. TЕсли шарик упал в лунку, то IsLeave = true, IsStoped = true, return false. Если расчет закончился, то IsStoped = true и return false.

BallCollection - содержит все шарики
После удара по шару, бежишь циклом по всем шарикам и вызываешь метод DoStep у тех, у которых IsStoped = false и рисуешь шарик BallPainter.Draw(Ball). Повторяешь пробег по коллекции, пока хоть один шарик имеет свойство IsStoped = false.

Все это можно делать в основном потоке или в ОДНОМ отдельном потоке, если основной должен еще чем нибудь заниматься.

Все выше - это поток моих мыслей, незнаю, есть ли практическое применение им или нет.

PS: Как-то раз, очень давно, я написал на QBasic программу, которая делала "одновременно" несколько задач на экране. Это в том языке где ООП, классы и потоки, вообще считалось "синтаксической ошибкой"  smile 


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
marcusmae
Дата 14.2.2007, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Гулять - так гулять  smile. Предложение по иллюстрации потока мыслей -Mikle-

Сначала определим класс-шарик :

Код

public class Ball : BallPainter
{
    private int number;
    /// Получить номер шарика
    public int Number { get { return this.number; } }

    /// Предельное изменение позиции шарика, после которого считать, что он остановился
    private double epsilon;

    private bool isStopped = true;
    /// Остановился ли
    public bool IsStopped { get { return this.isStopped; } }

    private bool isLeft = false;
    /// Упал ли в лунку
    public bool IsLeft { get { return this.isLeft; } }

    /// шаг по времени
    protected double timeStep;

    /// текущее время
    protected  double currentTime;

    private Point currentPosition;
    /// текущая позиция
    public Point CurrentPosition { get { return this.currentPosition; } }

    /// радиус шарика
    private double radius;

    /// проверка на соударение данного шарика и шарика-параметра
    public bool Meets(Ball ball)
    {
        if ((this.currentPosition.X - ball.CurrentPosition.X < 2d * this.radius) ||
            (this.currentPosition.Y - ball.CurrentPosition.Y < 2d * this.radius)) return true;
        return false;
    }

    /// делегат, представляющий собой уравнение движения
    public delegate Point MovingEquationDelegate(double t);

    private MovingEquationDelegate movingEquation;
    /// задать уравнение движения
    public MovingEquationDelegate MovingEquation
    { set { this.movingEquation = value; this.currentTime = 0; } }

    /// продвинуть шарик за шаг времени по уравнению движения от данной позиции
    protected void MoveStep() 
    {
        if (!this.isStopped)
        {
            this.currentTime += this.timeStep;
            this.Erease(this.currentPosition);
            Point newPosition = this.MovingEquation(this.currentTime);

            // проверяем, не остановился ли
            Point difference = new Point(
                this.currentPosition.X - newPositionX,
                this.currentPosition.Y - newPositionY);
            if ((difference.X<this.epsilon) && (difference.Y<this.epsilon))
                this.isStopped = true;

            this.currentPosition = newPosition;

            this.Draw(this.currentPosition);
        }
    }

    ...

    public Ball(int number, double timeStep, Point currentPosition, double radius)
    {
        this.number = number; this.timeStep = timeStep; this.radius = radius;
        this.currentPosition = currentPosition;
    }
}


Класс шарика унаследуем от рисователя, методы которого могут быть описаны в зависимости от графических возможностей :

Код

public class BallPainter
{
    /// отрисовать шарик в точке
    private Draw(Point point)
    { ... }

    /// стереть шарик
    private Erease(Point point)
    { ... }
}


Также понадобилась структура, определяющая точку на плоскости :

Код

public struct Point
{
    public double X;
    public double Y;
}


Шарики готовы, определим теперь класс-коллекцию :

Код

public class BallCollection
{
    protected Ball[] balls = new Ball[?] // убейте : не помню, сколько шаров на стандартном столе :)))

    /// получить/установить шарик с номером ballNumber
    public this[int ballNumber]
    {
        get { return this.balls[ballNumber; }
        set { this.balls[ballNumber] = value; }
    }

    public BallCollection(double timeStep, radius, Point[] positions)
    {
        for (int ballIndex=0; ballIndex<balls.Length; ballIndex++)
            balls[ballIndex] = new Ball(ballIndex, timeStep, positions[ballIndex], radius);
    }
}


И, наконец, основной класс физики игры, наследующийся от коллекции шариков :

Код

public class Billyard : BallCollection
{
    /// делегат на функцию, умеющую пересчитывать уравнения двух шариков при соударении
    /// backstage : закон сохр-я импульса и т.п.
    public delegate void RecomputeEquationsDelegate(ref Balls.MovingEquationDelegate equation1,
        ref Balls.MovingEquationDelegate equation2);

    private RecomputeEquationsDelegate recomputeEquations;

    /// конструктор
    public Billyard(double timeStep, double radius,
        RecomputeEquationsDelegate recomputeEquations,
        Point[] positions)
        // positions - начальные позиции шариков (не забудьте выравнить треугольной рамкой! ;-)  )
        : base(timestep, radius, positions) // прокидываем конструктору базового класса
    {
        this.recomputeEquations = recomputeEquations;
    }

    /// остановились ли все шарики?
    private bool AllBallsStopped()
    {
        int ballIndex = 0;
        while (ballIndex<this.balls.Length)
        {
            if (!this.balls[ballIndex].isStopped) return true;
            ballIndex++;
        }
        return false;
    }
 
    /// играем множеством уравнений движений всех шариков
    public Play(Ball.MovingEquationDelegate[] equations)
    {
        /// устанавливаем уравнения движения
        /// играя нормально, задаём уравнение одного шарика, остальные ставим нулевыми;
        /// останавливать нулевые нет нужды - они сделают это сами (см. class Ball) после первого
        /// обновления
        for(int ballIndex=1; ballIndex < this.balls.Length; ballIndex++)
            this.balls[ballIndex].MovingEquation = equation[ballIndex];

        /// до тех пор, пока все не остановятся
        while(!this.AllBallsStopped())
        {
            for(int ballIndex=1; ballIndex < this.balls.Length; ballIndex++)
            {
                /// прокидываем очередной шарик
                this.balls[ballIndex].MoveStep();

                /// TODO : проверить, не закатился ли в лунку

                /// проверям не ударился ли он с каким-то другим
                for (int otherBallIndex = 0; otherBallIndex < ballIndex; otherBallIndex++)
                    if (this.balls[ballIndex].Meets(this.balls[otherBallIndex])
                       this.recomputeEquations(this.balls[ballIndex].MovingEquation,
                           this.balls[otherBallIndex].MovingEquation); 
                for (int otherBallIndex = ballIndex+1; otherBallIndex < this.balls.Length; otherBallIndex++)
                       this.recomputeEquations(this.balls[ballIndex].MovingEquation,
                           this.balls[otherBallIndex].MovingEquation);
            }
        }
    }
}


В лучшем случае, останется слегка доработать основу, определить физику движения и соударения, включить графику.

Это сообщение отредактировал(а) marcusmae - 15.2.2007, 00:11


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
-Mikle-
Дата 14.2.2007, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 17
Всего: 59



Цитата(marcusmae @  14.2.2007,  23:48 Найти цитируемый пост)
Гулять - так гулять  . Предложение по иллюстрации потока мыслей -Mikle-


ты прям как CSharpGenerator smile
сериализовал Stream моих мыслей в код на С#  smile 



--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
marcusmae
Дата 14.2.2007, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



SharpCoding. Live!

Цитата

сериализовал Stream моих мыслей в код на С#


smile может, сойдёт в качестве основы.


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0653 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.