I'm working in pygame & python and trying to make a zombie shooting game. It all worked smoothly until I tried to add the collision system. If you also know how to add a collision system for this game please leave a comment with a full code.
The error:
type object 'bullet' has no attribute 'rect'
File "C:\Users\*\Desktop\Zombie!\main.py", line 172, in game
collide = pygame.sprite.spritecollide(bullet, enemiesList, False)
File "C:\Users\*\Desktop\Zombie!\main.py", line 44, in menu
game()
File "C:\Users\*\Desktop\Zombie!\main.py", line 211, in <module>
menu()
The code:
import pygame, sys, math, random, time
pygame.init()
#var
screen = pygame.display.set_mode([800, 500])
font = pygame.font.SysFont(None, 20)
playerX = 200
playerY = 200
player = pygame.Rect((playerX, playerY), (10,10))
bullets = pygame.sprite.Group()
clock = pygame.time.Clock()
previous_time = pygame.time.get_ticks()
waveCount = 1
#Remaining enemy count
enemiesList = pygame.sprite.Group()
normalEnemy = 0
speedyEnemy = 0
tankEnemy = 0
def draw_text(text, font, color, surface, x, y):
textobj = font.render(text, 1, color)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
click = False
def menu():
while True:
global click
screen.fill((0,0,0))
draw_text('main menu', font, (255, 255, 255), screen, 20, 20)
mx, my = pygame.mouse.get_pos()
button_1 = pygame.Rect(50, 100, 200, 50)
button_2 = pygame.Rect(50, 200, 200, 50)
if button_1.collidepoint((mx, my)):
if click:
game()
if button_2.collidepoint((mx, my)):
if click:
options()
pygame.draw.rect(screen, (255, 0, 0), button_1)
pygame.draw.rect(screen, (255, 0, 0), button_2)
click = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
click = True
pygame.display.update()
clock.tick(60)
def game():
run = True
class bullet(pygame.sprite.Sprite):
def __init__(self, x, y, mx, my):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.mx = mx
self.my = my
self.speed = 10
self.angle = math.atan2(my-self.y, mx-self.x)
self.x_vel = math.cos(self.angle) * self.speed
self.y_vel = math.sin(self.angle) * self.speed
self.radius = 4
self.mask = pygame.mask.Mask((self.radius, self.radius), True)
self.rect = pygame.Rect(self.x, self.y, self.radius, self.radius)
def update(self):
self.x = int(self.x_vel)
self.y = int(self.y_vel)
pygame.draw.circle(screen, (0, 255, 255), (self.x 5, self.y 5), self.radius)
if self.x > 800 or self.x < 0 or self.y > 500 or self.y < 0:
#Remove Bullet Class from list(bullets)
self.kill()
class enemy(pygame.sprite.Sprite):
def __init__(self, enemyType, x, y):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
if enemyType == "normal":
self.speed = 1
self.hp = 1
self.color = (255, 28, 28)
self.radius = 10
if enemyType == "speedy":
self.speed = 3
self.hp = 1
if enemyType == "tank":
self.speed = 3
self.hp = 3
self.mask = pygame.mask.Mask((self.radius, self.radius), True)
self.rect = pygame.Rect(self.x, self.y, self.radius, self.radius)
def update(self):
global playerX, playerY, enemiesList, bullets
# Find direction vector (dx, dy) between enemy and player.
dx, dy = playerX - self.x, playerY - self.y
dist = math.hypot(dx, dy)
dx, dy = dx / dist, dy / dist # Normalize.
# Move along this normalized vector towards the player at current speed.
self.x = dx * self.speed
self.y = dy * self.speed
pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius)
#Wave system
def waves(waveNumber):
global normalEnemy,speedyEnemy, tankEnemy, enemiesList, waveCount
if waveNumber == 1:
normalEnemy = 5
speedyEnemy = 0
tankEnemy = 0
for i in range(5):
enemiesList.add(enemy("normal", random.randint(0, 800), random.randint(0, 600)))
if waveNumber == 2:
normalEnemy = 7
speedyEnemy = 0
tankEnemy = 0
while run:
clock.tick(60)
screen.fill([255, 255, 255])
mx, my= pygame.mouse.get_pos()
#movements
def movement():
global playerX, playerY, previous_time
key = pygame.key.get_pressed()
mouse = pygame.mouse.get_pressed()
if key[pygame.K_w]:
playerY -= 5
if key[pygame.K_s]:
playerY = 5
if key[pygame.K_d]:
playerX = 5
if key[pygame.K_a]:
playerX -= 5
if mouse[0]:
current_time = pygame.time.get_ticks()
if current_time - previous_time > 500:
previous_time = current_time
bullets.add(bullet(playerX, playerY, mx, my))
for bullets_ in bullets:
bullets_.update()
for enemies_ in enemiesList:
enemies_.update()
if normalEnemy == 0 and speedyEnemy == 0 and tankEnemy == 0:
waves(waveCount)
collide = pygame.sprite.spritecollide(bullet, enemiesList, False)
def draw():
global player, waveCount
player = pygame.Rect((playerX, playerY), (10,10))
pygame.draw.rect(screen, (0, 255, 0), player)
draw_text('wave:' str(waveCount), font, (0, 0, 0), screen, 20, 20)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
movement()
draw()
pygame.display.flip()
def options():
running = True
while running:
screen.fill((0,0,0))
draw_text('options', font, (255, 255, 255), screen, 20, 20)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
pygame.display.update()
clock.tick(60)
menu()
I am pretty sure I assigned self.rect at the bullet class, I checked the indents and the spelling but I can't to seem to find the error.
CodePudding user response:
pygame.sprite.spritecollide - assumes that first parameter is an instance of a class which has 'rect' attribute. But you put the class itself there.
I believe the code must looks like this:
for bullets_ in bullets:
collide = pygame.sprite.spritecollide(bullets_, enemiesList, False)
CodePudding user response:
Look at the error: type error bullet ... . Somewhere, you're using the bullet
class name instead of using an instance of that class.
CodePudding user response:
You have a Group bullets
and a Group enemiesList
. Use pygame.sprite.groupcollide()
to detect collisions between Sprites in Groups:
collide = pygame.sprite.groupcollide(bullets, enemiesList, False, False)