I'm doing the alien invasion game and my bullets are just appearing and disappearing. I checked my code many times and I don't know why it is not traveling up the screen. can someone please help me. I don't want to try another method I want to learn by seeing the flaws in my code so I don't repeat the same mistakes again
import sys
import pygame
pygame.init()
# Setting up a window
screen = pygame.display.set_mode((1200, 800))
screen_rect = screen.get_rect()
# Caption
pygame.display.set_caption("space shooter".title())
# Setting up the icon
icon = pygame.image.load("undertake.png").convert_alpha()
pygame.display.set_icon(icon)
# Identifying a Background
bg = pygame.image.load("bg.png").convert_alpha()
# Adding the jet
jet = pygame.image.load("jet.png").convert_alpha()
jet_rect = jet.get_rect()
jet_rect.centerx = screen_rect.centerx
jet_rect.bottom = screen_rect.bottom
# Adding bullets to the left of the jet
bullet = pygame.image.load("pixel_laser_red.png").convert_alpha()
bullet_rect = bullet.get_rect()
bullet_state = "ready"
# Moving the jet
def move_jet(x):
jet_rect.centerx += x
# Firing the bullet
def fire_bullet(x, y):
bullet_state = "fire"
screen.blit(bullet, (x, y))
# Adding Boundaries
def boundaries():
if jet_rect.left >= 1200:
jet_rect.right = 0
elif jet_rect.right <= 0:
jet_rect.left = 1200
# Game Loop
while True:
screen.blit(bg, (0, 0))
screen.blit(jet, jet_rect)
# EVENTS
for event in pygame.event.get():
# Quitting
if event.type == pygame.QUIT:
sys.exit()
# KeyStrokes
pressed = pygame.key.get_pressed()
jet_xincrement = 0
if pressed[pygame.K_RIGHT]:
jet_xincrement += 3
if pressed[pygame.K_LEFT]:
jet_xincrement -= 3
if pressed[pygame.K_SPACE]:
bullet_x = jet_rect.centerx
bullet_y = jet_rect.top
fire_bullet(bullet_x - 28, bullet_y + 7)
if bullet_state == "fire" :
bullet_y -= 10
boundaries()
move_jet(jet_xincrement)
pygame.display.flip()
Actually the bullet is just drawn when space is pressed. You have to draw the bullet continuously in every frame.
The function fire_bullet just sets the state and the position of the bullet. The variables are in global namespace. Hence you have to use the global statement to set them:
bullet_state = "ready"
bullet_x = 0
bullet_y = 0
# Firing the bullet
def fire_bullet(x, y):
global bullet_state, bullet_x, bullet_y
bullet_state = "fire"
bullet_x = x
bullet_y = y
When space is pressed, then the fire_bullet is invoked. The arguments are the current position of the jet. When bullet_state is "fire", then the bullet has to be drawn in the main application loop:
while True:
# [...]
if pressed[pygame.K_SPACE]:
fire_bullet(jet_rect.centerx - 28, jet_rect.top + 7)
if bullet_state == "fire":
bullet_y -= 10
screen.blit(bullet, (bullet_x, bullet_y))
# [...]
Related
I have a list with all my enemies and when the distance between the players bullet and the enemy is close enough, I can make a enemy disappear but its never the right one that was hit with the bullet, its always the enemy with the greatest x value(in my case the one at the end of the list) so my questions is how do I make the specific enemy disappear. here is my code for reference.
import pygame
import random
import math
# initalize pygame
pygame.init()
# creates game screen to display game
game_window = pygame.display.set_mode((800, 570))
# Title and icon for window
pygame.display.set_caption("Power of the Doctor")
icon = pygame.image.load('tardisShooter.png')
pygame.display.set_icon(icon)
# backgroun picture
background = pygame.image.load('SpaceTardissmall.png')
# player info
Playerimg = pygame.image.load('tardisShooter.png')
playerx = 370 # players x axis
playery = 470 # players y axis
playerx_change = 0 # adds constant change while added in loop
def player(x, y):
# blit draws image on screen: x axis y axis
game_window.blit(Playerimg, (x, y))
# enemy info
Enemyimg = []
enemyx = []
enemyy = []
enemyx_change = 1
enemyy_change = 0
num_enemies = 2
enemyspawnx = 50
enemyspawny = 200
for i in range(num_enemies):
Enemyimg.append(pygame.image.load('CybermanShooter.png'))
enemyx.append(enemyspawnx) # random x axis for enemy
enemyy.append(enemyspawny) # random y axis for enemy
enemyspawnx += 70
def enemy(x, y, i):
game_window.blit(Enemyimg[i], (x, y))
# bullet info
bulletimg = pygame.image.load('torpedo32.png')
bullety = playery
bulletx = playerx
bulletstate = "idle"
bullety_change = 5
def bullet(x, y):
global bulletstate
bulletstate = "FIRE"
game_window.blit(bulletimg, (x + 15.5, y - 25))
def collision(enemyx, enemyy, bulletx, bullety):
distance = math.sqrt((math.pow(bulletx - enemyx, 2)) + (math.pow(bullety - enemyy, 2)))
if distance < 27:
return True
else:
return False
rand = random.randint(0, num_enemies)
# timer info
bulletevent = pygame.USEREVENT
pygame.time.set_timer(bulletevent, 2000)
# get a rabdom number
# when the timer hits 2 secodsn spawsn bomb at the index of the random number that corresponds witht the enemy
# enemy bomb
bombimg = []
bombx = []
bomby = []
bomby_change = 1
bombstate = "idle"
num_bombs = 2
for i in range(num_bombs):
bombimg.append(pygame.image.load('bomb.png'))
bombx.append(enemyx[i])
bomby.append(enemyy[i])
def bomb(x, y, i):
global bombstate
bombstate = "fire"
game_window.blit(bombimg[i], (x + 15, y + 65))
# player hit detection
def enemyhit(bombx, bomby, x, y):
distance2 = math.sqrt((math.pow(bombx - x, 2)) + (math.pow(bomby - (y - 50), 2)))
if distance2 < 20:
return True
else:
return False
# loop to keep screen running
Running = True
while Running:
# background color
game_window.fill((0, 0, 0))
# background image in loop
game_window.blit(background, (0, 0))
# checks anything typed while game is running
for event in pygame.event.get():
# if they click x to quit close window
if event.type == pygame.QUIT:
Running = False
if event.type == bulletevent:
if bombstate == 'idle':
bomb(bombx[rand], bomby[rand], i)
bombx[rand] = enemyx[rand]
bomby[rand] = enemyy[rand]
# means key has been pressed(not released)
if event.type == pygame.KEYDOWN:
# escape key closes game
if event.key == pygame.K_ESCAPE:
Running = False
# right key moves player 5 spaces
if event.key == pygame.K_RIGHT:
playerx_change = 5
# left key moves players back 5 spaces
if event.key == pygame.K_LEFT:
playerx_change = -5
if event.key == pygame.K_SPACE:
bulletx = playerx
if bulletstate == "idle":
bullet(bulletx, bullety)
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
playerx_change = 0
playerx += playerx_change # constantly adds user input to player model
# player bounds
if playerx >= 740:
playerx = 740
if playerx <= 0:
playerx = 0
# player fucntion draws image
player(playerx, playery)
# loops through all the items in the lists named
for i in range(num_enemies):
# draws all enemies
enemy(enemyx[i], enemyy[i], i)
enemyx[i] += enemyx_change
if enemyx[i] >= 735:
enemyx_change = -.8
enemyy[i] += 10
if enemyx[i] <= 0:
enemyx_change = .8
enemyy[i] += 10
# is state is fire
if bulletstate == "FIRE":
# draws torpepd at coordinates
bullet(bulletx, bullety)
bullety -= bullety_change # decreases y axis moving bullet
if bullety <= 0: # if goes past border
bulletstate = "idle" # ittl switch back to idle
bullety = playery # moves bullet y back to player y
for i in range(num_enemies):
collided = collision(enemyx[i], enemyy[i], bulletx, bullety)
if collided == True:
bulletstate = 'idle'
bullety = playery
Enemyimg.remove(Enemyimg[i])
num_enemies -= 1
# when enemy fires
if bombstate == 'fire':
bomb(bombx[rand], bomby[rand], i)
bomby[rand] += bomby_change
if bomby[rand] > 570:
bombstate = 'idle'
bomby[rand] = enemyy[rand]
rand = random.randint(0, 1)
# enemy bullets hit player
enemyhits = enemyhit(bombx[rand], bomby[rand], playerx, playery)
if enemyhits == True:
playerx = 370
bombstate = 'idle'
bomby[rand] = enemyy[rand]
# updates the screen in loop
pygame.display.update()
A big problem with your code is having different lists for each attribute of your enemies.
You wrote this :
Enemyimg = []
enemyx = []
enemyy = []
Meaning that you always need to sync those three lists at all time to get coherent results. Which you are not doing, when you "remove" an enemy, you just remove the img from Enemyimg and not removing its coords in enemyy and enemyx.
While you could manage to make it work with three lists, you are just overcomplicating things. Let me show you what you may want to do to make your life way easier :)
I'm going to assume, you don't know about OOP (Object Oriented Programming) yet ? I Would be a great time to use it but it can be a little complexe if you are just starting out with programming.
So let's introduce python's dict !
What you really want to do is have one single list :
enemies = []
But how to store everything in one list you might wonder ?
Well, it will be a list of dict. A dict looks something like that :
example = {'image': pygame.image.load('CybermanShooter.png'), 'x': enemyspawnx, 'y': enemyspawny}
(Note that if you always use the same image, you don't need to put it here, you can just draw your image at the position)
Now if you do something like :
print(example['x'])
It will print your enemy's x value.
So, to sum up :
You want to have one single list : enemies = []
To add an enemy you will do :
enemies.append({'image': pygame.image.load('CybermanShooter.png'), 'x': enemyspawnx, 'y': enemyspawny})
To detect your collisions :
# Your collision function
def collision(enemy, bulletx, bullety):
distance = math.sqrt((math.pow(bulletx - enemy['x'], 2)) + (math.pow(bullety - enemy['y'], 2)))
if distance < 27:
return True
return False
# Your loop (in 2 steps: 1 - find enemies to remove, 2 - actually remove them)
enemies_to_remove = []
for enemy in enemies :
if collision(enemy, bulletx, bullety):
bulletstate = 'idle'
bullety = playery
enemies_to_remove.append(enemy)
num_enemies -= 1
for enemy in enemies_to_remove:
enemies.remove(enemy)
To draw your enemies:
# Your draw_enemy function (which you called `enemy(...)` for some reason)
def draw_enemy(enemy):
game_window.blit(enemy['image'], (enemy['x'], enemy['y']))
# Inside the main loop
for enemy in enemies:
draw_enemy(enemy)
To update the position of enemies:
# Make a move_enemy function
def move_enemy(enemy):
# put your moving logic here
# Inside the main loop:
for enemy in enemies:
move_enemy(enemy)
Do you get the principle ?
I've tried to stay as close as your original code as possible so it's not too many information to take in at once.
But technically you should apply the same principle for your bullets and to some extend to your player.
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 1 year ago.
import pygame
# initialize the pygame
pygame.init()
# create the screen
screen = pygame.display.set_mode((800, 600))
# Title and icon
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load('Invader2.xcf')
pygame.display.set_icon(icon)
# Player
playerImg = pygame.image.load('Player.xcf')
player_big = pygame.transform.scale(playerImg, (48, 48))
playerX = 370
playerY = 480
vel = 0.15
# Player Bullets
playerBulletImg = pygame.image.load('Player_bullet.xcf')
playerBulletX = playerX + 16
playerBulletY = playerY + 10
bulletVel = 0.3
def player(x, y):
screen.blit(player_big, (playerX, playerY))
def bullet(x, y):
screen.blit(playerBulletImg, (playerBulletX, playerBulletY))
# Game Loop
running = True
while running:
# RGB
screen.fill((18.8, 83.5, 78.4))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and playerX > 0:
playerX -= vel
playerBulletX -= vel
if keys[pygame.K_RIGHT] and playerX < 800 - 48:
playerX += vel
playerBulletX += vel
if keys[pygame.K_SPACE]:
playerBulletY -= 0.5
if playerBulletY == 0:
playerBulletY = 480
bullet(playerBulletX, playerBulletY)
player(playerX, playerY)
pygame.display.update()
Hi! I'm a beginner who has just started using Pygame. I'm making a Space Invaders / Galaga type game. When I press the space bar, the bullet goes up the y-axis, but only when I hold it down. I want the bullet to continue to move up the screen, even when I'm not holding down the space bar. Also, another problem is that when the bullet is in the air it still follows the x-value for the player. So when the bullet shoots up, It moves around depending on where the player is.
you should run your game as a class it is much more easier to code pygame with classes you can change your b.move to where else
import pygame
# initialize the pygame
pygame.init()
# create the screen
screen = pygame.display.set_mode((800, 600))
# Title and icon
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load('Invader2.xcf')
pygame.display.set_icon(icon)
# Player
class Player:
def __init__(self):
self.Img = pygame.image.load('Player.xcf')
self.big = pygame.transform.scale(playerImg, (48, 48))
self.x = 370
self.y = 480
self.vel = 0.15
def draw(self,screen):
screen.blit(self.big, (self.x, self.y))
class Bullet:
def __init__(self):
self.Img = pygame.image.load('Player_bullet.xcf')
self.x = playerX + 16
self.y = playerY + 10
self.vel = 0.3
def draw(screen):
screen.blit(self.Img, (self.y, self.y))
def move():
self.y -= self.vel
def draw(p,b):
p.draw()
for i in b:
i.draw()
# Game Loop
def main():
running = True
p = Player()
b = []
while running:
screen.fill((18.8, 83.5, 78.4))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and p.x > 0:
p.x -= p.vel
if keys[pygame.K_RIGHT] and p.x < 800 - 48:
p.x += p.vel
if keys[pygame.K_SPACE]:
b.append(Bullet())
draw(p,b)
for bullet in b:
bullet.move()
pygame.display.update()
Use the keyboard event instead of pygame.key.get_pressed() to shoot a bullet.
pygame.key.get_pressed() returns a sequence with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement.
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action.
Add a shootBullet variable that indicates when the bullet will be fired. Set the state when SPACE is pressed. Move and draw the bullet depending on this state. Set the starting position of the bullet when the bullet is fired.
shootBullet = False
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
shootBullet = True
playerBulletX = playerX
playerBulletY = 480
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and playerX > 0:
playerX -= vel
if keys[pygame.K_RIGHT] and playerX < 800 - 48:
playerX += vel
if shootBullet:
playerBulletY -= 1
if playerBulletY <= 0:
shoot_bullet = False
screen.fill((18.8, 83.5, 78.4))
if shootBullet:
bullet(playerBulletX, playerBulletY)
player(playerX, playerY)
pygame.display.update()
Use pygame.time.Clock to control the frames per second and thus the game speed.
The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time. See pygame.time.Clock.tick():
This method should be called once per frame.
That means that the loop:
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
runs 100 times per second.
This is the code of a survive the horde type game I'm working on. I have been facing an issue where the alien(s) sometimes (enemy in code) randomly spawns at the bottom of the surface, even though I have specified their spawn location to be randomized (within a certain part of the surface).
What has made them spawn at the bottom of the surface, where they cannot be touched by bullets?
import pygame
import random
import math
# for initialising pygame (req for every pygame app)
pygame.init()
# making the basic window (dimensions must be written inside a tuple )
screen = pygame.display.set_mode((500, 500))
# background
background = pygame.image.load('C:/Users/aryan/Downloads/background.jpg')
# load and set the logo
logo = pygame.image.load('C:/Users/aryan/Downloads/bp.png') # directory of logo
pygame.display.set_icon(logo)
pygame.display.set_caption("space wars") # program name
# define a variable to control the main loop
running = True
# player
playerimg = pygame.image.load('C:/Users/aryan/Downloads/spaceship.png')
playerX = 218 # x and y coordinates of image
playerY = 350
playerxchange = 0 # this will be the change in movement in x direction of our image
playerychange = 0 # this will be the change in movement in y direction of our image
def player(x, y):
screen.blit(playerimg, (x, y)) # blit draws our image on the surface(basically the background)
# syntax for blit(imagename, (xcoordinate,ycoordinate))
class Enemy:
def __init__(self):
self.x = random.randint(0, 476)
self.y = random.randint(0, 300)
self.moveX = 0.2
self.moveY = 40
def move(self):
self.x += self.moveX
if self.y >= 476:
self.y = 476
self.moveY = 0
self.moveX = 0
if self.x <= 0:
self.moveX = 0.1
self.y += self.moveY
elif self.x >= 465:
self.moveX = -0.1
self.y += self.moveY
def draw(self):
screen.blit(enemyimg, (self.x, self.y))
# enemy
enemyimg = pygame.image.load('C:/Users/aryan/Downloads/enemy.png')
enemy_list = []
for i in range(5):
new_enemy = Enemy()
enemy_list.append(new_enemy)
# game over
overimg = pygame.image.load('C:/Users/aryan/Downloads/gameover.png')
# bullet
bulletimg = pygame.image.load('C:/Users/aryan/Downloads/bullet.png')
bulletX = 0
bulletY = 350
bulletxchange = 0
bulletychange = 1
bullet_state = "ready" # "ready" you cant see bullet on screen
# "fire" you can see bullet firing
bullets = [] # bullets is a list that contains the coordinates of every bullet
score = 0
font30 = pygame.font.SysFont(None, 30)
#class
# Functions
def enemy(x, y):
screen.blit(enemyimg, (x, y)) # blit draws our image on the surface(basically the background)
# syntax for blit(imagename, (xcoordinate,ycoordinate))
def firebullet(x, y):
global bullet_state
bullet_state = "ready"
bullets.append([x + 12, y + 6]) # Creating a new bullet
def iscollision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt(math.pow(enemyX-bulletX, 2)+ math.pow(enemyY-bulletY,2)) # distance formula
if distance <= 20:
return True
else:
return False
def TextScore(game):
text2 = font30.render("Your Score is: " + str(game), True, (37, 97, 188))
screen.blit(text2, (10, 45))
# main loop
while running:
screen.fill((120, 120, 120)) # in order (r, g, b) . (0, 0, 0) is black (255, 0, 0) is red...
screen.blit(background, (0, 0))
# event handling, gets all event from the event queue
for event in pygame.event.get():
# only do something if the event is of type QUIT
if event.type == pygame.QUIT:
# change the value to False, to exit the main loop
running = False
# checking keystroke
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
playerxchange += 0.3 # change in movement will be 0.2 towards the right
if event.key == pygame.K_LEFT:
playerxchange -= 0.3 # change in movement will be 0.2 towards the right
if event.key == pygame.K_UP:
playerychange -= 0.3
if event.key == pygame.K_DOWN:
playerychange += 0.3
if event.key == pygame.K_SPACE:
bullet_state = "fire"
firebullet(playerX, playerY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_DOWN or event.key == pygame.K_UP:
playerxchange = 0
playerychange = 0
playerY += playerychange
playerX += playerxchange # the value of playerx changes by +- 0.1 depending on keystroke
if playerX <= -64: # this teleports the spaceship from left end to right end
playerX = 564
elif playerX >= 564: # this teleports spaceship from right end to left
playerX = -64
if playerY >= 436: # this prevents spaceship from leaving vertically
playerY = 436
if playerY <= 0:
playerY = 0
# enemy movement
for enemy in enemy_list:
enemy.move()
# bullet movement
if bullet_state == "fire":
firebullet(playerX, playerY)
for bullet in bullets:
screen.blit(bulletimg, (bullet[0], bullet[1])) # Print a bullet
bullet[0] -= bulletxchange # Updates its position
bullet[1] -= bulletychange
if bullet[1] < 0:
bullets.remove(bullet)
# collision
for enemy in enemy_list:
for bullet in bullets: # Use a for-loop to iterate through all the bullets in the list.
collision = iscollision(enemy.x, enemy.y, bullet[0], bullet[1])
if collision: # Test if a single bullet collides with the enemy inside the loop.
score += 1
print(score)
bullets.remove(bullet) # Remove the bullet from the list when it collides with the enemy.
enemy.x = random.randint(0, 476) # if collision takes place, alien respawns
enemy.y = random.randint(0, 30)
TextScore(score)
player(playerX, playerY) # player method is called AFTER screen.fill otherwise the screen will fill after image has been blitted
for enemy in enemy_list: # new edit
enemy.draw()
pygame.display.update() # necessary for events to keep updating
The problem is that you are generating number out out of bounds defined in the move method of Enemy class. Specifically, the problem is with x for which the upper bound seems to be 465, but you are generating numbers up to 476.
I obviously can't test this, but replace
enemy.x = random.randint(0, 476) # if collision takes place, alien respawns
enemy.y = random.randint(0, 30)
with
enemy.x = random.randint(1, 464) # if collision takes place, alien respawns
enemy.y = random.randint(1, 30)
and the problem should go away.
After looking through your code, it seems like after a collision you set the respawn y coordinate to be between 0 and 30, which I assume is what you want. Although, your original y coordinate for spawning aliens goes from 0 to 300; this may be your issue as to why they are spawning farther down the screen?
I'm making a simple game in pygame, in which you're supposed to dodge or shoot the targets that descend through the screen. So far, I've created the ship and managed to set the movement of both the bullet and the ship, as for their key bindings. However, the bullet's x coordinate doesn't seem to change at all, even though I've defined in the init method in the bullet class that the bullet x coordinate is equal to the ship x coordinate, therefore, the bullet would always be leaving the ship's position. Instead, the bullet always leaves the middle of the screen. I can't find the issue. Any help would be very much appreciated
import pygame, sys
pygame.init()
clock = pygame.time.Clock()
screen_width = 600
screen_height = 800
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Space Race Game")
class ROCKET:
def __init__(self):
self.rocketImg = pygame.image.load("spaceship.png")
self.rocket_x = screen_width/2 - 32
self.rocket_y = screen_height/2 + 100
def draw_rocket(self):
screen.blit(self.rocketImg, (self.rocket_x, self.rocket_y))
def move_rocket(self):
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] and self.rocket_x + 15 > 0:
self.rocket_x -= 5
if key[pygame.K_RIGHT] and self.rocket_x < screen_width - 40:
self.rocket_x += 5
class BULLET(ROCKET):
def __init__(self):
super().__init__()
self.bullet_width = 10
self.bullet_height = 20
self.bullet_x = self.rocket_x + 25
self.bullet_y = self.rocket_y
self.move = [0, 0]
self.bullet_speed = 5
self.bullet_rect = pygame.Rect(self.bullet_x, self.bullet_y, self.bullet_width, self.bullet_height)
def draw_bullet(self):
key = pygame.key.get_pressed()
if key[pygame.K_SPACE]:
self.bullet_x = self.rocket_x
self.move[1] = -1
self.bullet_y += self.move[1] * self.bullet_speed
self.bullet_rect.topleft = (self.bullet_x, self.bullet_y)
if self.bullet_y < self.rocket_y - 10:
pygame.draw.rect(screen, (0, 0, 0), self.bullet_rect)
if self.bullet_y < - 20:
self.bullet_y = self.rocket_y
self.move[1] = 0
rocket = ROCKET()
bullet = BULLET()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill((255, 255, 255))
rocket.draw_rocket()
rocket.move_rocket()
bullet.draw_bullet()
pygame.display.flip()
clock.tick(60)
You have to set the x-coordinate of the bullet by the current x-coordinate of the rocket.
Add an argument rocket to the method draw_bullet of the class BULLET. Make sure that you can only fire the bullet if the bullet has not yet been fired (self.move[1] == 0). Compute the center of the rocket and set the position of the bullet (rocket.rocket_x + self.rocketImg.get_width() // 2):
class BULLET(ROCKET):
# [...]
def draw_bullet(self, rocket):
key = pygame.key.get_pressed()
if key[pygame.K_SPACE] and self.move[1] == 0:
rocket_center_x = rocket.rocket_x + self.rocketImg.get_width() // 2
self.bullet_x = rocket_center_x - self.bullet_width // 2
self.move[1] = -1
# [...]
Passe the instance of ROCKET to the method draw_bullet:
while True:
# [...]
bullet.draw_bullet(rocket)
# [...]
If you want to fire multiple bullets, see the answers to the questions:
How can i shoot a bullet with space bar?
How do I stop more than 1 bullet firing at once?
I'm making a game with Python. I have a spaceship in this game. The spaceship can move to the left and to the right and it is supposed to shoot bullets from its x-position and it is supposed to fire the bullets up. I am able to move the spaceship and I am able to put it on the screen. The problem is that I am not able to fire the bullet from the spaceship's x-position and I am not able to make the bullet move up. Can somebody help me with this? Please post simple code too if possible.
Here's the code:
import pygame
import sys
pygame.init()
screen_length = 512
screen_width = 288
clock = pygame.time.Clock()
screen = pygame.display.set_mode((screen_width, screen_length))
bg = pygame.image.load(r'C:\Users\Anonymous\Downloads\space game folder\space background3.png').convert()
bg = pygame.transform.scale2x(bg)
spaceship = pygame.image.load(r'C:\Users\Soorya\Anonymous\space game folder\spaceship.png').convert()
missile = pygame.image.load(r'C:\Users\Soorya\Anonymous\space game folder\bullet2.png').convert()
x = 130
y = 480
z = 460
velocity = 30
spaceship_rect = spaceship.get_rect(center=(x, y))
spaceship_x_pos = spaceship_rect.left + 170
bullet_speed = 10
missile_rect = missile.get_rect(center=(round(spaceship_x_pos // 2), z))
spaceship_direction = 10
while True:
for event in pygame.event.get():
if event == pygame.QUIT:
pygame.display.quit()
sys.exit(0)
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] and x < 288:
x += velocity
if keys[pygame.K_LEFT] and x > 0:
x -= velocity
if keys[pygame.K_SPACE]:
bg.blit(missile, missile_rect)
screen.fill(0)
screen.blit(bg, (0, 0))
screen.blit(spaceship, (x, y))
pygame.display.update()
clock.tick(120)
The problem with your code is that your indentation is not right.
while True:
for event in pygame.event.get():
if event == pygame.QUIT:
pygame.display.quit()
sys.exit(0)
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] and x < 288:
x += velocity
if keys[pygame.K_LEFT] and x > 0:
x -= velocity
if keys[pygame.K_SPACE]:
bg.blit(missile, missile_rect)
screen.fill(0) # THIS
screen.blit(bg, (0, 0)) #THIS
screen.blit(spaceship, (x, y)) #THIS
pygame.display.update() #THIS
clock.tick(120) #THIS
The lines where i commented this have to be indented like this:
while True:
for event in pygame.event.get():
if event == pygame.QUIT:
pygame.display.quit()
sys.exit(0)
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] and x < 288:
x += velocity
if keys[pygame.K_LEFT] and x > 0:
x -= velocity
if keys[pygame.K_SPACE]:
bg.blit(missile, missile_rect)
screen.fill(0)
screen.blit(bg, (0, 0))
screen.blit(spaceship, (x, y))
pygame.display.update()
clock.tick(120)
That's because you want to do those things every single frame while the game is running. One more thing, you are filling the screen with black in line screen.fill(0), which is not necessary since you are already rendering a background image, so you basically cannot see it. With that being said, i recommend taking an object oriented approach as well because you wont get very far without it. Also, set velocity to like 0.5 or something. Its currently 30, which means 30 pixels every frame and that's not what you want.
Now to fire bullets. What you are doing right now wont work because you are only "blitting" a missile if space is pressed. Below i wrote a separate code for you that only fires missiles, so hopefully its clear and you can implement in your own code.
import pygame
import sys
pygame.init()
d = pygame.display.set_mode((1200, 600))
# WE WILL USE FIRING BOOLEAN TO KEEP TRACK OF IF WE ARE FIRING MISSILES
firing = False
missile = pygame.Surface((10, 50))
while True:
d.fill((255, 255, 255))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
# Assign initial positions only if it isnt firing
if not firing:
missilex = 600 # This is the initial position of the missile. This will be
missiley = 500 # your player position in your game
if pygame.key.get_pressed()[pygame.K_SPACE]: # if space pressed set firing to true
firing = True
# if firing is true, we want to display the missile and move it.
if firing:
d.blit(missile, (missilex, missiley))
missiley -= 1
# if missile is off the screen, set firing to false so it resets to initial position (600, 500).
if missiley < -20:
firing = False
pygame.display.update()
The way you are approaching it doesn't seem right to me, unless ofc that isn't your whole code. But you are using the same variable to represent the x and y coordinate of your bullet and the spaceship. You want to bullet to move independently from the space ship. So if you change the variable y in your code, that will move space ship up too, and same with the x variable.
What you need to do is to create 2 separate classes. One for you bullet, and the other for the space ship. Here is a simple example of its implementation, which you can improve upon by adding whatever features you want later.
class Spaceship:
image = pygame.image.load(r'C:\Users\Soorya\Anonymous\space game folder\spaceship.png').convert()
def __init__(self, x, y, vel):
self.x = x
self.y = y
self.vel = vel
def draw(self, screen):
screen.blit(Spaceship.image, (self.x, self.y))
class Bullet:
image = pygame.image.load(r'C:\Users\Soorya\Anonymous\space game folder\bullet2.png').convert()
bullet_list = [] # holds the list of bullets in the screen
def __init__(self, x, y, vel):
self.x = x
self.y = y
self.vel = vel
Bullet.bullet_list.append(self)
def move(self):
self.y -= self.vel
if self.y < 0: # remove bullet if it goes beyond screen
Bullet.bullet_list.remove(self)
def draw(self, screen):
screen.blit(Bullet.image, (self.x, self.y))
spaceship = Spaceship(130, 480, 30)
# set up screen and bg as before
while True:
for event in pygame.event.get():
if event == pygame.QUIT:
pygame.display.quit()
sys.exit(0)
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] and x < 288:
spaceship.x += spaceship.vel
if keys[pygame.K_LEFT] and x > 0:
spaceship.x -= spaceship.vel
if keys[pygame.K_SPACE]: # create a bullet if space is pressed
Bullet(spaceship.x, spaceship.y, 10)
screen.blit(bg, (0, 0))
spaceship.draw()
for bullet in Bullet.bullet_list():
bullet.move() # actually moves the bullet on each iteration of the loop
bullet.draw()
pygame.display.update()
clock.tick(120)
Important note for future if you want to create games, make everything object oriented lol. Trust me, it will make your life a whole lot easier. Let me know if you have any problems.