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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перерисовка формы 
:(
    Опции темы
Enteropoly
Дата 17.6.2009, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Привет всем. 

У меня такое дело. Я пишу что-то типа стратегической игры на C#, использую только GDI+. Итак, тайлы (клеточки на игровом поле) у меня имеют форму шестиугольника, с отрисовкой всей этой сетки всё нормально. Проблемы начинаются при перерисовке. 

По задумке, у меня "подсвечивается" только тот тайл, над которым находится курсор мыши. Для этого бы создан массив эти клеточек, написаны методы, с технической стороны проблем, в общем, нету. Всё работает как надо. НО! Перерисовка весит на MouseMove, поэтому получается, что с каждым движением у меня перерисовывается всё поле размером в, скажем, 1000х1000 клеток, посему, как результат, под 100% грузится процессор, что, как понятно, недопустимо.

Так вот, мне нужно перерисовывать только видимую часть поля, ту, что видно на форме, а ту, что за кадром, оставить как есть до тех пор, пока она не станет видимой. Копал Invalidate, ничего путного не нашёл. Кто что может посоветовать?


ЗЫ. Метод поиска нужной клетки для подсвечивания, по координатам, работает максимально быстро (по бинарному дереву), поиск по полю 32000х32000 проходит за 6-7 итераций. Грешу на перерисовку.



-----------
Едит:
Повесил перерисовку на таймер, но всё равно тормозит жутко. Слишком много перерисовывается всего.

Это сообщение отредактировал(а) Enteropoly - 17.6.2009, 18:31
PM MAIL   Вверх
Heinzz
Дата 17.6.2009, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 12.12.2008
Где: .net

Репутация: 3
Всего: 9



Если каждый шестиугольничек является объектом, можно добавить ему метод
 "перерисоваться" если содержит курсор мыши
координаты мыши на всем поле вычислить проблем быть не должно


--------------------
user posted image
PM MAIL   Вверх
Grok
Дата 17.6.2009, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



а почему Invalidate() не подходит? 
Передавать туда прямоугольник который нужно перерисовать и  должно работать нормально ....
PM MAIL ICQ   Вверх
Enteropoly
Дата 17.6.2009, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

"перерисоваться" если содержит курсор мыши

Тут суть в том, что перерисовывать всё равно нужно все клетки, а ту, над которой курсор, просто по-другому =)


PM MAIL   Вверх
Enteropoly
Дата 17.6.2009, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Воть.


Код

protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            field.DrawField(e.Graphics, firsttimeredraw);
            base.OnPaint(e);
            firsttimeredraw = false;
        }

-------------------------------------------------------

public void DrawField(Graphics g, bool firsttime)
        {
            if (firsttime)
            {
                foreach (GTile tile in tiles)
                {
                    tile.DrawTile(g);
                }
            }
            else
            {
                RedrawLastRestateTiles(g);
            }

-------------------------------------------------------

public override void DrawTile(Graphics g) //отрисовка клетки (зависит от её состояния)
        {
            switch (this.sstate)
            {
                case Globals.SelectState.Normal:
                    g.DrawPath(Pens.Black, hexagonoutline);
                    if (Globals.ConsoleVariables.TileShowHashnum)
                    {
                        g.DrawString(this.hashnum.ToString(), Globals.StringFontFormat, Brushes.Red, this.hexcenterpoint.X- 
Globals.TileIntRadius / 2, this.hexcenterpoint.Y - Globals.TileExtRadius / 4); 
                    }
                    break;
            
                  ........................



Вот как-то так. Ладно, я тут пыхнул, и понял, что суть не в Invalidate. Просто надо разработать какой-то критерий, по которому определялось бы, надо перерисовывать клетку, или нет. В общем, будем искать.  smile 

Это сообщение отредактировал(а) Enteropoly - 17.6.2009, 20:19
PM MAIL   Вверх
amarenkov
Дата 18.6.2009, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 183
Регистрация: 21.2.2008
Где: Воронеж

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



Enteropoly, есть несколько вопросов и несколько советов smile.

Вопросы:
1. Я так понял, у тебя не все поле сразу видно, а 100-200 клеток? А каким образом это у тебя реализуется? Есть какие-то координатные преобразования? Или ты Image по форме двигаешь smile?
2. Проекция у тебя изометрическая или чисто 2D? Другими словами, у тебя есть части, вылезающие за клетку?

Советы:
1. Делай сразу на XNA, Tao или чистом DirectX, OpenGL - много сил сэкономишь smile.
2. Перерисовывать надо не на MouseMove, а при изменении состояния, т.е. когда меняется подсвечиваемя клетка. Надо помнить на какой были и при движении мыши проверять, изменилась ли она. Если да - перерисовать.
3. Рисовать сначала стоит на Bitmap, который находится в памяти. Потом весь Bitmap рисовать на Image, а не сразу на Graphics'e Image-а.
PM MAIL ICQ   Вверх
Enteropoly
Дата 20.6.2009, 02:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(amarenkov @ 18.6.2009,  13:46)
Enteropoly, есть несколько вопросов и несколько советов smile.

Вопросы:
1. Я так понял, у тебя не все поле сразу видно, а 100-200 клеток? А каким образом это у тебя реализуется? Есть какие-то координатные преобразования? Или ты Image по форме двигаешь smile?
2. Проекция у тебя изометрическая или чисто 2D? Другими словами, у тебя есть части, вылезающие за клетку?

Советы:
1. Делай сразу на XNA, Tao или чистом DirectX, OpenGL - много сил сэкономишь smile.
2. Перерисовывать надо не на MouseMove, а при изменении состояния, т.е. когда меняется подсвечиваемя клетка. Надо помнить на какой были и при движении мыши проверять, изменилась ли она. Если да - перерисовать.
3. Рисовать сначала стоит на Bitmap, который находится в памяти. Потом весь Bitmap рисовать на Image, а не сразу на Graphics'e Image-а.

1. 1 клетка = 1 экземпляр класса Tile. В классе реализован метод отрисовки. Всё прям напрямую через Graphics.Draw......
2. Чисто 2D.

1. С XNA знаком, но в целях как бы... ммм... повышения уровня квалификации именно в традиционном C#, хочется написать на GDI+  smile 
2. Щас уже перерисовывается по таймеру. Я как бы отвязал перерисовку от каких-то действий. Картинка меняется назависимо от происходящего, как лента в проекторе крутится постоянно, вне зависимости от того, что на ней нарисовано. А вот что на ней будет нарисовано (какие клетки надо перерисовать и как) - это у меня уже выполняет другая функция, которая как раз привязана к разным кликам, мувам и прочим событиям. Работает на ура.
3. А вот тут надо подумать =) Я ещё функцию скролла карты не реализовал и до сих пор предвкушаю долгие часы неиллюзорного секса с TranslateTransform и прочими радостями  smile 


PM MAIL   Вверх
gambit
Дата 29.6.2009, 00:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***
Награды: 1



Профиль
Группа: Комодератор
Сообщений: 1359
Регистрация: 25.6.2006
Где: я?

Репутация: 3
Всего: 40



Может конечно не поможет, но что если использовать двойную буферизацию??? Он тогда вроде как тогда использует особый метод отрисовки, что то типа отрисовывает изменившейся объект, а все остальное нет. Так решается проблема с мерцанием, но может и с нагрузкой ЦПУ, что ниб решится?
PM MAIL ICQ Skype   Вверх
Enteropoly
Дата 29.6.2009, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Двойная буферизация ессно включена =)
PM MAIL   Вверх
gambit
Дата 29.6.2009, 23:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***
Награды: 1



Профиль
Группа: Комодератор
Сообщений: 1359
Регистрация: 25.6.2006
Где: я?

Репутация: 3
Всего: 40



Создай класс шестиугольника, загони все объекты в массив, отрисуй их все, в mouse_move повесь процедуру определения, к какому объекту принадлежат данные координаты, если координаты наехали на другой объект, то только тогда перерисовывай форму.
PM MAIL ICQ Skype   Вверх
gambit
Дата 30.6.2009, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***
Награды: 1



Профиль
Группа: Комодератор
Сообщений: 1359
Регистрация: 25.6.2006
Где: я?

Репутация: 3
Всего: 40



Криво, но общий смысл понятен.

Присоединённый файл ( Кол-во скачиваний: 18 )
Присоединённый файл  WindowsFormsApplication1.rar 41,22 Kb
PM MAIL ICQ Skype   Вверх
gambit
Дата 30.6.2009, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***
Награды: 1



Профиль
Группа: Комодератор
Сообщений: 1359
Регистрация: 25.6.2006
Где: я?

Репутация: 3
Всего: 40



До меня уже после дошло, в mouse move в начале можно вставить проверку с текущего ли объекта не ушла ли мышь, тогда он еще и цикл поиска гнать не будет, еще больше разгрузишь проц. А если ушла, то уже цикл поиска.

Это сообщение отредактировал(а) gambit - 30.6.2009, 10:15
PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

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


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

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


 




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


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

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