Нужен совет о том, как работает битблит

Я создаю свою первую игру, когда-либо используя pygame, и я обнаружил, что для анимации наиболее популярным методом является использование битового блитирования.
Однако у меня есть несколько вопросов по этому поводу:

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

  2. Если да... Я рисую "сцену" зданий, используя прямоугольники (каждое здание имеет разные цвета (генерируются случайным образом), разную высоту (случайно), и у них также есть окна двух разных чередующихся цветов). Что было бы лучшим способом для моего класса Building запомнить каждый цвет, который он имел для здания и его окон, чтобы, когда я немного блистал, здание не приобретало разные цвета, чтобы сделать его более реалистичным?


person Community    schedule 12.10.2009    source источник
comment
Вы можете перерисовать весь экран или только измененную часть.   -  person ninMonkey    schedule 23.11.2012


Ответы (4)


У вас может быть простой класс Building:

class Building:
  def __init__(self, x, y, w, h, color):
    self.x = x
    self.y = y
    self.w = w
    self.h = h
    self.color = color


  def draw(self):
    // code for drawing the rect at self.x,self.y 
    // which is self.w wide and self.h high with self.color here

Что касается окон, вы можете указать каждое из них в списке, например [(x, y, w, h)] для каждого здания, или просто создать класс здания, который выглядит следующим образом:

class Building:
  def __init__(self, x, y, w, h, color, wx, wy):
    self.x = x
    self.y = y
    self.w = w
    self.h = h
    self.color = color
    self.wx = wx
    self.wy = wy


  def draw(self):
    // code for drawing the rect at self.x,self.y 
    // which is w wide and h high with self.color here

    // Draw wx windows horizontally and wy windows vertically
    for y in range(0, self.wy):
      for x in range(0, self.wx):
        // draw Window code here

Другой подход заключается в том, что вы «преобразовываете» свои здания в изображение, а затем просто отображаете его (это также может быть быстрее, если у вас много зданий).

И тогда ваш игровой цикл мог бы выглядеть примерно так

  buildingList = [Building(0, 0, 15, 50, RED), Building(0, 0, 40, 30, BLUE)]
  while gameIsRunning:
        // Clear screen code here

        // Show Building
        for b in buildingList:
          b.draw()

        // More stuff

Это в значительной степени самый простой подход к рисованию чего-либо, вы можете рисовать таким образом символы, клавиши или даже плитки, которые должны быть над вашим персонажем, например. водные плитки в таких платформерах, как Tuff. Деревья здесь также находятся в одном большом списке (хорошо, на самом деле я веду меньший список с деревьями, которые находятся на 1 1/2 окружающих экранах из соображений производительности. Там более 1500 «деревьев»).

РЕДАКТИРОВАТЬ: В случае разных цветов окна есть два возможных решения.

Использование разных цветов окон в каждом здании:

class Building:
  def __init__(self, x, y, w, h, color, wx, wy, windowColor):
    self.x = x
    self.y = y
    self.w = w
    self.h = h
    self.color = color
    self.wx = wx
    self.wy = wy
    self.windowColor = windowColor


  def draw(self):
    // code for drawing the rect at self.x,self.y 
    // which is self.w wide and self.h high with self.color here

    // Draw wx windows horizontally and wy windows vertically
    for y in range(0, self.wy):
      for x in range(0, self.wx):
        // draw Window code here using self.windowColor

Вариант 2, с разными цветами для каждого окна:

   class Building:
      def __init__(self, x, y, w, h, color, windows):
        self.x = x
        self.y = y
    self.w = w
    self.h = h
        self.color = color
        self.wx = wx
        self.wy = wy
        self.windows = windows


      def draw(self):
        // code for drawing the rect at self.x,self.y 
        // which is self.w wide and self.h high with self.color here

        // Draw all windows
        for w in windows:
          // draw Window at w[0] as x, w[1] as y with w[2] as color

// Create a building at 0,0 that is 20 wide and 80 high with GRAY color and two windows, one at 2,2 which is yellow and one at 4, 4 that's DARKBLUE.
b = Building(0, 0, 20, 80, GRAY, [(2, 2, YELLOW), (4, 4, DARKBLUE)])
person Ivo Wetzel    schedule 12.10.2009
comment
используя метод класса Building, мне любопытно узнать, как вы передаете эти аргументы функции рисования? откуда он получит аргументы x, y и color, если я не использую какой-то список, в котором есть эта информация? - person ; 12.10.2009
comment
Упс :) На самом деле я ошибся, сам экземпляр класса уже имеет все необходимые ему значения. - person Ivo Wetzel; 12.10.2009
comment
ааа теперь это имеет больше смысла! :) еще одна деталь: окна имеют разные цвета (выбирает случайный цвет из списка двух цветов). как он узнает, какой цвет использовать для функции рисования? Я предполагаю, что из вашего примера вы имели в виду рисовать, чтобы использовать self.color, но self.color — это цвет фактического здания. как передать текущий цвет окна? спасибо за помощь и очень подробный ответ. теперь все имеет больше смысла - person ; 12.10.2009
comment
Являются ли цвета разными для каждого окна в каждом здании или они просто разные, так что в здании A есть окна с цветом 1, а в здании B - окна с цветом 2. Если имеет место более поздний случай, вы можете просто добавить еще одну переменную в класс здания , что-то вроде self.windowColor, а затем закрасить прямоугольники окна этим цветом. В другом случае вашему списку окон для каждого здания требуется другое значение для каждого цвета окон, я отредактирую это в своем ответе. - person Ivo Wetzel; 12.10.2009
comment
он первый. окна могут быть желтыми или серыми, и они выбираются случайным образом. во всех зданиях есть окна этих двух цветов. - person ; 12.10.2009

Да, считайте экран холстом, на котором вы рисуете. Как только сцена закончена и показана зрителю, вы начинаете следующую сцену (также известную как «кадр»), рисуя поверх нее, заменяя все, что там было. Движение представлено повторным рисованием одного и того же предмета в несколько разных местах. Это очень похоже на традиционную анимацию в кино — покажите серию слегка различающихся картинок, чтобы создать иллюзию движения. Обычно вы делаете это несколько десятков раз в секунду.

Так работает не только бит-блит pygame/SDL — так работает почти вся компьютерная графика в реальном времени. Однако некоторые системы могут скрывать это от вас и делать это под прикрытием.

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

person Kylotan    schedule 12.10.2009
comment
Спасибо за ваш очень подробный ответ. Теперь я намного лучше понимаю, как работает битовый блит :) Что вы имеете в виду, когда я генерирую случайные высоты и цвета, которые должны быть сделаны до фазы рисования? По сути, что происходит, как только игра начинается, я рисую эту сцену, а позже, в игре, основанной на поворотах, мне нужно начать анимировать вещи. я не совсем уверен, как мне перерисовать тот же самый экран, который у меня был раньше. все мои попытки заканчиваются разными цветами и высотой - person ; 12.10.2009
comment
Между запуском игры и рисованием сцены вы создавали здания. Обычно у вас есть фаза инициализации, прежде чем вы сделаете какой-либо рендеринг или войдете в основной цикл, поэтому сделайте это там. Графика — это только визуальное представление вашей логики, а не сама логика. Поэтому настройте логику, один раз создав здания с нужными вам свойствами. Затем вы правильно визуализируете их позже, ссылаясь на эти свойства. Перерисовка сцены не изменит цвета или высоты, потому что вы создаете эти значения только один раз, в начале. - person Kylotan; 12.10.2009

Вы можете найти ответ на свой первый вопрос здесь:
http://en.wikipedia.org/wiki/Bit_blit

person THE DOCTOR    schedule 12.10.2009

  1. Да. Вам нужно использовать «алгоритм художника", чтобы нарисовать сцену сзади наперед.

  2. Таким образом, для каждого кадра анимации вы сначала рисуете фон, затем здания, а затем все, что находится перед зданиями. Вам не нужно «очищать» экран, если фон занимает весь экран.

person Justicle    schedule 12.10.2009