2016-07-16 18 views
0

В настоящее время я создаю игру 2d-плитки, и мне интересно, нужно ли перемещать плитки или персонаж?Мне нужно переместить плитки или игрока в мир 2d плитки?

Я задаю этот вопрос, потому что я уже создал «карту плитки 2d», но он работает слишком медленно, и я не могу его исправить. Я попробовал все сейчас, и результат в том, что я получаю 30 кадров в секунду.

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

Если кто-то может мне помочь, я был бы очень признателен!

Это, как я сделать карту:

 public void makeBoard() 
    { 
     for (int i = 0; i < tileArray.GetLength(0); i++) 
     { 
      for (int j = 0; j < tileArray.GetLength(1); j++) 
      { 
       tileArray[i, j] = new Tile() { xPos = j * 50, yPos = i * 50 }; 
      } 
     } 
    } 

Здесь я перерисовки каждый 1мс или выше, плитки и спрайты:

 private void Wereld_Paint_1(object sender, PaintEventArgs e) 
    { 
     //label1.Text = k++.ToString(); 
     using (Graphics grap = Graphics.FromImage(bmp)) 
     { 
      for (int i = 0; i < tileArray.GetLength(0); i++) 
      { 
       for (int j = 0; j < tileArray.GetLength(1); j++) 
       { 
        grap.DrawImage(tileArray[i, j].tileImage, j * 50, i * 50, 50, 50); 
       } 
      } 
      grap.DrawImage(player.movingObjectImage, player.xPos, player.yPos, 50, 50); 
      grap.DrawImage(enemyGoblin.movingObjectImage, enemyGoblin.xPos, enemyGoblin.yPos, 50, 50); 

      groundPictureBox.Image = bmp; 
      // grap.Dispose(); 

     } 
    } 

Это таймер с конкретным Интервал:

 private void UpdateTimer_Tick(object sender, EventArgs e) 
    { 
     if(player.Update()==true) // true keydown event is fired 
     { 
      this.Invalidate(); 
     } 
     label1.Text = lastFrameRate.ToString(); // for fps rate show 
     CalculateFrameRate(); // for fps rate show 
    } 
+0

рисовать только плитки, которые должны появляться на экране, и использовать камеру, чтобы помочь вам сделать вещи: http://stackoverflow.com/questions/9997006/slick2d-and-jbox2d-how- to-draw? answertab = votes # tab-top – user3814613

+0

@ user3814613 Прежде всего, спасибо за ваш комментарий! Я не понимаю, что вы говорите. Мне нужно перерисовать все плитки, потому что я хочу, чтобы плитки перемещались, поэтому он будет выглядеть так, как игрок идет по «миру». Кроме того, я никогда не использовал функцию камеры, и я бы не знал, с чего начать. –

+0

Вы прочитали сообщение, которое было связано с этим комментарием? Если бы у вас было, вам не нужно было бы говорить *, я бы не знал, с чего начать. *. Люди предоставляют ссылки на другие вопросы, чтобы помочь; это не очень приятно игнорировать их после того, как они сделали работу, чтобы найти ее для вас. –

ответ

1

Как указано в комментариях, ваша концепция неверна. Так вот только простое резюме того, как сделать эту задачу:

  1. Плитка карта является статическим

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

    Для того, чтобы достичь цели игрока или просмотреть его, вам также нужно переместить камеру.

  2. рендеринг

    Перекрашивания каждого 1мса является безумного и, скорее всего, невозможно на компьютерах в нашем время, если вы получили среднюю сложность сцены. Человеческое видение не может его обнаружить, так что нет смысла перерисовывать больше, чем 25-40 fps. Единственная причина для более высоких потребностей в fps - синхронизация с обновлением монитора, чтобы избежать артефактов строк сканирования (Да даже ЖК-дисплей использует линии сканирования, освежающие). Чтобы иметь больше кадров в секунду, частота обновления вашего монитора бессмысленна (многие игроки fps будут противостоять, но наше восприятие - это то, что независимо от того, что они говорят ...).

    В любом случае, если ваш рендеринг занимает больше 1 мс (что более вероятно), то ваш таймер завинчивается, потому что он должен срабатывать несколько раз, прежде чем первый обработчик даже остановится. Это обычно вызывает массовые замедления из-за проблем с синхронизацией, поэтому полученные fps обычно даже меньше, чем может обеспечить механизм рендеринга. Итак, как исправить это?

    1. установить timer интервал 20ms или более
    2. добавить bool _redraw=false И использовать его перерисовывать только тогда, когда вам нужно перекрасить экран.Таким образом, при любом действии, таком как движение игрока, движение или поворот камеры, изменение анимации устанавливают его на true
    3. обработчик события таймера вызывает ваш перерисовку только в том случае, если _redraw==true и затем установите значение false.

    Это значительно повысит производительность. даже если ваша перекраска займет больше времени таймера, это будет намного быстрее, чем ваш текущий подход.

    Во избежание мерцания использования Задняя буферизация.

  3. камеры и отсечение

    Ваша карта затем экран, скорее всего, намного больше, так что нет никакого смысла перекрасить все плитки. Вы можете смотреть на камеру как средство для выбора правой части вашей карты. Если ваша игра не использует вращения, вам нужно всего лишь position и может быть zoom/scale. Если вам нужны вращения, то гомогенные матрицы 2D 3x3 - это путь.

    Пусть Предположим, вы получили только положение (без увеличения или вращающихся), то вы можете использовать эти преобразования:

    screen_x=world_x-camera_x 
    screen_y=world_y-camera_y 
    
    world_x=screen_x+camera_x 
    world_y=screen_y+camera_y 
    

    так camera ваша камера зрения позиция, world это вы позиционируете плитки в сетке карты и screen является положение на экране. Если вы получили вашей плитки на карте, то просто умножьте их на размер плитки в пикселях, чтобы получить координаты world.

    Чтобы выбрать только видимые фрагменты, вам необходимо получить угловые положения вашего экрана, преобразовать их в мировые координаты, затем в индексы на карте и, наконец, отобразить только плитки внутри прямоугольника, которые эти точки образуют на вашей карте + некоторый запас ошибки (например, выведите 1 плиту с увеличенным прямоугольником во всех направлениях). Таким образом, рендеринг будет независимым от размера вашей карты. Этот процесс называется отсечением.

я настоятельно рекомендую посмотреть на этих родственных QA с:

Демонстрационные в связанных КвА использовать только GDI и прямой доступ пикселя к растровым изображениям в win32 виде приложении, так что вы можете сравнить производительность с кодом (они должны быть похожи) и настроить свой код, пока он не ведет себя как следует.

+0

Прежде всего, спасибо вам за вашу помощь:) Я полностью выполнил шаг 2, но теперь мне не нужно делать шаг 3. Я понял, как это сделать. Но прежде всего, я хотел избавиться от 30 fps p/s. У вас есть советы по достижению около 50/60 кадров в секунду при рисовании полной карты каждые 20 мс? Я рисую карту так же сильно, как экран, поэтому никакие плитки не выходят за ее пределы. Позже я буду реализовывать остальные ... Спасибо за ваше время! –

+0

@MYil в первом связанном QA также является моим исходным кодом для демонстрации, которая достаточно быстро. Не видя, как вы делаете рендеринг, сложно сказать, где узкое место ... как вы справляетесь с спрайтами? или у вас есть только плитки (нет прозрачности или масок)? во всяком случае неправильно кодированный gfx-рендеринг может быть болезненно медленным ... – Spektre

+0

Спасибо за ваш ответ! Оке, старайся как можно яснее:) У меня есть 2-й массив, заполненный плитками. Эти плитки - это классы, и в этих классах есть образ. Это изображение составляет около 1 килобайта. Я перерисовываю с недействительным каждые 1 мс (или 20 мс, дает ту же производительность) изображения в растровое изображение. и нарисуйте это на большой картинке. Размер растрового изображения такой же размер, как размер изображения. Перерисовка выполняется каждый раз, когда я нажимаю событие keydown. Затем таймер откроет метод перемещения в классе спрайтов и заставит его двигаться. Позвольте мне поместить мой код, повесить на него :) –

1

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

2D-двигатели с прокруткой плитки должны нарисовать плитки на большом спрайте, чем на экране, а затем нарисуйте этот спрайт, вокруг которого выполняется быстрая операция (вам нужно указать язык, который вы используете, чтобы я мог дать некоторый намек на как на самом деле сделать это быстро - основном в видеопамяти ускоряются Blit, но каждый язык имеет свой путь, чтобы это произошло)

enter image description here

когда граница этого супер-спрайт ближе к границе экрана, чем порог (обычно половина плитки), большой спрайт перерисовывается вокруг текущей позиции, но нет необходимости рисовать все плитки на этом! начните копировать суперспринт на этом возвращенном спрайте, и вам нужно всего лишь нарисовать плитки, отсутствующие на предыдущем суперспеле, из-за смещения.

enter image description here

+1

забыл упомянуть об этом в своем ответе сначала. поэтому +1. Кстати, это называется повторной буферизацией или двойной буферизацией вместо супер спрайта ... Мое понимание заключается в том, что супер спрайт используется для объединения слоев спрайтов для улучшения производительности анимаций на основе каждого элемента, а не как теневого экрана ... но идея правильный – Spektre

+0

обратная/двойная буферизация имеет точный смысл и имеет обратный буфер, который вытягивается каждый кадр и заменяется на передний буфер. Здесь вы создаете предварительно загруженный лист, который вы можете разбить на задний или передний буфер после этого, - поэтому он ортогонален - но идея схожа, есть графическая карта, нажимающая на большинство пикселей вместо процессора. –

+0

Хм, я думаю, что вы правы, экран прокрутки супер прокрутки не соответствует счету точно ... – Spektre