Вам не хватает некоторых уровней абстракции .
Давайте начнем с базового скелета игры-пигмеи:
import pygame
def main():
pygame.init()
screen = pygame.display.set_mode((500, 500))
screen_rect = screen.get_rect()
sprites = pygame.sprite.Group()
clock = pygame.time.Clock()
rects = []
dt = 0
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
sprites.update(dt, events)
screen.fill(pygame.Color('darkgrey'))
sprites.draw(screen)
pygame.display.update()
dt = clock.tick(60)
if __name__ == '__main__':
main()
Мы хотим достичь Разделение интересов , поэтому давайте сохраним наш основной цикл чистым ипросто.Мы обрабатываем события (и единственные события, о которых заботится основной цикл, это QUIT
), мы обновляем наше игровое состояние (которое является Group
спрайтов с именем sprites
), мы рисуем вещи вэкран, и мы ограничиваем частоту кадров с помощью Clock
Итак, вы говорите, что у вас есть монопольная доска, поэтому давайте подумаем, как это представить.Давайте создадим список свойств, каждое из которых имеет цвет, имя и цену:
properties = (
('purple', 100, 'Oriental Avenue'),
('purple', 200, 'Vermont Avenue'),
('purple', 300, 'Connecticut Avenue'),
('white', 400, 'Atlantic Avenue'),
('white', 500, 'Ventnor Avenue'),
('white', 600, 'Marvin Gardens'),
('blue', 700, 'Park Place'),
('blue', 800, 'Boadwalk')
)
Обратите внимание, что это просто список некоторых данных (на самом деле это кортеж кортежей), так как мы хотим Разделение данных и кода .
Свойства являются частью игрового состояния.Давайте создадим класс, который будет содержать все игровое состояние и создаст для нас несколько спрайтов , которые мы будем использовать для рисования чего-либо на экране.Этот класс также вычисляет позицию каждого спрайта.
class Board:
def __init__(self, properties, font):
self.properties = properties
self.sprites = []
side = len(properties) / 4 + 1
size = (side * PROP_SIZE.width, side * PROP_SIZE.height)
x, y = 0, 0
flow = 'r'
for prop in properties:
if flow == 'r':
if x == side - 1:
flow = 'd'
else:
x += 1
if flow == 'd':
if y == side - 1:
flow = 'l'
else:
y += 1
if flow == 'l':
if x == 0:
flow = 'u'
else:
x -= 1
if flow == 'u':
y -= 1
self.sprites.append(Property(*prop, (x*PROP_SIZE.width, y*PROP_SIZE.height), font))
Мы хотим, чтобы каждое свойство имело две кнопки, поэтому давайте создадим класс спрайта Property
, который будет обрабатывать проверку событий для использования:
class Property(pygame.sprite.Sprite):
def __init__(self, color, price, name, pos, font):
super().__init__()
self.image = pygame.Surface(PROP_SIZE.size)
self.rect = self.image.get_rect()
pygame.draw.rect(self.image, (0, 0, 0), self.rect)
pygame.draw.rect(self.image, pygame.Color(color), self.rect.inflate(-2, -2))
self.color = color
self.price = price
self.name = name
font.render_to(self.image, (11, 21), name, pygame.Color('black'))
font.render_to(self.image, (10, 20), name, pygame.Color('white'))
self.buttons = {
'A': pygame.Rect(10, 100, 100, 20),
'B': pygame.Rect(10, 125, 100, 20),
}
self.rect.topleft = pos
def update(self, dt, events):
pos = pygame.mouse.get_pos()
for button in self.buttons:
hovered = self.buttons[button].move(*self.rect.topleft).collidepoint(pos)
pygame.draw.rect(self.image, pygame.Color('red' if hovered else 'darkgrey'), self.buttons[button])
for event in events:
if event.type == pygame.MOUSEBUTTONDOWN:
for button in self.buttons:
hovered = self.buttons[button].move(*self.rect.topleft).collidepoint(pos)
if hovered:
print(f'{self.name} says: You clicked {button}')
Мы используем некоторые приятные вещи в стиле пигмеев, такие как Rect класс, и это inflate , move и collidepoint методы, поэтому мынам не нужно вычислять позиции / столкновения самостоятельно.
Вот полный, работающий код.Вы получите идею:
import pygame
import pygame.freetype
PROP_SIZE = pygame.Rect(0, 0, 120, 180)
class Property(pygame.sprite.Sprite):
def __init__(self, color, price, name, pos, font):
super().__init__()
self.image = pygame.Surface(PROP_SIZE.size)
self.rect = self.image.get_rect()
pygame.draw.rect(self.image, (0, 0, 0), self.rect)
pygame.draw.rect(self.image, pygame.Color(color), self.rect.inflate(-2, -2))
self.color = color
self.price = price
self.name = name
font.render_to(self.image, (11, 21), name, pygame.Color('black'))
font.render_to(self.image, (10, 20), name, pygame.Color('white'))
self.buttons = {
'A': pygame.Rect(10, 100, 100, 20),
'B': pygame.Rect(10, 125, 100, 20),
}
self.rect.topleft = pos
def update(self, dt, events):
pos = pygame.mouse.get_pos()
for button in self.buttons:
hovered = self.buttons[button].move(*self.rect.topleft).collidepoint(pos)
pygame.draw.rect(self.image, pygame.Color('red' if hovered else 'darkgrey'), self.buttons[button])
for event in events:
if event.type == pygame.MOUSEBUTTONDOWN:
for button in self.buttons:
hovered = self.buttons[button].move(*self.rect.topleft).collidepoint(pos)
if hovered:
print(f'{self.name} says: You clicked {button}')
class Board:
def __init__(self, properties, font):
self.properties = properties
self.sprites = []
side = len(properties) / 4 + 1
size = (side * PROP_SIZE.width, side * PROP_SIZE.height)
x, y = 0, 0
flow = 'r'
for prop in properties:
if flow == 'r':
if x == side - 1:
flow = 'd'
else:
x += 1
if flow == 'd':
if y == side - 1:
flow = 'l'
else:
y += 1
if flow == 'l':
if x == 0:
flow = 'u'
else:
x -= 1
if flow == 'u':
y -= 1
self.sprites.append(Property(*prop, (x*PROP_SIZE.width, y*PROP_SIZE.height), font))
def main():
pygame.init()
screen = pygame.display.set_mode((800, 600))
screen_rect = screen.get_rect()
font = pygame.freetype.SysFont(None, 14)
font.origin = True
properties = (
('purple', 100, 'Oriental Avenue'),
('purple', 200, 'Vermont Avenue'),
('purple', 300, 'Connecticut Avenue'),
('white', 400, 'Atlantic Avenue'),
('white', 500, 'Ventnor Avenue'),
('white', 600, 'Marvin Gardens'),
('blue', 700, 'Park Place'),
('blue', 800, 'Boadwalk')
)
board = Board(properties, font)
sprites = pygame.sprite.Group(*board.sprites)
clock = pygame.time.Clock()
rects = []
dt = 0
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
sprites.update(dt, events)
screen.fill(pygame.Color('darkgrey'))
sprites.draw(screen)
pygame.display.update()
dt = clock.tick(60)
if __name__ == '__main__':
main()