Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Игра арканоид  (Прочитано 22773 раз)
0 Пользователей и 1 Гость смотрят эту тему.
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« : 26-06-2012 19:23 » 

У меня две проблемы:
1) не получается эффективно, без тормозов отрисовывать объекты;
2) время от времени выскакивает конфликт обращений к одному и тому же объекту.

По первому вопросу :
Отрисовывается сцена следующим образом. На форме есть таймер, по нему вызывается событие формы InValidate(). Далее (в OnPaint(PaintEventArgs e)) рисуется вся сцена, используя е.Graphics.DrawImage (bmp).
В свою очередь, есть 4 бмпшки, котрые соответсвуют Фону, Стене кирпичей, Шарику и Доске. Они хранятся статично в классе Painter, т.е. один раз я их создаю (оператор new) остальное время я их лишь обновляю.
Обновление бмпшек происходит по событиям (изменение координат шарика / доски, удар об стену). Я стираю и заново на них отрисовываю объекты. Каждой бмпшке соответсвует один объект.
Код: (C#)
public void paintTimer_Tick(object s, EventArgs e)
        {
            Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.DrawImage(Painter.back_bmp, 0,0,
                ClientRectangle.Width, ClientRectangle.Height);
            e.Graphics.DrawImage(Painter.wall_bmp, 0, 0,
                ClientRectangle.Width, ClientRectangle.Height);
            e.Graphics.DrawImage(Painter.ball_bmp, 0, 0,
                ClientRectangle.Width, ClientRectangle.Height);
            e.Graphics.DrawImage(Painter.board_bmp, 0, 0,
                ClientRectangle.Width, ClientRectangle.Height);
        }
Код: (C#)
public class Painter
    {
        static public Bitmap wall_bmp;
        static public Bitmap back_bmp;
        static public Bitmap ball_bmp;
        static public Bitmap board_bmp;

        static public void Ball_LocationChanged(Field sender)
        {
            RefreshBallBmp(sender.ClientRectangle, sender.Ball);
        }

        static public void Board_LocationChanged(Field sender)
        {
            RefreshBoardBmp(sender.ClientRectangle, sender.Board);
        }

        static public void Wall_BallHittedWall(Field sender)
        {

            RefreshWallBmp(sender.ClientRectangle, sender.Wall);
        }

        static public void initAll(Field field)
        {
            ball_bmp = new Bitmap(field.ClientRectangle.Width, field.ClientRectangle.Height);
            board_bmp = new Bitmap(field.ClientRectangle.Width, field.ClientRectangle.Height);
            wall_bmp = new Bitmap(field.ClientRectangle.Width, field.ClientRectangle.Height);

            StateBackBmp(field.ClientRectangle, Field.BackImage);
            RefreshBallBmp(field.ClientRectangle, field.Ball);
            RefreshWallBmp(field.ClientRectangle, field.Wall);
            RefreshBoardBmp(field.ClientRectangle, field.Board);
        }

        static public void RefreshWallBmp(Rectangle clientRect, Wall wall)
        {
            Graphics g = Graphics.FromImage(wall_bmp);
            g.Clear(Color.Transparent);

            drawWall(g, wall.Bricks);
        }

        static public void RefreshBallBmp(Rectangle clientRect, Ball ball)
        {
            Graphics g = Graphics.FromImage(ball_bmp);
            g.Clear(Color.Transparent);

            drawBall(g, ball);
        }

        static public void RefreshBoardBmp(Rectangle clientRect, Board board)
        {
            Graphics g = Graphics.FromImage(board_bmp);
            g.Clear(Color.Transparent);

            drawBoard(g, board);
        }

        static public void StateBackBmp(Rectangle clientRect, Image backImage)
        {
            back_bmp = new Bitmap(backImage, clientRect.Size);
        }
       
        static public void drawWall(Graphics g, List<Brick> wall)
        {
            foreach (Brick b in wall)
                if (b.IsAlive)
                {
                    Size size_ = new Size(Brick.Width, Brick.Height);
                    Rectangle rect_ = new Rectangle(b.Location,
                        size_);
                    g.FillRectangle(new SolidBrush(b.Color), rect_);
                }
        }
       
        static public void drawBall(Graphics g,
            Ball ball)
        {
            SolidBrush b = new SolidBrush(ball.Color);
            g.FillEllipse(b, ball.Location.X, ball.Location.Y,
                ball.Radius*2, ball.Radius*2);
        }

        static public void drawBoard(Graphics g,
            Board board, bool wipe = false)
        {
            SolidBrush b = new SolidBrush(!wipe? board.Color:
                board.Parent.Parent.BackColor);
            Rectangle r = new Rectangle (board.Location, board.Size);
            g.FillRectangle(b, r);
        }


        static public void wipeOff_Brick(Graphics g,
            Brick brick)
        {
            // стирает кирпичик с экрана
            SolidBrush b = new SolidBrush(Brick.Parent.Parent.Parent.BackColor);
            Size s = new Size(Brick.Width, Brick.Height);
            Rectangle rect = new Rectangle(brick.Location, s);
            g.FillRectangle(b, rect);
        }
    }
}
Сейчас писал и понял, что события передвижения доски (т.к. они идут по движению мышки ) происходят Очень часто. Может в этом проблема?
Есть еще идея хранить бмпшки по размеру объектов. Но что-то мне не кажется, что в размерах проблема.

И второй вопрос : Как ? Потоки?

Проект vs 2010 тут http://rghost.net/38895290
« Последнее редактирование: 27-06-2012 06:34 от KBAC » Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 26-06-2012 19:55 » 

Во-первых, было бы вежливо указать версию VS, чтобы не пришлось гадать, что это 2010. Во-вторых, было бы ещё более вежливо, если бы прикреплённый проект хотя бы как-то работал, а не падал с исключительной ситуацией Null reference.

Добавлено через 13 минут и 39 секунд:
Посмотрел код. Кода много - толку мало. Поскольку не видел работающей программы, замысел всех манипуляций с картинками не очень понятен. Событийная модель тоже не очень понятна. Понятно лишь то, что при paint формы рисуются bitmap'ы - это правильно. Понятно, что осуществлена попытка обеспечить 60 fps.

Первый совет: останавливай таймер при входе в обработчик и включай при выходе. С помощью этого нехитрого средства ты избавишься от накапливающейся очередь "холостых" событий, делающих бессмысленную отрисовку, когда время на самом деле уже было упущено из-за какой-нибудь длительной обработки. С помощью этого нехитрого приёма не нужны будут потоки. Хотя fps станет плавающим, зависящим от способностей процессора справиться с логикой и перерисовками.
« Последнее редактирование: 26-06-2012 20:09 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 27-06-2012 06:38 » 

Dimka, Дело в том, что у меня 2 таймера.
1 - двигает шарик и вызываются соответсвующие события, в том числе и изменение бмпшки;
2 - отрисовывает форму, используя те же самые бмпшки.

Проект рабочий залил на ргхост. См. предыдущий пост.
За нерабочий проект извиняюсь.
« Последнее редактирование: 27-06-2012 07:51 от KBAC » Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 27-06-2012 08:11 » 

Ты, похоже, таймеры не различаешь.

Таймер в System.Window.Forms - это таймер, который сообщает приложению своё событие при помощи системного сообщения WM_TIMER. Сообщение это становится в очередь всех прочих сообщений приложения (наряду с тем же WM_PAINT, движениями мыши и т.д.). Приложение обрабатывает системные сообщения в порядке поступления. Соответственно, если обработка какого-то сообщения затянулась, в очереди накапливаются уже поступившие, но ещё не обработанные сообщения. Приложение работает строго в 1 поток.

Таймер в System.Timers или System.Threading - это таймер, который сообщает приложению своё событие фактически при помощи системного сигнала. Это значит, что обработчик такого таймера выполняется в отдельном потоке - не в потоке приложения, т.е. асинхронно. Это же значит, что доступ к разделяемым между потоками объектам (например, bitmap'ы) нужно синхронизировать.

Я бы советовал для рисования использовать только таймеры 1-го типа. Таймеры 2-го типа использовать только для расчётов координат. Тогда движения объектов не будут зависеть от fps обновления изображения на экране. У тебя в общем-то так и делается. Но, к примеру, событие game over (равно, как и любые другие события) генерировать в обработчике таймера 2-го типа неправильно. Лучше установить флаг события (bool-переменную), а саму реакцию на событие делать в основном потоке приложения. Иначе по цепочке обработчиков концов не соберёшь - какие объекты в каком потоке срабатывают.

По поводу рисования. Шарик, кирпичи и "подставка", равно как и фон - это либо статические bitmap'ы, либо простые геометрические фигуры. Нет смысла рисовать одно в другом, изменяя bitmap'ы, чтобы потом вывести это на экран. Наоборот, нужно просто выводить на экран все bitmap'ы в порядке их взаимного наложения и расположения на каждый fefresh экрана. Может быть слегка ускорит дело кэширование изображения стены, т.к. она меняется реже. Но, я думаю, это не сделает погоды. Лучше пусть приложение работает в "стационарном" режиме. Прохождение шарика через кирпичи, их массированное удаление приведут к интенсивному обновлению кэша стены, что может создать торможение в самый ответственный момент. "Лёгкость" отрисовки в периоды простого полёта шарика тебе никак не помогает - фоновых расчётов у тебя нет. Без кэша загрузка процессора отрисовкой стабильна, плавно снижается по мере убывания количества кирпичей - так проще добиться устойчивого качества отрисовки.

P.S. И всё-таки, отчего у тебя в проекте уже второй раз есть файлы, отсутствующие на диске, и само приложение не работает при запуске из VS? Опять сбой, правда в другом месте.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 27-06-2012 08:34 » 

Dimka, спасибо за проявленный энтузиазм, буду разбираться.
Сори еще раз проект  Улыбаюсь Теперь не понимаю почему что-то не так у тебя.
Выкладываю проект, который у меня на двух машинах как есть запустился. http://rghost.net/38896792.

Прочитал, вник и вот что думаю: надо как-то защитить бмпшку от чтения, если она используется в другом потоке (пока шарик стирается и рисуется заново OnPaint формы успевает попользоваться объектом ..._bmp, и, бывает, не выводит на экран, а иногда выскакивает ошибка обращения к используемому объекту). Только как это сделать я еще до конца не придумал. Так как у Bitmap нет метода InvokeRequired, то можно отловить исключение в OnPaint. А в catch(...) уже пользоваться сохраненной версией (ввести такую предварительно) ..._bmp. Мне кажется проблемой перезапись сохраненной версии, ведь такая операция тоже требует доступа к нашей используемой бмпшке.

Цитата
Наоборот, нужно просто выводить на экран все bitmap'ы в порядке их взаимного наложения и расположения на каждый refresh экрана.
Так и есть. По крайней мере задумано.

Цитата
Лучше пусть приложение работает в "стационарном" режиме.
Что ты имеешь ввиду под "стационарным " режимом ?
« Последнее редактирование: 27-06-2012 10:27 от KBAC » Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 27-06-2012 10:29 » 

"Второй" проект у меня падает здесь:

        static public void RefreshBallBmp(Rectangle clientRect, Ball ball)
        {
>>>     Graphics g = Graphics.FromImage(ball_bmp);
            g.Clear(Color.Transparent);

            drawBall(g, ball);
        }

Value cannot be null.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 27-06-2012 11:25 » 

Джон, если ты пошагово это выполнял, тогда все понятно: таймер движения (запускается в конструкторе Ball) при пошаговом проходе работает столько же быстро, как если бы мы не запускали отладку, и перый тик таймера вызывает сначала Ball.move, затем RefreshBallBmp еще до того, как произошла инициализация объектов Painter'а.
Иначе как в отладке, не могу придумать почему выскочила эта ошибка.
« Последнее редактирование: 27-06-2012 11:27 от KBAC » Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #7 : 27-06-2012 12:33 » 

Нет не в отладке, все точки останова вырубил. Падает, если запускаю из студии.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 27-06-2012 13:15 » 

Джон, в точности так же. Только я полагал, что автор сам поправит этот мелкий косяк...
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #9 : 27-06-2012 13:36 » 

Наверное "гранаты у него не той системы" (с) Ага

зы Хотя я и допускаю, что проблема может заключаться в тайминге. Просто ща ковыряться времени нет, а основная проблема темы, как я понял, заключается в другом.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 27-06-2012 14:33 » 

Не получилось воспроизвести ошибку. Но подправил запуск таймера. Теперь по щелчку мышки запускается игровой процесс.
Залил сюда http://rghost.net/38903613 . Старую заливку удалил случайно, так что не пытайтесь в истерике скачать то, чего нет Улыбаюсь

Джон, там багов еще достаточно. С ними особых проблем не будет. А вот с отрисовкой не знаю что делать.
Я все таки думаю это из-за довольно уж частого вызова события перемещения мышки. С шариком еще  кое-как летает, а вот если мышкй бегать постоянно, то можно и гамовер пропустить.
« Последнее редактирование: 27-06-2012 14:40 от KBAC » Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 27-06-2012 16:19 » 

KBAC, не смотрел проект и не видел, как там обрабатывается движение мыши, но у меня есть некоторые соображения, как это можно сделать:
Можно сделать платформу немного инертной: она двигается в определённом направлении, набирая скорость и замедляясь в зависимости от того, достигла ли уже той точки, где в данный момент находится мышь, или нет.
Тогда, если мы резко шевельнули мышью в противоположном направлении, то платформа просто ещё немного прокатится в прежнем направлении, а потом, резко ускорившись, пойдёт в противоположном. Вот, как-то так.

Получается, платформа болтается несколько свободнее, что даёт нам возможность не перерисовывать по каждому шевелению мыши, а лишь изменять переменную, отвечающую за скорость движения. Это намного дешевле, чем шевелить каждый раз.
« Последнее редактирование: 27-06-2012 16:22 от Вад » Записан
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 27-06-2012 16:47 » 

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

Подумал. Сделал следующее:
Код: (C#)
public void move(Point new_loc)
        {
            int old_coord = location.X;
            location.X = new_loc.X;
            // событие движения доски должно
            // вызвать перерисвоку бмпэшки мяча
            if (Math.Abs(old_coord - location.X) > 100)
                LocationChanged(parent);
        }
т.е. метод перерисовки битмапы вызывается крайне редко, а отрисовка как была так и осталась тормозить. Сделал вывод что дело не в доске.
Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 27-06-2012 17:42 » new

Похоже, мои рассуждения о таймерах вообще пролетели мимо. А всё из-за слабости архитектуры. Ещё раз и конкретнее.

В программе есть 3 вещи: обработка сигналов и событий, математическая модель игры в виде координат разных объектов и вывод на экран.

Событийная модель должна иметь 2 независимых контура обработки.

В первом контуре сигналы одного таймера и события мыши обрабатываются таким образом, чтобы вносить изменения в модель - в результате пересчитываются координаты. Поскольку тут лишь чисто арифметические расчёты над несколькими десятками чисел, это происходит очень быстро и никак не тормозит.

Во второму контуре сигналы второго таймера приводят к обновлению изображения на экране. В результате считывается текущее значение модели, и по полученным координатам на экран выводятся нужные bitmap'ы.

В результате достигается желаемый эффект. Пользователь может как угодно двигать мышью, и сколь угодно часто менять положение платформы; по таймеру может как угодно часто изменяться положение шарика, может удаляться любое количество кирпичей. И ничто не приведёт к перерисовке. Но зато перерисовка по второму контуру будет выполняться 60, 50, ... 25 раз в секунду (по желанию) вне зависимости от того, двигал пользователь мышь, или не двигал, сильно двигал или слабо, шарик летел прямо или успел выбить десяток кирпичей, и даже если вообще ничего не происходило, а шарик прилип к платформе - всё равно будет перерисовка. Чтобы убрать лишние перерисовки, достаточно завести логический флаг updated (или систему таких флагов): как только в первом контуре что-то меняется, флаг устанавливается. Во втором контуре первым делом проверяется флаг: если он установлен, значит нужно перерисовать и сбросить флаг; если он не установлен, то ничего не делать.

В первом контуре система живёт своей жизнью. Второй контур обеспечивает как бы "фотографирование" текущего положения дел с нужной частотой, что и создаёт эффект анимации.

Собственно, так реализуется любой графический движок (ну естественно, с наворотами из конвейеров обработки и буферов).
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 27-06-2012 22:24 » 

Вад, я подумаю над этим, но получается какой-то подгон устройства игры под производительность.
Не совсем. Просто мы используем более гибкий механизм, позволяющий нам не учитывать лишние суетливые телодвижения пользователя и более адекватно оценивать движение, а не реагировать на сдвиг сначала на 100 px влево, а потом на 101px вправо, если мы при этом к следующему акту перерисовки всё равно останемся на месте. Просто исключаем ненужные действия, и всё. А дальше - если система позволит нам отрисовывать 1000 кадров в секунду (ну, пофантазируем на миг), и нам это зачем-нибудь будет надо - хорошо, нарисуем. Тогда вся дерготня пользователя уже будет попадать в результаты, потому что за 1/1000 секунды пользователь, определённо, успеет дёрнуться только куда-то в одно место. Если нужно, даже попиксельно сдвиг этот тогда анимируем - но не ранее того.

В общем, Димка всё правильно говорит про контуры управления. Одно дело - "датчик" положения, другое - реакция на этот датчик, и тут надо продумать физику воздействия и обратную связь, отталкиваясь от ограничений графики, чтобы реалистично выглядело: не тормозило, но и доска чтобы не телепортировалась внезапно. Если реагировать на каждое возмущение - играть будет невозможно, пользователь же не плавно мышью водит, а дёргается, плюс шум с сенсора, всё будет вечно дрожать.

Цитата
Подумал. Сделал следующее:
---
т.е. метод перерисовки битмапы вызывается крайне редко, а отрисовка как была так и осталась тормозить. Сделал вывод что дело не в доске.
Это не решает вышеупомянутой проблемы, когда дёрнулись право, потом дёрнулись влево - и всё это за время, пока отрисовывается один кадр. Дёрнемся на 500 вправо, потом на 500 влево - вот уже и 10 кадров вместо положенного 0.
« Последнее редактирование: 27-06-2012 22:29 от Вад » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #15 : 28-06-2012 07:37 » 

Джон, там багов еще достаточно.

Это понятно, я понял твою проблему, поэтому и не собирался искать, почему падает. Дело в следующем. Даже посмотрев код, архитектуру программы я сразу не увидел. А начинать надо именно с этого. Ведь казалось бы, чего проще? Зачем тебе кирпичи? Фон? Таймеры? Я бы сначала сделал работоспособное управление ракеткой, без всяких шариков и кирпичей. Просто и наглядно.

Если не работает, разбираемся почему. Если работает, переходим к след. шагу.

Просто летает шарик. Без всяких ракеток и пр. Летает по законам физики (ну или арканоидной физики, если угодно).

Если не работает, разбираемся почему. Если работает, переходим к след. шагу.

Добавляем ОДИН (!) единственный кирпич. Шарик должен на него реагировать.

Если не работает, разбираемся почему. Если работает, переходим к след. шагу.

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

В принципе всё. Размножить кирпичи, шарики и ракетки уже не составит труда. Поместить всё в отдельные треды, добавить таймеры и пр лабуду - аналогично, поскольку есть работающие и обкатанные единицы.

А разбираться с этим одно сплошное удовольствие. И самому себе и нам. Ага

« Последнее редактирование: 28-06-2012 08:53 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 28-06-2012 15:07 » 

Изменил проект кардинально - посмотрите ,плз http://rghost.net/38922335 .

Dimka, я сделал четыре контура.
1 - WM_TICK'и (или как их). Отлавливается движение мыши, и меняются координаты доски.
2 - Перерисовка формы (Timers.Timer)
3 - Проверка флага перерисовки стены, и (если что) изменение бмпшки стены.
4 - движение шарика.

4 и 1 в принципе можно соединить, но я подумал что для каждого таймера пусть будет отдельная задача, тогда ничто не будет сточять в очереди, к тому же операция move довольно продолжительная.

Резюме: На мой взягляд, все пожелания по поводу контуров учтены, и приложение действительно работает быстрее, но все равно тормозит. Обновление экрана каждые 16 мсек, так что дело не в фпс.

Я готов к следующей волне критики   :Улыбаюсь

Джон, уже поздно заново писать, завтра сдача. Физика хромает из-за того, что алгоритмы проверки писались для движения шарика на один пиксель. А сейчас стало понятно, что это слишком медленно.

По поводу скорости , может стоит ввести еще несколько независимых таймеров, которые будут один за другим изменять координаты шарика?
Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #17 : 28-06-2012 15:16 » 

рекомендую поискать и почитать

motion tween algorithm
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #18 : 28-06-2012 18:14 » 

Завтра - это да. Тут уже научная медицина бессильна. Жаль Единственное что могу пожелать, в след. раз всё-таки чуть пораньше беспокоиться.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 28-06-2012 19:10 » 

Основное торможение на DrawImage.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 28-06-2012 19:53 » 

Dimka, а как избавиться? И как ты это понял?
Джон, обязательно Улыбаюсь
Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 29-06-2012 07:02 » 

KBAC, закомментировал DrawImage фона, затем стены. Всякий раз - заметное ускорение, если форма развёрнута на весь экран. Если форма не развёрнута, то и торможения особого нет.

Ты просто не учитываешь, как работает DrawImage. Один тот факт, что ты задаёшь не только координаты левого верхнего угла картинки, но и её размер, приводит к тому, что DrawImage занимается масштабированием картинки. Конечно, это очень удобно для программиста, но это очень скверно для скорости работы.

Ускорить можно, если работать с буферным Bitmap'ом через прямой доступ к его двоичному представлению и пропускать все шаги матричных трансформаций изображения. Причём в буферный Bitmap писать блоками (например, строками), а не попиксельно. Тогда вывод результирующего bitmap'а будет почти такой же быстрый, как вывод одной только фоновой картинки без трансформаций.

Но это уже движение в сторону написания собственного графического движка. Тут уж лучше DirectX использовать. Хотя... для общего развития можно и свой конвейер написать.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 29-06-2012 17:08 » 

Спасибо всем! До новых встреч Улыбаюсь
Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines