I get the error message 'Enemy' object has no attribute '_Sprite__g' and I have no idea how to use the sprite groups. I'm trying to get them to spawn randomly across the x-axis only.
import pygame, os, random
pygame.init()
FPS=60
SCREEN = pygame.display.set_mode((400,500))
pygame.display.set_caption('caption')
x=50
y=450
vel = 3
width = 20
height = 20
class Player(object):
def __init__(self,x,y,width,height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 3
self.image = pygame.Surface((width, height))
self.image.fill((0,0,0))
def draw(self,SCREEN):
SCREEN.blit(self.image, (self.x,self.y))
class B():
def __init__(self,x,y,radius, color):
self.x = x
self.y = y
self.color = color
self.radius = radius
self.vel = vel
def draw(self,SCREEN):
pygame.draw.circle(SCREEN, self.color, (self.x,self.y),self.radius)
class Enemy(pygame.sprite.Sprite):
def __init__(self):
self.image = pygame.Surface((20,20))
self.x = random.randrange (0,400)
self.y = 500
self.speed = random.randrange(1,3)
def draw (self,SCREEN):
SCREEN.blit(self.image,(self.x,self.y))
player = Player(x, y, width, height)
bullets = []
enemies = pygame.sprite.Group()
# Main loop
running = True
clock = pygame.time.Clock()
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
for bullet in bullets:
if bullet.x < 450 and bullet.x >0:
bullet.x += bullet.vel
else:
bullets.pop(bullets.index(bullet))
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if len(bullets)< 5:
bullets.append(B(round(player.x + player.width //2), round(player.y + player.height//2),3, (0,0,0)))
if keys[pygame.K_w] and player.y > 30 - player.width - player.vel:
player.y -= player.vel
if keys[pygame.K_s] and player.y < 500 - player.width - player.vel:
player.y += player.vel
SCREEN.fill((190, 232, 220))
player.draw(SCREEN)
for bullet in bullets:
bullet.draw(SCREEN)
for i in range (8):
e = Enemy()
enemies.add(e)
pygame.display.update()
pygame.quit()
the obects need to be derives from pygame.sprite.Sprite. The base class needs to be initialized as well. Use super() to delegate to the base class constructor. e.g.:
class Player(object):
def __init__(self,x,y,width,height):
super().__init__()
# [...]
pygame.sprite.Group.draw() and pygame.sprite.Group.update() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update method of the contained pygame.sprite.Sprites - you have to implement the method. See pygame.sprite.Group.update():
Calls the update() method on all Sprites in the Group [...]
The later uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects - you have to ensure that the pygame.sprite.Sprites have the required attributes. See pygame.sprite.Group.draw():
Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]
Therefore the Sprite class must have the attributes .rect and .image. However you don't need the draw method:
class Player(pygame.sprite.Sprite):
def __init__(self,x,y,width,height):
super().__init__()
self.vel = 3
self.image = pygame.Surface((width, height))
self.image.fill((0,0,0))
self.rect = self.image.get_rect(topleft = (x, y))
Create a transparent pygame.Surface with the SRCALPHA flag and draw a circle on it:
class B(pygame.sprite.Sprite):
def __init__(self,x,y,radius, color):
super().__init__()
self.x = x
self.y = y
self.color = color
self.radius = radius
self.vel = vel
self.image = pygame.Surface((self.radius * 2, self.radius * 2), pygame.SRCALPHA)
pygame.draw.circle(self.image, self.color, (self.radius, self.radius), self.radius)
self.rect = self.image.get_rect(center = (self.x, self.y))
Add pygame.sprite.Groups for all sprites. add() the player, the enemies and bullets to the Groups:
enemies = pygame.sprite.Group()
bullets = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
for i in range (8):
e = Enemy()
enemies.add(e)
all_sprites.add(e)
Draw the Sprites in the all_sprites Group with pygame.sprite.Group.draw. Remove a Sprite (form all Groups) with kill:
while running:
# [...]
for bullet in bullets:
if 0 < bullet.rect.y < 500:
bullet.rect.y -= bullet.vel
else:
bullet.kill()
# [...]
all_sprites.draw(SCREEN)
Use the keyboard event instead of pygame.key.get_pressed() to fire a bullet. See How do I stop more than 1 bullet firing at once?:
The collision of the enemies and bullets can be detected with pygame.sprite.groupcollide(). When the doKill arguments are set True, the sprites will be automatically removed:
pygame.sprite.groupcollide(bullets, enemies, True, True)
Complete example:
import pygame, os, random
pygame.init()
FPS=60
SCREEN = pygame.display.set_mode((400,500))
pygame.display.set_caption('caption')
x=50
y=450
vel = 3
width = 20
height = 20
class Player(pygame.sprite.Sprite):
def __init__(self,x,y,width,height):
super().__init__()
self.vel = 3
self.image = pygame.Surface((width, height))
self.image.fill((0,0,0))
self.rect = self.image.get_rect(topleft = (x, y))
class B(pygame.sprite.Sprite):
def __init__(self,x,y,radius, color):
super().__init__()
self.x = x
self.y = y
self.color = color
self.radius = radius
self.vel = vel
self.image = pygame.Surface((self.radius * 2, self.radius * 2), pygame.SRCALPHA)
pygame.draw.circle(self.image, self.color, (self.radius, self.radius), self.radius)
self.rect = self.image.get_rect(center = (self.x, self.y))
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((20,20))
self.image.fill((255, 0, 0))
y = random.randrange (0, 480)
x = 400
self.rect = self.image.get_rect(topleft = (x, y))
self.speed = random.randrange(1,3)
player = Player(x, y, width, height)
enemies = pygame.sprite.Group()
bullets = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
# Main loop
running = True
clock = pygame.time.Clock()
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and len(bullets) < 5:
bullet = B(player.rect.centerx, player.rect.centery, 3, (0,0,0))
bullets.add(bullet)
all_sprites.add(bullet)
if len(enemies) < 8:
e = Enemy()
enemies.add(e)
all_sprites.add(e)
for bullet in bullets:
if bullet.rect.right < 500:
bullet.rect.x += bullet.vel
else:
bullet.kill()
for enemy in enemies:
if enemy.rect.right > 0:
enemy.rect.x -= enemy.speed
else:
enemy.kill()
pygame.sprite.groupcollide(bullets, enemies, True, True)
keys = pygame.key.get_pressed()
if keys[pygame.K_w] and player.rect.top > player.vel:
player.rect.y -= player.vel
if keys[pygame.K_s] and player.rect.bottom < 500 - player.vel:
player.rect.y += player.vel
SCREEN.fill((190, 232, 220))
all_sprites.draw(SCREEN)
pygame.display.update()
pygame.quit()
Per the documentation:
"When subclassing the Sprite, be sure to call the base initializer before adding the Sprite to Groups."
So the first two lines of Enemy __init__() should be:
def __init__(self):
pygame.sprite.Sprite.__init__(self)
You also need to set a rect for the enemy:
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
Related
This question already has answers here:
How can i shoot a bullet with space bar?
(1 answer)
How do I stop more than 1 bullet firing at once?
(1 answer)
Closed 10 months ago.
Im continuing practicing in pygame, and now the problem is that collisions between player and enemy dont work and player doesnt shoot. I watched at least 5 or 6 guides, googled, but it just doesnt work in my case. Game works even after player and enemy collide, and shoot when i shoot nothing happens.
import pygame, random
pygame.init()
pygame.font.init()
width, height = 924, 500
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Priest Beast')
clock = pygame.time.Clock()
BG = pygame.transform.scale2x(pygame.image.load('art/background.png')).convert_alpha()
music = pygame.mixer.Sound('sound/music.mp3')
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.transform.scale2x(pygame.image.load('art/Player.png')).convert_alpha()
self.x = x
self.y = y
self.rect = self.image.get_rect(center = (800, 300))
def move(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
self.rect.x -= 3
if keys[pygame.K_d]:
self.rect.x += 3
if self.rect.x >= 810:
self.rect.x = 810
if self.rect.x <= -30:
self.rect.x = -30
if keys[pygame.K_SPACE]:
self.shoot
def shoot(self):
bullet = Bullet(self.x, self.y)
bullets.add(bullet)
def update(self):
self.move()
self.shoot()
class Enemy(pygame.sprite.Sprite):
def __init__(self,x,y):
super().__init__()
self.image = pygame.transform.scale2x(pygame.image.load('art/Enemy.png'))
self.image.convert_alpha()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def move(self):
self.rect.x += 3
if self.rect.x >= 900:
self.kill
def update(self):
self.move()
class Bullet(pygame.sprite.Sprite):
def __init__(self,x,y):
super().__init__()
self.image = pygame.image.load("art/bullet.png").convert_alpha()
self.rect = self.image.get_rect()
self.x = x
self.y = y
self.speed = -10
def update(self):
self.rect.x -= self.speed
if self.rect.x <= -100:
self.kill()
player = pygame.sprite.GroupSingle(Player(800,200))
enemy_list = pygame.sprite.Group()
obstacle_timer = pygame.USEREVENT + 1
timer = pygame.time.set_timer(obstacle_timer,4000)
bullets = pygame.sprite.Group()
hit = pygame.sprite.groupcollide(player, enemy_list, False, False)
bullethit = pygame.sprite.groupcollide(bullets, enemy_list, False, False)
#Loop and exit
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == obstacle_timer:
enemy_list.add(Enemy(random.randint(-1000, -30), 210))
if event.type == hit:
running = False
if event.type == bullethit:
print("hit!")
# Sounds
#music.play()
#music.set_volume(0.1)
screen.blit(BG, (0, 0))
enemy_list.draw(screen)
enemy_list.update()
bullets.update()
player.draw(screen)
player.update()
pygame.display.update()
clock.tick(60)
For some reason, all my enemies are slowing down after they collide with the bullet. Why is this occurring? I have attached a GIF below. This game is incomplete and I am fairly new to pygame. Give any advice as needed. I made a previous post with a different, please reply to that as well if possible.
Attached GIF
import pygame, sys, random
from pygame.locals import *
pygame.init()
screen_height = 870
screen_width = 1530
screen = pygame.display.set_mode((screen_width, screen_height))
fpsfunc = pygame.time.Clock()
enemy_speed = 6
enemy_motion = 1
SPAWNENEMY = USEREVENT + 1
SPAWNEASY = USEREVENT + 2
SPAWNMED = USEREVENT + 3
SPAWNHARD = USEREVENT + 4
pygame.time.set_timer(SPAWNENEMY, 1000)
cenx = screen_width / 2
ceny = screen_height / 2
gen1 = [cenx-200,ceny-200,cenx-100,ceny-100,cenx,ceny,cenx+100,ceny+100,cenx+200,ceny+200]
gen2 = []
gen3 = []
choices = [gen1]
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.surf = pygame.Surface((50, 50))
self.surf.fill((255, 0, 0))
self.rect = self.surf.get_rect(center=(screen_width / 2,
screen_height - 100))
def update(self, pressed_keys):
if pressed_keys[K_d]:
self.rect.move_ip(3, 0)
if pressed_keys[K_a]:
self.rect.move_ip(-3, 0)
if pressed_keys[K_w]:
self.rect.move_ip(0, -5)
if pressed_keys[K_s]:
self.rect.move_ip(0, 2)
if self.rect.left <= 0:
self.rect.left = 0
if self.rect.top <= 0:
self.rect.top = 0
if pressed_keys[K_SPACE]:
bullet_sprites.add(player.create_bullet())
def create_bullet(self):
return PlayerBullet(self.rect.x + 25, self.rect.y)
class PlayerBullet(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y):
super().__init__()
self.image = pygame.Surface((10, 30))
self.image.fill((0, 255, 255))
self.rect = self.image.get_rect(center=(pos_x, pos_y))
def update(self):
self.rect.y -= 5
if self.rect.y + 30 < 0:
self.kill()
class Enemy(pygame.sprite.Sprite):
def __init__(self, cenx, ceny):
super(Enemy, self).__init__()
self.image = pygame.Surface((35,35))
self.image.fill((0,0,255))
self.rect = self.image.get_rect(center = (cenx, ceny))
def update(self):
global enemy_motion, enemy_speed, cycle
if pygame.sprite.spritecollide(self, bullet_sprites, True):
self.kill()
for enemy in enemy_sprites:
if enemy not in enemy_dir_data:
enemy_dir_data[enemy] = 1
if enemy.rect.right >= screen_width:
enemy_dir_data[enemy] = -1
if enemy.rect.left <= 0:
enemy_dir_data[enemy] = 1
enemy.rect.x += enemy_speed * enemy_dir_data[enemy]
def createnem(pos1, pos2):
return Enemy(pos1, pos2)
player = Player()
bullet_sprites = pygame.sprite.Group()
enemy_sprites = pygame.sprite.Group()
enemy_dir_data = {}
start_ticks=pygame.time.get_ticks()
while True:
seconds=(pygame.time.get_ticks()-start_ticks)/1000
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
bullet_sprites.add(player.create_bullet())
#print(seconds)
if seconds >= 10:
enemy_sprites.empty()
if len(enemy_sprites) == 0:
selected = random.choice(choices)
for create in range(0,len(selected),2):
x = create
y = create + 1
print(selected[x],selected[y])
enemy_sprites.add(createnem(gen1[x], gen1[y]))
enemy_dir_data = {}
start_ticks=pygame.time.get_ticks()
pressed_keys = pygame.key.get_pressed()
screen.fill((0, 0, 0))
screen.blit(player.surf, player.rect)
bullet_sprites.draw(screen)
enemy_sprites.draw(screen)
player.update(pressed_keys)
enemy_sprites.update()
bullet_sprites.update()
pygame.display.update()
fpsfunc.tick(60)
The speed of your enemies depends on the number of enemies because of the for loop in Enemy.update. update is called once for each enemy in the Group. Because of the for loop each enemy is moved multiple times per frame.
Read about Method Objects and move just the "self" instance object in update:
class Enemy(pygame.sprite.Sprite):
# [...]
def update(self):
global enemy_motion, enemy_speed, cycle
if pygame.sprite.spritecollide(self, bullet_sprites, True):
self.kill()
if self not in enemy_dir_data:
enemy_dir_data[self] = 1
if self.rect.right >= screen_width:
enemy_dir_data[self] = -1
if self.rect.left <= 0:
enemy_dir_data[self] = 1
self.rect.x += enemy_speed * enemy_dir_data[self]
pygame.sprite.Group.draw() and pygame.sprite.Group.update() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update mehtod of the contained pygame.sprite.Sprites - you have to implement the method. See pygame.sprite.Group.update():
Calls the update() method on all Sprites in the Group [...]
The later uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects - you have to ensure that the pygame.sprite.Sprites have the required attributes. See pygame.sprite.Group.draw():
Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]
You don't need the dictionary enemy_dir_data at all. Instead add an attribute enemy_dir to the Enemy class:
class Enemy(pygame.sprite.Sprite):
def __init__(self, cenx, ceny):
super(Enemy, self).__init__()
self.image = pygame.Surface((35,35))
self.image.fill((0,0,255))
self.rect = self.image.get_rect(center = (cenx, ceny))
self.enemy_dir = 1
def update(self):
global enemy_motion, enemy_speed, cycle
if pygame.sprite.spritecollide(self, bullet_sprites, True):
self.kill()
if self.rect.right >= screen_width:
self.enemy_dir = -1
if self.rect.left <= 0:
self.enemy_dir = 1
self.rect.x += enemy_speed * self.enemy_dir
Try:
pygame.sprite.Sprite.kill(self)
Instead of self.kill
In my game the problem is that bullets are coming only from one place i.e, from the center. As my player rotates in direction of cursor, I want the bullets to be shot from top of the player even if the player is rotated and travel in a straight line in the direction player is facing towards, As the player rotates in the direction of cursor.
As you can view here the the bullets are always in same direction and always come out of same place.
I tried to use getpos() method to get cursor position and tried to subtract from the player coordinates but failed to get the result.
I think the problem is within the def shoot(self) method of Rotator class, I need to get the coordinates spaceship's tip even when it is rotating all time.
import math
import random
import os
import pygame as pg
import sys
pg.init()
height=650
width=1200
os_x = 100
os_y = 45
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (os_x,os_y)
screen = pg.display.set_mode((width,height),pg.NOFRAME)
screen_rect = screen.get_rect()
background=pg.image.load('background.png').convert()
background = pg.transform.smoothscale(pg.image.load('background.png'), (width,height))
clock = pg.time.Clock()
running = True
class Mob(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.image.load('enemy.png').convert_alpha()
self.image = pg.transform.smoothscale(pg.image.load('enemy.png'), (33,33))
self.rect = self.image.get_rect()
self.rect.x = random.randrange(width - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
self.speedx = random.randrange(-3, 3)
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > height + 10 or self.rect.left < -25 or self.rect.right > width + 20:
self.rect.x = random.randrange(width - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
class Rotator(pg.sprite.Sprite):
def __init__(self, screen_rect):
pg.sprite.Sprite.__init__(self)
self.screen_rect = screen_rect
self.master_image = pg.image.load('spaceship.png').convert_alpha()
self.master_image = pg.transform.smoothscale(pg.image.load('spaceship.png'), (33,33))
self.image = self.master_image.copy()
self.rect = self.image.get_rect(center=[width/2,height/2])
self.delay = 10
self.timer = 0.0
self.angle = 0
self.distance = 0
self.angle_offset = 0
def get_angle(self):
mouse = pg.mouse.get_pos()
offset = (self.rect.centerx - mouse[0], self.rect.centery - mouse[1])
self.angle = math.degrees(math.atan2(*offset)) - self.angle_offset
old_center = self.rect.center
self.image = pg.transform.rotozoom(self.master_image, self.angle,1)
self.rect = self.image.get_rect(center=old_center)
self.distance = math.sqrt((offset[0] * offset[0]) + (offset[1] * offset[1]))
def update(self):
self.get_angle()
self.display = 'angle:{:.2f} distance:{:.2f}'.format(self.angle, self.distance)
self.dx = 1
self.dy = 1
self.rect.clamp_ip(self.screen_rect)
def draw(self, surf):
surf.blit(self.image, self.rect)
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.centery)
all_sprites.add(bullet)
bullets.add(bullet)
class Bullet(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.image.load('bullet.png').convert_alpha()
self.image = pg.transform.smoothscale(pg.image.load('bullet.png'), (10,10))
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.speedy = -8
def update(self):
self.rect.y += self.speedy
# kill if it moves off the top of the screen
if self.rect.bottom < 0:
self.kill()
all_sprites = pg.sprite.Group()
bullets = pg.sprite.Group()
mobs = pg.sprite.Group()
rotator = Rotator(screen_rect)
all_sprites.add(rotator)
for i in range(5):
m = Mob()
all_sprites.add(m)
mobs.add(m)
while running:
keys = pg.key.get_pressed()
for event in pg.event.get():
if event.type == pg.QUIT:
sys.exit()
pygame.quit()
if event.type == pg.MOUSEBUTTONDOWN:
rotator.shoot()
screen.blit(background, [0, 0])
all_sprites.update()
hits = pg.sprite.groupcollide(mobs, bullets, True, True)
for hit in hits:
m = Mob()
all_sprites.add(m)
mobs.add(m)
hits = pg.sprite.spritecollide(rotator, mobs, False)
if hits:
running = False
all_sprites.draw(screen)
clock.tick(60)
pg.display.update()
See Shooting a bullet in pygame in the direction of mouse and calculating direction of the player to shoot pygame.
Pass the mouse position to rotator.shoot(), when the mouse button is pressed:
if event.type == pg.MOUSEBUTTONDOWN:
rotator.shoot(event.pos)
Calculate the direction of from the rotator to the mouse position and pass it the constructor of the new bullet object:
def shoot(self, mousepos):
dx = mousepos[0] - self.rect.centerx
dy = mousepos[1] - self.rect.centery
if abs(dx) > 0 or abs(dy) > 0:
bullet = Bullet(self.rect.centerx, self.rect.centery, dx, dy)
all_sprites.add(bullet)
bullets.add(bullet)
Use pygame.math.Vector2 to store the current positon of the bullet and the normalized direction of the bullet (Unit vector):
class Bullet(pg.sprite.Sprite):
def __init__(self, x, y, dx, dy):
pg.sprite.Sprite.__init__(self)
self.image = pg.transform.smoothscale(pg.image.load('bullet.png').convert_alpha(), (10,10))
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.speed = 8
self.pos = pg.math.Vector2(x, y)
self.dir = pg.math.Vector2(dx, dy).normalize()
Calcualate the new position of the bullet in update() (self.pos += self.dir * self.speed) and update the .rect attribute by the new position.
.kill() the bullet when it leaves the screen. This can be checked by self.rect.colliderect():
class Bullet(pg.sprite.Sprite):
# [...]
def update(self):
self.pos += self.dir * self.speed
self.rect.center = (round(self.pos.x), round(self.pos.y))
if not self.rect.colliderect(0, 0, width, height):
self.kill()
Hello I am new to pygame and I am trying to write a shmup game.
However I am always having this error:
TypeError: add() argument after * must be an iterable, not int
self.add(*group)
This is the traceback of the error:
File "C:/Users/Pygame/game.py", line 195, in
player.shoot()
File "C:/Users/Pygame/game.py", line 78, in shoot
bullet = Bullets(self.rect.center,self.angle)
File "C:/Users/Pygame/game.py", line 124, in init
super(Bullets,self).init(pos,angle)
This is the code I have written so far, it works well however when the user wants to shoot the error is being raised.
import os
import pygame
import random
import math
WIDTH = 480
HEIGHT = 600
FPS = 60
#colors:
WHITE = (255,255,255)
BLACK = (0,0,0)
GREEN = (0,250,0)
RED = (255,0,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
#setup assets
game_folder = os.path.dirname("C:/Users/PygameP/")
img_folder = os.path.join(game_folder,"img")
#intialise pygame
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH,HEIGHT))
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((50,40))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH/2
self.rect.bottom = HEIGHT-10
#controls the speed
self.angle = 0
self.orig_image = self.image
#self.rect = self.image.get_rect(center=pos)
def update(self):
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.angle -= 5
self.rotate()
if keystate[pygame.K_RIGHT]:
self.angle += 5
self.rotate()
def rotate(self):
self.image = pygame.transform.rotozoom(self.orig_image, self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)
def shoot(self):
bullet = Bullets(self.rect.center,self.angle)
all_sprites.add(bullet)
bullets.add(bullet)
class Mob(pygame.sprite.Sprite):
def __init__(self):
super(Mob,self).__init__()
self.image = pygame.Surface((30,40))
self.image = meteor_img
self.image = pygame.transform.scale(meteor_img,(50,38))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = int(self.rect.width/2)
self.rect.x = random.randrange(0,WIDTH - self.rect.width)
self.rect.y = random.randrange(-100,-40)
self.speedy = random.randrange(1,8)
#updating the position of the sprite
def update(self):
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10:
self.rect.x = random.randrange(0,WIDTH - self.rect.width)
self.rect.y = random.randrange(-100,-40)
self.speedy = random.randrange(1,8)
class Bullets(pygame.sprite.Sprite):
def __init__(self,pos,angle):
super(Bullets,self).__init__(pos,angle)
# Rotate the image.
self.image = pygame.Surface((10,20))
self.image = bullet_img
self.image = pygame.transform.scale(bullet_img,(50,38))
self.image = pygame.transform.rotate(bullet_img, angle)
self.rect = self.image.get_rect()
speed = 5
self.velocity_x = math.cos(math.radians(-angle))*speed
self.velocity_y = math.sin(math.radians(-angle))*speed
#store the actual position
self.pos = list(pos)
def update(self):
self.pos[0] += self.velocity_x
self.pos[1] += self.velocity_y
self.rect.center = self.pos
if self.rect.bottom <0:
self.kill()
#load all game graphics
background = pygame.image.load(os.path.join(img_folder,"background.png")).convert()
background_rect = background.get_rect()
player_img = pygame.image.load(os.path.join(img_folder,"arrow.png")).convert()
bullet_img = pygame.image.load(os.path.join(img_folder,"bullet.png")).convert()
meteor_img = pygame.image.load(os.path.join(img_folder,"m.png")).convert()
#creating a group to store sprites to make it easier to deal with them
#every sprite we make goes to this group
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
bullets = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(8):
m = Mob()
all_sprites.add(m)
mobs.add(m)
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shoot()
#Update
all_sprites.update()
#checking if a bullet hits a mob
hits = pygame.sprite.groupcollide(mobs,bullets,True,True)
for hit in hits:
m = Mob()
all_sprites.add(m)
mobs.add(m)
hits = pygame.sprite.spritecollide(player,mobs, False,pygame.sprite.collide_circle)
#drawing the new sprites here
screen.fill(BLACK)
#show the background image
screen.blit(background,background_rect)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
Any comments?
You're passing the pos and the angle to the __init__ method of pygame.sprite.Sprite here,
super(Bullets,self).__init__(pos,angle)
but you can only pass sprite groups to which this sprite instance will be added. So just remove those arguments:
super(Bullets,self).__init__()
Basically the rocket moves up and down, stops when it reaches the top or bottom and recognizes that the spacebar is being pressed. However the bullet won't shoot from the ship. I'm new to python and pygame. Anyways here is the code, thank you for any help!:
import pygame
import sys
from pygame.locals import*
bg_color = (0, 191, 255)
d_w = 1200
d_h= 800
class Rocket(object):
def __init__(self):
self.image = pygame.image.load('Rocket.bmp')
self.x = 0
self.y = d_h/2
def handle_keys(self):
key = pygame.key.get_pressed()
dist = 6.5
if key[pygame.K_UP]:
if self.y > 0:
self.y -= dist
elif key[pygame.K_DOWN]:
if self.y < 775:
self.y += dist
elif key[pygame.K_SPACE]:
Bullet.update(Bullet)
def draw(self, surface):
surface.blit(self.image, (self.x, self.y))
class Bullet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([2, 5])
self.image.fill(0, 0, 0)
self.rect = self.image.get_rect()
def update(self):
""" Move the bullet. """
self.image = pygame.Surface([2, 5])
self.image.fill((0, 0, 0))
self.rect = self.image.get_rect()
self.rect.x += 3
pygame.init()
screen = pygame.display.set_mode((d_w, d_h))
pygame.display.set_caption("Game Character")
Mario = pygame.image.load('Mario_Sprite.bmp')
rocket = Rocket()
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
rocket.handle_keys()
screen.fill(bg_color)
rocket.draw(screen)
pygame.display.update()
clock.tick(72)
Bullet.update(Bullet)
You're calling update statically. You need to create an instance of the class and then update that instance, as in:
bullet = Bullet()
...
bullet.update()