Мы не можем видеть значения textureSize
или размер вашего окна, поэтому мы не можем определить, должны ли они быть видимыми или нет. Если их координаты действительно находятся за пределами диапазона окна, они не будут видны.
Если вы хотите, чтобы ваши объекты были на экране, по крайней мере, некоторые их вершины должны находиться в пределах диапазона окна. Здесь есть три подхода:
- Изменение размера окна
- Масштабирование вершин
- Реализация прокрутки
" Прокрутка область рендеринга"не совсем так, как все работает на базовом уровне. Ваши вершины не относятся к реальному пространству: их координаты относительно окна . Концепция пространства визуализации - это абстракция, позволяющая сделать вещи более интуитивно понятными. Ваше окно не является порталом в какое-то альтернативное измерение, это фундаментальное пространство, где существуют объекты на самом низком уровне. Если координаты объекта находятся вне координат окна, объект не рисуется.
Если вы хотите, чтобы ваши вершины были видны, они должны находиться внутри окна. Первый вариант - увеличить окно.
Размер окна
Если вы хотите отобразить большую область, чем значение по умолчанию для pyglet (то есть 640 на 480), вы можете установить размер окна в один из следующих способов:
- Инициализировать окно с правильными размерами:
window = pyglet.window.Window(1280, 720)
.
Установите правильные размеры в другом месте программы:
window.set_size(1280, 720)
или window.width = 1280
и window.height = 720
.
Позволяет пользователю изменять размер окна при инициализации:
window = pyglet.window.Window(resizable = True)
.
И для максимального пространства рендеринга установите полноэкранное окно:
window = pyglet.window.Window(fullscreen = True)
, которое также можно переключать:
window.set_fullscreen(True)
и window.set_fullscreen(False)
.
См. Также Руководство и Документация обо всем, что вы можете сделать с окном.
В качестве альтернативы, вы можете захотеть масштабировать свой мир таким образом, оно полностью содержится внутри окна
Масштабирование
Возможно, вы довольны размером окна, но все еще не можете видеть все объекты в вашем мире. Если ваш мир больше, чем ваш идеальный размер окна, может быть целесообразно применить некоторое масштабирование и сопоставить ваши координаты мира с координатами окна.
Для масштабирования относительно координат начала координат (0., 0.)
в двух измерениях, процедура относительно проста: умножить все координаты на размер окна и разделить на размер мира. Возможно, вы захотите рассчитать соотношение window_size / world_size
раньше времени, а не каждый раз, когда вы хотите визуализировать.
Если вы хотите работать в системе координат, которая находится в большем масштабе, чем ваше окно, тогда вам нужно уменьшить координаты, когда вы хотите нарисовать их. Взяв приведенный выше код в качестве примера:
#Say our world is defined by the range of textureSize rectangles
widths, heights = zip(*textureSize)
world_width = max(widths) - min(widths) + 5
world_height = max(heights) - 0
#if your world has different dimensions, use those
#then this is our scale factor
scale_factor = min(window.width/world_width, window.height/world_height, 1.)
#keeping it up to date with our window
@window.event
def on_resize(width, height)
scale_factor = min(width/world_width, height/world_height, 1.)
#your code, now using scaled coordinates (and a few code readability changes)
for (width, height) in textureSize:
#working in world coordinates
prewidth = width + 5
#scale coordinates from world to window
width *= scale_factor
height *= scale_factor
prewidth *= scale_factor
#draw in window coordinates
pyglet.graphics.draw_indexed(
4,
pyglet.gl.GL_TRIANGLES,
[0, 1, 2, 0, 2, 3],
('v2f', (prewidth, 0, width, 0, width, height, prewidth, height)),
('c3B', (255,255,255, 255,255,255, 255,255,255, 255,255,255 ))
)
Этот шаблон работает, когда источник вашей мировой системы координат равен (0., 0.)
. Я настоятельно рекомендую работать в такой системе координат, если вы собираетесь использовать отдельную систему координат. Убедитесь, что scale_factor
доступен во всех позициях в коде, которые должны что-то нарисовать, или создайте объект pyglet (например, pyglet.graphics.vertex_list_indexed()
или pyglet.graphics.Batch().add_indexed()
), который будет нарисован позже. Если вы хотите что-то нарисовать или создать объект-пиглет, который что-то нарисовал aws, вам нужно будет указать масштабированные координаты, поэтому вам потребуется доступ к этому коэффициенту масштабирования.
Но, может быть, то, что вы на самом деле хочу не получить ваши объекты на стати c холсте. Возможно, вы действительно хотите реализовать прокрутку в качестве пользовательской функции.
Прокрутка
Как я уже говорил ранее, прокрутка не является нативной вещью. Это абстракция, которую мы придумываем, чтобы сделать вещи не нормальными для нас. Это работает так, что положение всех вершин перемещается в направлении, противоположном направлению прокрутки. Давайте распакуем это:
Вершины относительно окна. Если окно прокручивается вправо, то мы хотим, чтобы наши объекты двигались в кадре справа, двигаясь влево относительно рамки. Чтобы сделать это, мы хотим переместить их вершины влево пропорционально тому, сколько мы прокрутили вправо.
Чтобы начать с этой концепции, давайте сначала подумаем, что произойдет, если мы «прыгнем» вправо , На какое бы расстояние мы ни сместились вправо, на это расстояние мы должны переместить все вершины влево. Итак, давайте создадим функцию перехода (обычно называемую переводом):
import pyglet
#use this on all x, y pairs of vertices whenever we:
#jump the window a distance jump_x to the right
#and a distance jump_y up
def translate(x, y, jump_x, jump_y):
new_x = x - jump_x
new_y = y - jump_y
return new_x, new_y
# E X A M P L E
#---------------
#say we want to draw a white triangle 2k pixels offscreen somewhere
triangle_vertices = [(2000, 2000),(2050, 2100),(2100, 2000)]
triangle_colors = [(255,255,255)] * 3
#translate by a jump 2000 pixels right and up
jump_to = (2000, 2000)
triangle_vertices = [tuple(jump(*position, *jump_to)) for position in triangle_vertices ]
#useful function to have
#flattens 2D lists
def flatten(input_list):
return [value for sublist in input_list for value in sublist]
#now we can draw it
pyglet.graphics.draw_indexed(
3,
pyglet.gl.GL_TRIANGLES,
[0, 1, 2],
('v2f', tuple(flatten(triangle_locations))),
('c3B', tuple(flatten(triangle_colors)))
)
Теперь, когда мы можем переводить в прыжках, мы можем реализовать это всякий раз, когда просто прыгаем в окно. Но свиток не является внезапным прыжком; это плавное движение. Как нам это сделать?
Для этого нам потребуется оживить наш мир. Основной способ сделать это - добавить функцию анимации в расписание. Мы не можем запустить python в том же потоке, что и pyglet.app.run () после того, как он был вызван, так как он имеет бесконечное значение l oop, пока окно активно. Pyglet позволяет нам устанавливать расписание заранее, и он будет выполнять эти функции в то время, когда мы сообщаем ему об этом. Поэтому мы настроили расписание для анимации прокрутки.
У рассматриваемой функции должен быть доступ как к месту прокрутки, так и к вершинам для обновления. Это проблема, так как pyglet не имеет прямого доступа к нашему пространству имен. Один из элегантных способов сделать это - использовать классы.
Классы позволяют нам хранить переменные и функции в одной структуре данных и предоставлять функциям класса доступ к переменным класса. Поэтому, если мы создадим основной класс, который отслеживает все, что нам нужно знать, а также предоставляет функцию анимации, функция может использовать свой класс для доступа к месту прокрутки и вершинам для их перевода.
class Scroller
def __init__(self):
self.window = pyglet.window.Window()
#this keeps track of our scrolling
#we are currently scrolling to the right at a rate of 10 pixels per second
self.scroll = {
'currently': True
'x': 0
'y': 0
'vx': 10
'vy': 0
}
#this list is a stand-in for your actual data structure
#just make sure the animation function can access your vertices
x1, y1, x2, y2 = 100, 100, 200, 200
self.vertices = [(x1,y1),(x2,y2)]
#adding the animation function to the schedule (60 FPS)
framerate = 60
timestep = 1 / framerate
pyglet.clock.schedule_interval(self.scroll_animation, timestep)
#starting the program
pyglet.app.run()
#the translate function we already had
def translate(self, x, y, jump_x, jump_y):
return x - jump_x, y - jump_y
def scroll_animation(self, timestep):
#using self, we can access what we need
scroll = self.scroll
vertices = self.vertices
#by scaling the scrolling speed with the timestep
#we are free to choose our framerate independently of our scrollspeed
if scroll['currently']:
scroll['x'] += scroll['vx'] * timestep
scroll['y'] += scroll['vy'] * timestep
#the location to where we should scroll
scroll_to = [scroll[k] for k in ('x','y')]
#translating all vertices by the scrolling
for index, position in enumerate(vertices):
self.vertices[index] = translate(*vertex, *scroll_to)
#drawing the objects
#(this is pseudocode: use batches)
self.vertices.drawAll()
Scroller()
Это скелет прокрутки Вы можете выбрать способ прокрутки (пользовательский ввод? Непрерывное движение?), И вам нужно будет создать разумную структуру данных, чтобы эта работа работала. Но эта основная концепция, переводящая все вершины в противоположном направлении прокрутки, - это то, что вам нужно, чтобы прокрутка работала для вас. Я надеюсь, что это было полезно для вас. Желаем удачи.