Pygame: Problems with Shooting in Space Invaders

Space Invaders - Pygame - Make enemy shoot

The problem is here:

    elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shootPlayer()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_TAB:
enemy.shootEnemy()

Once event.type == KEYDOWN one time, the second evaluation is ignored.

Try this

    elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shootPlayer()
elif event.key == pygame.K_TAB:
enemy.shootEnemy()

This checks for a KEYDOWN event, then for the specific key that's pressed.

Bullets Not Appearing in Simple Space Invader Game

I believe that you need to update your screen at the end of the while-loop, not at the beginning:

while True:
#fill screen
for event in pygame.event.get():
#get user input

pygame.display().flip()

Pygame - Enemy shoot, problem with groups

You can get a list of the Sprties in a pygame.sprite.Group with the method sprites(). The sprites in the list cam be accessed by subscription.

If bosss contains exactly 1 Sprite, you can get the rect attribute of the Sprite with:

rect = bosss.sprites()[0].rect

How can i shoot a bullet with space bar?

The general approach to firing bullets is to store the positions of the bullets in a list (bullet_list). When a bullet is fired, add the bullet's starting position ([start_x, start_y]) to the list. The starting position is the position of the object (player or enemy) that fires the bullet. Use a for-loop to iterate through all the bullets in the list. Move position of each individual bullet in the loop. Remove a bullet from the list that leaves the screen (bullet_list.remove(bullet_pos)). For this reason, a copy of the list (bullet_list[:]) must be run through (see How to remove items from a list while iterating?). Use another for-loop to blit the remaining bullets on the screen:

bullet_list = []

while run == True:
# [...]

for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False

if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullet_list.append([start_x, start_y])

for bullet_pos in bullet_list[:]:
bullet_pos[0] += move_bullet_x
bullet_pos[1] += move_bullet_y
if not screen.get_rect().colliderect(bullet_image.get_rect(center = bullet_pos))
bullet_list.remove(bullet_pos)

# [...]

for bullet_pos in bullet_list[:]
screen.blit(bullet_image, bullet_image.get_rect(center = bullet_pos))

# [...]

See also Shoot bullet.


Please note, that class names should normally use the CapWords convention.
(See Style Guide for Python Code - Class names)

That means it has to be Player and Bullet rather than player and bullet

You have an application loop, so use it. All the objects are continuously updated and drawn in the main application loop, in each frame.

The class Bullet do not need any loop. The constructor has to have parameters for the position (x, y). Further it needs on method which changes the position and one which draws the bullet:

class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y

def update(self):
self.y -= self.speed#

def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)

Use a list of bullets. Create a new bullet when space is pressed. Move the bullets (update) in every frame an remove a bullet if it is out of the window. Draw the remaining bullets in every frame:

bullets = []

# [...]
while run:

for event in pygame.event.get():
# [...]
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))

# [...]
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)

# [...]
for b in bullets:
b.draw()

Furthermore use pygame.key.get_pressed() use to get the state of the keys in every frame and to update the position of the player:

while run:

# [...]

keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()

Complete example:

Sample Image

import pygame, os

os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()

win = pygame.display
d = win.set_mode((1200, 600))
clock = pygame.time.Clock()

class Player:
def __init__(self, x, y, height, width):
self.x = x
self.y = y
self.height = height
self.width = width
self.speed = 2

def draw(self):
pygame.draw.rect(d, (0, 0, 0), (self.x, self.y, self.width, self.height))

def move_left(self):
self.x -= self.speed

def move_right(self):
self.x += self.speed

class Bullet:
def __init__(self, x, y):
self.radius = 10
self.speed = 10
self.x = x
self.y = y

def update(self):
self.y -= self.speed#

def draw(self):
pygame.draw.circle(d, (255, 0, 0), (self.x, self.y), self.radius)

bullets = []
p = Player(600, 500, 50, 30)

run = True
while run:
clock.tick(100)

# handel events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bullets.append(Bullet(p.x+p.width//2, p.y))

# update objects
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
p.move_left()
if keys[pygame.K_RIGHT]:
p.move_right()
for b in bullets:
b.update()
if b.y < 0:
bullets.remove(b)

# clear display
d.fill((98, 98, 98))

# draw scene
for b in bullets:
b.draw()
p.draw()

# update display
win.update()

Python Pygame: Fire multiple bullets for Space Invader game

You should separate your game into a loop that contains 3 different functions:

LOOP
UPDATE_LOGIC
INPUT_HANDLING
DRAW_ELEMENTS
END-LOOP

In the input_handling, put a bullet into a list of bullets if the player is not in cool-down.

In the update_logic, iterate of the bullet list calculating the positions through time, and cool-down time of the player.

In the draw_elements, simply draw every thing on your scene. (iterate over the bullet list)

and you can use different timers for the draw and update_logic. That way will help you to add new elements to your game easily



Related Topics



Leave a reply



Submit