pygame:自定义类继承自pygame.Surface
我第一次在玩pygame(而且对python也不太熟),想问问有没有人能帮我解决这个问题...
我正在做一个小的射击游戏,想为坏人创建一个类。我想这个类应该继承自pygame.Surface,但这让我遇到了很多问题(可能是我在基本的继承和类的知识上搞错了)。比如,为什么下面的代码不工作(pygame、屏幕等在代码的其他部分都能正常使用,我只是想把已经能用的函数移动到一个类里):
class Zombie(pygame.Surface):
x_pos = y_pos = 0
def __init__(self, x, y):
#create zombie
self = pygame.image.load('zombie_1.png')
self = pygame.transform.scale(self,(50, 50))
x_pos = x
y_pos = y
zombie = Zombie(screen.get_width()/3, screen.get_height()/3)
screen.blit(zombie, (zombie.x_pos, zombie.y_pos))
上面的代码产生了一个错误:“pygame.error: display Surface quit”。编辑:显然这是因为在调用pygame.display.quit()之后又试图使用Surface。有没有在pygame方面有经验的人能帮我看看这个?
完整代码:
#Initialize
import pygame, sys
pygame.init()
#classes
class Zombie(pygame.Surface):
x_pos = y_pos = 0
def __init__(self, x, y):
#create zombie
self = pygame.image.load('zombie_1.png')
self = pygame.transform.scale(self,(50, 50))
x_pos = x
y_pos = y
def is_hit(mouse_pos):
#grab variables
(mouseX, mouseY) = mouse_pos
print "\nboxW_x, y = " + str(self.x) + ", " + str(self.y) + "\nmouseX, Y = " + str(mouseX) + ", " + str(mouseY)
headshot_x = self.x + (.5 * zombie.get_width())
headshot_y = self.y + (.25 * zombie.get_height())
margin_of_error_x = (zombie.get_width()/float(1000)) * zombie.get_width()
margin_of_error_y = (zombie.get_height()/float(1000)) * zombie.get_height()
print "Headshot_x: " + str(headshot_x) + ", " + str(headshot_y)
print "diff in headshot and actual shot: " + str(mouseX - headshot_x) + ", " + str(mouseY - headshot_y)
print "margin of error x = " + str(margin_of_error_x) + " y = " + str(margin_of_error_y)
print "zombie size: " + str(zombie.get_size())
valid_x = valid_y = False
if abs(mouseX-headshot_x) < margin_of_error_x:
valid_x = True
print "valid x"
if abs(mouseY-headshot_y) < margin_of_error_y:
valid_y = True
print "valid y"
return (valid_x and valid_y)
#list of bad guys
zombie_list = []
#functions (which should later be moved into classes)
def is_hit():
#grab variables
(mouseX, mouseY) = pygame.mouse.get_pos()
print "\nboxW_x, y = " + str(boxW_x) + ", " + str(boxW_y) + "\nmouseX, Y = " + str(mouseX) + ", " + str(mouseY)
headshot_x = boxW_x + (.5 * boxW.get_width())
headshot_y = boxW_y + (.25 * boxW.get_height())
margin_of_error_x = (boxW.get_width()/float(1000)) * boxW.get_width()
margin_of_error_y = (boxW.get_height()/float(1000)) * boxW.get_height()
print "Headshot_x: " + str(headshot_x) + ", " + str(headshot_y)
print "diff in headshot and actual shot: " + str(mouseX - headshot_x) + ", " + str(mouseY - headshot_y)
print "margin of error x = " + str(margin_of_error_x) + " y = " + str(margin_of_error_y)
print "zombie size: " + str(boxW.get_size())
valid_x = valid_y = False
if abs(mouseX-headshot_x) < margin_of_error_x:
valid_x = True
print "valid x"
if abs(mouseY-headshot_y) < margin_of_error_y:
valid_y = True
print "valid y"
return (valid_x and valid_y)
pygame.mouse.set_visible(True)
pygame.mouse.set_cursor(*pygame.cursors.diamond)
#Display
screen = pygame.display.set_mode((640, 640))
pygame.display.set_caption("Zombie Massacre")
#Entities
#background
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((0, 0, 0))
#make a zombie
boxW = pygame.image.load('zombie_1.png')
boxW = pygame.transform.scale(boxW,(50, 50))
#set up some box variables
boxW_x = screen.get_width()/3
boxW_y = screen.get_height()/3
#testing zombie class
zombie = Zombie(screen.get_width()/3, screen.get_height()/3)
#Action
#Assign
clock = pygame.time.Clock()
keepGoing = True
#Loop
count = 0;
rotation_vect = 1.01
while keepGoing:
#setup rotation_vect for this pass
if (count % 3) == 0:
rotation_vect = 0 - rotation_vect
#Time
clock.tick(30)
#Events
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
elif event.type is pygame.MOUSEBUTTONDOWN:
#loop through zombie list, using each one's "is_hit()" function
keepGoing = not(is_hit())
#Refresh screen
screen.blit(background, (0,0))
boxW = pygame.transform.rotozoom(pygame.image.load('zombie_1.png'), rotation_vect, 1.01)
boxW = pygame.transform.scale(boxW,(count+50, count+100))
#for zombie in zombies
screen.blit(boxW,(boxW_x+(boxW_x * .1), boxW_y+(boxW_y * .1)))
# error is result of following line
screen.blit(zombie, (zombie.x_pos, zombie.y_pos))
pygame.display.flip()
#increment count
count += 1
2 个回答
3
我看到这个问题是在一个月前提的,但也许现在问还不算晚……
从你的代码来看,你基本上是在尝试重新创建一个精灵类。确实,你把图像和位置绑定在了一起。
我不太明白游戏的玩法是什么(除了那个爆头的部分 :D),不过这里有个例子,教你怎么显示僵尸并检测它们被射击的情况:
import pygame
TITLE = "Zombie Massacre"
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
class ZombieSprite(pygame.sprite.Sprite):
def __init__(self, image):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = pygame.Rect((0, 0), image.get_size())
self.defineHeadPos()
def defineHeadPos(self):
# To call each time the size of the rect changes.
head_x_center = self.rect.width / 2
head_y_center = self.rect.height / 4
head_width = self.rect.height / 4
head_height = self.rect.height / 4
head_x_min = head_x_center - head_width / 2
head_y_min = head_y_center - head_height / 2
self.head_rect = pygame.Rect((head_x_min, head_y_min),
(head_width, head_height))
def update(self):
# Here we could move the zombie.
pass
def shoot(self, pos):
x, y = pos
x -= self.rect.left
y -= self.rect.top
if self.head_rect.collidepoint(x, y):
print "Head shot !"
else:
print "Shot."
def ActionShoot(zombies, pos):
print "Shot at %s." % (pos,)
sprites = zombies.get_sprites_at(pos)
if not sprites:
print "Missed."
return
sprite = sprites[-1]
sprite.shoot(pos)
def DrawScene(screen, background, zombies):
screen.blit(background, (0, 0))
zombies.draw(screen)
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption(TITLE)
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((32, 32, 32))
image_zombie = pygame.image.load('zombie.png')
image_zombie.convert()
zombies = pygame.sprite.LayeredUpdates()
zombie = ZombieSprite(image_zombie)
zombie.rect.move_ip(0, 0)
zombies.add(zombie)
zombie = ZombieSprite(image_zombie)
zombie.rect.move_ip(400, 100)
zombies.add(zombie)
zombie = ZombieSprite(image_zombie)
zombie.rect.move_ip(300, 250)
zombies.add(zombie)
clock = pygame.time.Clock()
running = True
while running:
clock.tick(30)
zombies.update()
DrawScene(screen, background, zombies)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
ActionShoot(zombies, pygame.mouse.get_pos())
print "Quitting..."
pygame.quit()
这并不是一个完整的游戏,但我把这个留给你去完善。关键在于使用精灵和组来在不同的位置显示一堆僵尸。你可以把僵尸的“智能”放在它们的更新方法里(让它们移动,如果靠近屏幕就放大)。注意:我只用了一个图像对象来表示所有的僵尸。如果你开始放大,就需要给每个僵尸都用自己的图像对象,这意味着要为每个僵尸加载 zombie.png。否则,当你放大一个僵尸时,其他的也会一起放大。
4
你没有调用继承的构造函数:
class Zombie(pygame.Surface):
def __init__(self, x, y):
pygame.Surface.__init__(self, size=(w,h))
而且你在给 self
赋值。这是行不通的。