Python Pygame冲突,属性错误
我是一名学生,正在从事一项学校项目。我的碰撞不起作用,我开始感到沮丧。每当我尝试运行游戏时,就会弹出一条错误消息 AttributeError:类型对象“Ball”没有属性“rect” 在我的代码中,您将看到我有Python Pygame冲突,属性错误,python,python-2.7,pygame,collision,attributeerror,Python,Python 2.7,Pygame,Collision,Attributeerror,我是一名学生,正在从事一项学校项目。我的碰撞不起作用,我开始感到沮丧。每当我尝试运行游戏时,就会弹出一条错误消息 AttributeError:类型对象“Ball”没有属性“rect” 在我的代码中,您将看到我有self.rect=pygame.rect(self.x,self.y,100100)。我尝试过使用get_rect函数,但仍然不起作用。如果您对代码有任何提示,请随时添加注释 import pygame import random import os from pygame impor
self.rect=pygame.rect(self.x,self.y,100100)
。我尝试过使用get_rect函数,但仍然不起作用。如果您对代码有任何提示,请随时添加注释
import pygame
import random
import os
from pygame import mixer
# accessed: 4/6/18 code:https://github.com/codingandcaring/PYgame/blob/bacaab1bd6ec0c97412a136773dfd634455c3e2f/basketball_game.py
#Music
#Tutorial from computingmrh - https://www.youtube.com/watch?v=lUMSK6LmXCQ used on 5th may 2018
snd_file = 'Game.ogg'
mixer.init()
mixer.music.load(snd_file)
mixer.music.play()
#spirtes
class Ball(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('basketball.png').convert_alpha()
self.image = pygame.transform.scale(self.image, (100, 100))
self.x = x
self.y = y
self.rect = pygame.Rect(self.x, self.y, 100, 100)
self.speed_x = 5
self.speed_y = 5
self.radiusx = 0
self.radiusy = 100
self.mask = pygame.mask.from_surface(self.image)
def update(self, width, height):
self.x += self.speed_x
self.y += self.speed_y
self.rect = pygame.Rect(self.x, self.y, 100, 100)
if self.x + self.radiusx > width:
self.speed_x = 0
if self.y + self.radiusx > height:
self.speed_y = 0
if self.x + self.radiusy > width:
self.speed_x = 0
if self.y + self.radiusy > height:
self.speed_y = 0
if self.x - self.radiusx <= 0:
self.speed_x = 0
if self.y - self.radiusx <= 0:
self.speed_y = 0
def render(self, screen):
screen.blit(self.image, (self.x, self.y))
class Goal(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('goal.png').convert_alpha()
self.image = pygame.transform.scale(self.image, (220, 220))
self.x = x
self.y = y
self.rect = pygame.Rect(self.x, self.y, 220, 220)
def render(self, screen):
screen.blit(self.image, (self.x, self.y))
class Ring(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('ring.png').convert_alpha()
self.image = pygame.transform.scale(self.image, (400, 400))
self.x = x
self.y = y
self.rect = pygame.Rect(self.x, self.y, 400, 400)
self.mask = pygame.mask.from_surface(self.image)
def render(self, screen):
screen.blit(self.image, (self.x, self.y))
class Baddie(pygame.sprite.Sprite):
def __init__(self, x, y, z):
self.image = pygame.image.load().convert_alpha()
self.image = pygame.transform.scale(self.image, (220, 220))
self.rect = self.image.get_rect()
self.x = x
self.y = y
def render(self, screen):
screen.blit(self.image, (self.x, self.y))
def main():
# basics
width = 1200
height = 722
pygame.init()
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Basketball Shootout')
font = pygame.font.Font(None, 25)
#code for the badguys
badtimer=100
badtimer1=0
badguys=[[640,100]]
# Add Variables
court = pygame.image.load('halfcourt.jpg')
court = pygame.transform.scale(court, (1200, 722))
basketball = Ball(50, 50)
goal = Goal(487, 0)
ring = Ring(400,400)
player = Ball
badguyimg1 = pygame.image.load("wpierdol.png")
badguyimg1 = pygame.transform.scale(badguyimg1, (100, 100))
badguyimg2 = pygame.image.load("bad_guy2.gif")
badguyimg2 = pygame.transform.scale(badguyimg2, (100, 100))
badguyimg3 = pygame.image.load("bad_guy3.gif")
badguyimg3 = pygame.transform.scale(badguyimg3, (100, 100))
badlist = [badguyimg1, badguyimg2, badguyimg3]
stop_game = False
#main game logic
while not stop_game:
badtimer -= 1
point = pygame.sprite.collide_mask(player, ring)
if point:
score = score + 1
#Draw the bad guys
if badtimer==0:
badguys.append([1040, random.randint(50,430)])
badtimer=100-(badtimer1*2)
if badtimer1>=35:
badtimer1=35
else:
badtimer1+=5
index=0
for badguy in badguys:
if badguy[0]<-64:
badguys.pop(index)
badguy[0]-=7
index+=1
for event in pygame.event.get():
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]:
basketball.y -= 5
basketball.speed_y = -5
elif pressed[pygame.K_DOWN]:
basketball.y += 5
basketball.speed_y = 5
elif pressed[pygame.K_LEFT]:
basketball.x -= 5
basketball.speed_x = -5
elif pressed[pygame.K_RIGHT]:
basketball.x += 5
basketball.speed_x = 5
if event.type == pygame.QUIT:
stop_game = True
# Updating
basketball.update(width, height)
screen.blit(court, (0,0))
text = font.render('Dodge the other team to get to the goal!', True, (0, 0, 0))
screen.blit(text, (430, 630))
goal.render(screen)
basketball.render(screen)
for badguy in badguys:
screen.blit(badguyimg1)
pygame.display.update()
pygame.quit()
if __name__ == '__main__':
main()
导入pygame
随机输入
导入操作系统
从pygame导入混合器
#访问日期:2018年4月6日代码:https://github.com/codingandcaring/PYgame/blob/bacaab1bd6ec0c97412a136773dfd634455c3e2f/basketball_game.py
#音乐
#来自computingmrh的教程-https://www.youtube.com/watch?v=lUMSK6LmXCQ 2018年5月5日使用
snd_文件='Game.ogg'
mixer.init()
mixer.music.load(snd_文件)
混音器。音乐。播放()
#尖塔
班级舞会(pygame.sprite.sprite):
定义初始化(self,x,y):
pygame.sprite.sprite.\uuuuu init\uuuuuuu(自我)
self.image=pygame.image.load('basketball.png')。convert_alpha()
self.image=pygame.transform.scale(self.image,(100100))
self.x=x
self.y=y
self.rect=pygame.rect(self.x,self.y,100100)
自速度_x=5
自速度_y=5
self.radiusx=0
自半径Y=100
self.mask=pygame.mask.from_surface(self.image)
def更新(自身、宽度、高度):
self.x+=self.speed\u x
self.y+=self.speed\u y
self.rect=pygame.rect(self.x,self.y,100100)
如果self.x+self.radiusx>宽度:
自速度_x=0
如果self.y+self.radiusx>高度:
自速度_y=0
如果self.x+self.radiusy>宽度:
自速度_x=0
如果self.y+self.radiusy>高度:
自速度_y=0
如果self.x-self.radiusx会引发异常,因为变量player
是对类Ball
的引用,而不是它的实例
请看这一行:
player = Ball
这不会创建新实例,因为您不会使用(…)
调用该类
除此之外,如果您使用Sprite
类,最好像预期的那样使用它。当类中已有rect
属性时,将坐标存储在x
和y
属性中没有意义
另外,如果已经有组
类为您执行此操作,则不需要渲染
方法
下面是一个示例,我更改了您的代码以使用预期的pygame功能(为简洁起见简称):
引发异常是因为变量player
是对类Ball
的引用,而不是它的实例
请看这一行:
player = Ball
这不会创建新实例,因为您不会使用(…)
调用该类
除此之外,如果您使用Sprite
类,最好像预期的那样使用它。当类中已有rect
属性时,将坐标存储在x
和y
属性中没有意义
另外,如果已经有组
类为您执行此操作,则不需要渲染
方法
下面是一个示例,我更改了您的代码以使用预期的pygame功能(为简洁起见简称):
有几个问题,但正如Sloth已经解释的那样,AttributeError
被提出,因为player
是对Ball
类的引用,而不是实例。player
变量实际上毫无意义,因为basketball
是实际的可玩实例,而不是player
,您应该将basketball
传递给collide\u mask
函数。只需卸下播放器
point = pygame.sprite.collide_mask(basketball, ring)
事件处理有点混乱。不要调用事件循环内的pygame.key.get\u pressed
(用于pygame.get\u event():
),因为队列中的每个事件都将执行该行和以下代码一次
您还混合了两种移动精灵的方法:使用键执行basketball.y-=5
。按下或在事件循环中设置速度:basketball.speed\u y=-5
for event in pygame.event.get():
if event.type == pygame.QUIT:
stop_game = True
# Either set the speed here.
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
basketball.speed_y = -5
# Or increment the `basketball.y` in the while loop with `pygame.key.get_pressed`.
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]:
basketball.y -= 5
elif pressed[pygame.K_DOWN]:
basketball.y += 5
if pressed[pygame.K_LEFT]: # if not elif, to separate vertical and horizontal movement.
basketball.x -= 5
elif pressed[pygame.K_RIGHT]:
basketball.x += 5
如果使用键.get_pressed
解决方案,可以删除self.speed_x
和speed_y
属性
您还可以将屏幕大小的矩形传递给update
方法,并使用它夹住球的矩形
def update(self, screen_rect): # Pass a rect with the size of the screen.
self.x += self.speed_x
self.y += self.speed_y
self.rect.topleft = (self.x, self.y)
if not screen_rect.contains(self.rect):
# Clamp the rect if it's outside of the screen.
self.rect.clamp_ip(screen_rect)
self.x, self.y = self.rect.topleft
您应该添加一个pygame.time.Clock
实例,并在每一帧调用Clock.tick
以限制帧速率,否则游戏将运行得太快,速度将取决于电脑
在对列表(和其他可变容器)进行迭代时,不应修改它们,或者可以跳过项目。只需迭代切片副本(或使用列表):
有几个问题,但正如Sloth已经解释的那样,AttributeError
被提出,因为player
是对Ball
类的引用,而不是实例。player
变量实际上毫无意义,因为basketball
是实际的可玩实例,而不是player
,您应该将basketball
传递给collide\u mask
函数。只需卸下播放器
point = pygame.sprite.collide_mask(basketball, ring)
事件处理有点混乱。不要调用事件循环内的pygame.key.get\u pressed
(用于pygame.get\u event():
),因为队列中的每个事件都将执行该行和以下代码一次
您还混合了两种不同的方式来移动精灵:使用basketball.y-=5
import random
import pygame
class Ball(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
# self.image = pygame.image.load('basketball.png').convert_alpha()
# self.image = pygame.transform.scale(self.image, (100, 100))
self.image = pygame.Surface((100, 100)).convert_alpha()
self.image.fill((160, 70, 0))
self.x = x
self.y = y
self.rect = pygame.Rect(self.x, self.y, 100, 100)
self.speed_x = 0
self.speed_y = 0
self.radiusx = 0
self.radiusy = 100
self.mask = pygame.mask.from_surface(self.image)
def update(self, screen_rect): # Pass a rect with the size of the screen.
self.x += self.speed_x
self.y += self.speed_y
self.rect.topleft = (self.x, self.y)
if not screen_rect.contains(self.rect):
# Clamp the rect if it's outside of the screen.
self.rect.clamp_ip(screen_rect)
self.x, self.y = self.rect.topleft
def render(self, screen):
screen.blit(self.image, self.rect)
class Goal(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
# self.image = pygame.image.load('goal.png').convert_alpha()
# self.image = pygame.transform.scale(self.image, (220, 220))
self.image = pygame.Surface((220, 220)).convert_alpha()
self.image.fill((60, 80, 110))
self.x = x
self.y = y
self.rect = pygame.Rect(self.x, self.y, 220, 220)
def render(self, screen):
screen.blit(self.image, self.rect)
class Ring(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
# self.image = pygame.image.load('ring.png').convert_alpha()
# self.image = pygame.transform.scale(self.image, (400, 400))
self.image = pygame.Surface((400, 400)).convert_alpha()
self.image.fill((60, 180, 110))
self.x = x
self.y = y
self.rect = pygame.Rect(self.x, self.y, 400, 400)
self.mask = pygame.mask.from_surface(self.image)
def render(self, screen):
screen.blit(self.image, self.rect)
class Baddie(pygame.sprite.Sprite):
def __init__(self, x, y, z):
# self.image = pygame.image.load().convert_alpha()
# self.image = pygame.transform.scale(self.image, (220, 220))
self.image = pygame.Surface((90, 90)).convert_alpha()
self.image.fill((250, 50, 0))
self.rect = self.image.get_rect()
self.x = x
self.y = y
def render(self, screen):
screen.blit(self.image, (self.x, self.y))
def main():
width = 1200
height = 722
pygame.init()
screen = pygame.display.set_mode((width, height))
screen_rect = screen.get_rect()
clock = pygame.time.Clock() # Add a clock to limit the frame rate.
pygame.display.set_caption('Basketball Shootout')
font = pygame.font.Font(None, 25)
badtimer = 100
badtimer1 = 0
badguys = [[640, 100]]
# court = pygame.image.load('halfcourt.jpg')
# court = pygame.transform.scale(court, (1200, 722))
court = pygame.Surface((1200, 722))
court.fill((30, 30, 30))
basketball = Ball(50, 50)
goal = Goal(487, 0)
ring = Ring(400, 400)
# The player is not needed since the `basketball` is already
# the playable ball instance.
# player = Ball # Just remove this line.
# badguyimg1 = pygame.image.load("wpierdol.png")
# badguyimg1 = pygame.transform.scale(badguyimg1, (100, 100))
# badguyimg2 = pygame.image.load("bad_guy2.gif")
# badguyimg2 = pygame.transform.scale(badguyimg2, (100, 100))
# badguyimg3 = pygame.image.load("bad_guy3.gif")
# badguyimg3 = pygame.transform.scale(badguyimg3, (100, 100))
badguyimg1 = pygame.Surface((90, 90))
badguyimg1.fill((60, 50, 210))
badguyimg2 = pygame.Surface((90, 90))
badguyimg2.fill((250, 50, 210))
badguyimg3 = pygame.Surface((90, 90))
badguyimg3.fill((250, 50, 130))
badlist = [badguyimg1, badguyimg2, badguyimg3]
score = 0 # The score variable was missing.
stop_game = False
while not stop_game:
# Event handling.
for event in pygame.event.get():
if event.type == pygame.QUIT:
stop_game = True
# Either set the speed here or increment the `basketball.y`
# in the while loop with `pygame.key.get_pressed`.
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
basketball.speed_y = -5
elif event.key == pygame.K_DOWN:
basketball.speed_y = 5
elif event.key == pygame.K_LEFT:
basketball.speed_x = -5
elif event.key == pygame.K_RIGHT:
basketball.speed_x = 5
elif event.type == pygame.KEYUP:
# Stop the ball.
if event.key == pygame.K_UP:
basketball.speed_y = 0
elif event.key == pygame.K_DOWN:
basketball.speed_y = 0
elif event.key == pygame.K_LEFT and basketball.speed_x < 0:
basketball.speed_x = 0
elif event.key == pygame.K_RIGHT and basketball.speed_x > 0:
basketball.speed_x = 0
# Don't call get_pressed in the event loop (for every event).
# pressed = pygame.key.get_pressed()
# if pressed[pygame.K_UP]:
# basketball.y -= 5
# elif pressed[pygame.K_DOWN]:
# basketball.y += 5
# if pressed[pygame.K_LEFT]: # if not elif, to separate vertical and horizontal movement.
# basketball.x -= 5
# elif pressed[pygame.K_RIGHT]:
# basketball.x += 5
# Updating.
basketball.update(screen_rect)
badtimer -= 1
point = pygame.sprite.collide_mask(basketball, ring) # Use basketball not player.
if point:
# The score will be incremented continually.
score = score + 1
print(score)
# Update the bad guys.
if badtimer == 0:
badguys.append([1040, random.randint(50,430)])
badtimer = 100-(badtimer1*2)
if badtimer1 >= 35:
badtimer1 = 35
else:
badtimer1 += 5
# You can `enumerate` the badguys list to get the index
# and the item at the same time.
for index, badguy in enumerate(badguys[:]):
if badguy[0] < -64:
# Don't modify a list while you're iterating over it.
# Iterate over a slice copy: badguys[:]
badguys.pop(index)
badguy[0] -= 7
# Drawing.
screen.blit(court, (0,0))
text = font.render(
'Dodge the other team to get to the goal!',
True, (0, 0, 0))
screen.blit(text, (430, 630))
goal.render(screen)
# You forgot to render the ring.
ring.render(screen)
for badguy in badguys:
screen.blit(badguyimg1, badguy) # The `dest`ination arg was missing.
basketball.render(screen)
pygame.display.update()
clock.tick(60) # Limit the frame rate to 60 FPS.
pygame.quit()
if __name__ == '__main__':
main()