#python #pygame
#python #pygame
Вопрос:
Я довольно новичок в Pygame и, похоже, не могу найти четкого ответа на этот вопрос. У меня есть фигура, в частности эллипс, которую я хочу поворачивать как влево, так и вправо. Привязкой клавиш будет a
и d
, поскольку клавиши со стрелками уже привязаны для перемещения влево и вправо по осям x, y.
Я знаю, что это связано pygame.transform.rotate
, однако, похоже, я не могу правильно это реализовать.
def main():
#Setup basic variables and methods for pygame
pygame.init()
windowWidth = 800
windowHeight = 700
fps = 45
clock = pygame.time.Clock()
gameWindow = pygame.display.set_mode((windowWidth, windowHeight))
surface = pygame.Surface((50,50))
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
shipX = windowWidth/2
shipY = windowWidth/2
shipSpeed = 4
while(True):
pygame.draw.ellipse(gameWindow, WHITE, (shipX, shipY, 20, 30))
#Monitor the FPS of the game
clock.tick(fps)
for event in pygame.event.get():
# ________________________________________
if event.type == pygame.QUIT:
gameExit()
rotate = 0
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP] and shipY > shipSpeed: shipY -= shipSpeed
if pressed[pygame.K_DOWN] and shipY < windowHeight - shipSpeed - 20: shipY = shipSpeed
if pressed[pygame.K_LEFT] and shipX > shipSpeed:shipX -= shipSpeed
if pressed[pygame.K_RIGHT] and shipX < windowWidth - shipSpeed - 20: shipX = shipSpeed
if pressed[ord('a')]: rotate = pygame.transform.rotate(surface, -20)
if pressed[ord('d')]: rotate = pygame.transform.rotate(surface, 20)
gameWindow.fill(BLACK)
# 'flip' display - always after drawing...
pygame.display.flip()
Ожидаемый результат заключается в том, что фигура изменит свой угол, а затем переместится соответствующим образом.
Опять же, я очень новичок в pygame, поэтому буду признателен за любую подробную помощь.
Ответ №1:
Ваша проблема в том, что вы рисуете эллипс прямо на экране, но вы должны нарисовать свой эллипс на другом Surface
.
Затем вы можете повернуть эту новую фигуру Surface
с pygame.transform.rotate
помощью.
Вот простой пример:
import pygame
import random
def main():
pygame.init()
screen = pygame.display.set_mode((500, 500))
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
surface = pygame.Surface((100, 200))
surface.set_colorkey((2, 3, 4))
surface.fill((2, 3, 4))
rect = surface.get_rect(center=(100, 100))
pygame.draw.ellipse(surface, pygame.Color('white'), (0, 0, 100, 200))
angle = 0
dt = 0
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]: rect.move_ip(0, -5)
if pressed[pygame.K_DOWN]: rect.move_ip(0, 5)
if pressed[pygame.K_LEFT]: rect.move_ip(-5, 0)
if pressed[pygame.K_RIGHT]: rect.move_ip(5, 0)
if pressed[pygame.K_a]: angle = 1
if pressed[pygame.K_d]: angle -= 1
rotated = pygame.transform.rotate(surface, angle)
rect = rotated.get_rect(center=rect.center)
rect.clamp_ip(screen_rect)
screen.fill(pygame.Color('dodgerblue'))
screen.blit(rotated, rect.topleft)
pygame.display.update()
dt = clock.tick(60)
if __name__ == '__main__':
main()
Обратите внимание, что я использую a Rect
для сохранения положения объекта, потому что затем его легко повернуть Surface
вокруг его центра (установив его center
атрибут), и для того, чтобы он Surface
не выходил за пределы экрана (используя clamp_ip
).
Кроме того, важно всегда поворачивать исходный код Surface
, а не уже повернутый Surface
. В противном случае вы получите искажения.
Обратите внимание, что здесь у нас есть три вещи: изображение, позиция и некоторая логика поведения. Всякий раз, когда вы видите эти вещи вместе, подумайте о том, чтобы объединить их в класс. Pygame уже предлагает для этого хороший класс под названием Sprite
.
Вот тот же пример, но Sprite
основанный:
import pygame
import random
class Thingy(pygame.sprite.Sprite):
def __init__(self, area):
super().__init__()
# image is what get's painted on the screen
self.image = pygame.Surface((100, 200))
self.image.set_colorkey((2, 3, 4))
self.image.fill((2, 3, 4))
pygame.draw.ellipse(self.image, pygame.Color('white'), (0, 0, 100, 200))
# we keep a reference to the original image
# since we use that for rotation to prevent distortions
self.original = self.image.copy()
# rect is used to determine the position of a sprite on the screen
# the Rect class also offers a lot of useful functions
self.rect = self.image.get_rect(center=(100, 100))
self.angle = 0
self.area = area
def update(self, events, dt):
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]: self.rect.move_ip(0, -5)
if pressed[pygame.K_DOWN]: self.rect.move_ip(0, 5)
if pressed[pygame.K_LEFT]: self.rect.move_ip(-5, 0)
if pressed[pygame.K_RIGHT]: self.rect.move_ip(5, 0)
if pressed[pygame.K_a]: self.angle = 1
if pressed[pygame.K_d]: self.angle -= 1
# let's rotate the image, but ensure that we keep the center position
# so it doesn't "jump around"
self.image = pygame.transform.rotate(self.original, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
self.rect.clamp_ip(self.area)
def main():
pygame.init()
screen = pygame.display.set_mode((500, 500))
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
sprites = pygame.sprite.Group(Thingy(screen_rect))
dt = 0
while True:
# nice clean main loop
# all game logic goes into the sprites
# handle "global" events
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
# update all sprites
sprites.update(events, dt)
# draw everything
screen.fill(pygame.Color('dodgerblue'))
sprites.draw(screen)
pygame.display.update()
dt = clock.tick(60)
if __name__ == '__main__':
main()
Ответ №2:
Вы должны создать класс для своего объекта:
class myRect(pygame.Surface):
def __init__(self, parent, xpos, ypos, width, height):
super(myRect, self).__init__(width, height)
self.xpos = xpos
self.ypos = ypos
self.parent = parent
def update(self, parent):
parent.blit(self, (self.xpos, self.ypos))
def rotate(self, angle):
#(your rotation code goes here)
Комментарии:
1. Я вижу. Итак, код преобразования входит в указанное определение поворота, и указанный класс вызывается при нажатии клавиши? Имеет смысл. Я попробую это
2. Класс вызывается, когда вы хотите создать свой объект. Теперь вы можете просто вызывать
class instance.rotate()
при нажатии клавиши