Pygame: my bullet class does nothing apart from being drawn - python

So im trying to make a local multiplayer game, i have created the player class which works fine so far.
Now im trying to do a bullet class to create different types of shots for the player's spaceships, however upon calling my bullet, it only gets drawn to the screen where the player was at the start of the game and it doesnt move (so far just trying to program it to move)
Here is the code:
import pygame
pygame.init()
#Display screen
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Space Arena")
background = pygame.image.load(r'C:\Users\Bruno\Documents\PythonProjects\Pygame\Multiplayer\Images\background.png').convert_alpha()
playerImg = pygame.image.load(r'C:\Users\Bruno\Documents\PythonProjects\Pygame\Multiplayer\Images\Player.png').convert_alpha()
player2Img = pygame.image.load(r'C:\Users\Bruno\Documents\PythonProjects\Pygame\Multiplayer\Images\Player2.png').convert_alpha()
regular_bullet = pygame.image.load(r'C:\Users\Bruno\Documents\PythonProjects\Pygame\Multiplayer\Images\bullet.png').convert_alpha()
class Player:
def __init__(self, image, x, y, isPlayer1, isPlayer2):
self.image = image
self.x = x
self.y = y
self.isPlayer1 = isPlayer1
self.isPlayer2 = isPlayer2
def Move(self):
key_states = pygame.key.get_pressed()
x_change = 0.2
y_change = 0.2
if self.isPlayer1:
if key_states[pygame.K_a]:
self.x += -x_change
if key_states[pygame.K_d]:
self.x += x_change
if key_states[pygame.K_w]:
self.y += -y_change
if key_states[pygame.K_s]:
self.y += y_change
elif self.isPlayer2:
if key_states[pygame.K_LEFT]:
self.x += -x_change
if key_states[pygame.K_RIGHT]:
self.x += x_change
if key_states[pygame.K_UP]:
self.y += -y_change
if key_states[pygame.K_DOWN]:
self.y += y_change
def draw(self, screen):
screen.blit(self.image,(self.x,self.y))
def ColorPlayer(self ,image):
if self.isPlayer1:
self.image.fill((190,0,0,100), special_flags = pygame.BLEND_ADD)
if self.isPlayer2:
self.image.fill((0,0,190,100), special_flags = pygame.BLEND_ADD)
class Bullet():
def __init__(self, image, bulletx, bullety):
self.image = image
self.bulletx = bulletx
self.bullety = bullety
self.bullet_state = "ready"
def draw(self, screen):
if self.bullet_state == "fire":
screen.blit(self.image,(self.bulletx,self.bullety))
def shoot(self):
change_x = 0.9
if self.bullet_state == "fire":
self.bulletx += change_x
if self.bulletx > 800:
self.bullet_state = "ready"
def redrawWindow(screen, player, player2, background, player_bullet):
screen.fill((255,255,255))
screen.blit(background,(0,0))
player.draw(screen)
player2.draw(screen)
player_bullet.draw(screen)
pygame.display.update()
def Main():
done = False
player = Player(playerImg,200,200,True,False)
player2 = Player(player2Img,600,200,False,True)
player1_bullet = Bullet(regular_bullet, player.x, player.y)
while not done:
player.Move()
player2.Move()
player.ColorPlayer(playerImg)
player2.ColorPlayer(player2Img)
redrawWindow(screen, player, player2, background, player1_bullet)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if player1_bullet.bullet_state is "ready":
player1_bullet.bullet_state = "fire"
player1_bullet.shoot()
Main()

It looks like shoot is effectively the "update" function for your bullet, and the code inside would need to be called every frame (like with player.Move()) for the bullet to keep moving after it's fired.

The only code you have that changes the bullet position is this bit inside the shoot method.
def shoot(self):
change_x = 0.9
if self.bullet_state == "fire":
self.bulletx += change_x
Nothing else moves it. You need to have a move function that adjusts it position and call that each frame. In fact your shoot function is a bit odd it looks more like what the move function would look like. Perhaps rename it to move() and call it each frame?
That function is a bit unusual for a shoot() function, since it moves an existing bullet instead of firing a new one. Normally a shoot method would be expected to be a method in the player and to create a new bullet. It does not really make sense for a bullet instance function to shoot and to create a new bullet. Also you seem to have coded it so that there is a single bullet that goes to 800 and then can be re-fired, but you do not have anything that resets the bullets position back to where the player is.
It might make more sense for the 'ready' and 'fire' state to be a state of the player since the player is the one that can or cannot fire. Also the shoot() method is more commonly in the player class and when it fires (the player is in state 'ready') it creates a new Bullet instance at the players position.
The bullet move() method would be called each frame just like the player move() functions are. Normally there would be more than one bullet allowed at a time and so you would keep a list of the and have to iterate through the list of bullets moving them along (and doing collision checking to see if they hit anything). If a bullet goes off the screen or hits something then you remove the bullet from the bullet list.

You have to change 2 things.
The method Bullet.shoot() has to be continuously invoked in the main application loop. Note, this method updates the bullet dependent on its state. If the state of the bullet is "fire" then the bullet moves. Else it stands still.
Update the position of the bullet when it is fired. The bullet always has to start at the position of the player:
def Main():
# [...]
while not done:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if player1_bullet.bullet_state is "ready":
player1_bullet.bullet_state = "fire"
player1_bullet.bulletx = player.x
player1_bullet.bullety = player.y
player1_bullet.shoot()

Related

Enemies' and bullets' positions' value does not change - pygame

I'm writing a pygame shooting game where you have to use space station to shoot enemies flying from the top of the screen to the bottom. However, I noticed that the Y positions of enemy(enemy.pos_y) and bullet(bullet.pos_y) is just the position where they spawn, but this position doesn't change even though the enemy moves in the window of the game (because of the move() function in class Enemy) and also bullet moves (also because of the move() function but in Bullet class) and that's obvious because the Y values are constant (enemy.pos_y=-30 and bullet.pos_y=STATION_HEIGHT - 5. So is there any solution to make those positions' values change (I'm saying value because on screen enemies' and bullets' positions change) and still spawn them in those given positions? This issue stops my further steps, because for example making collision between enemies and bullets is impossible, because it's like they never move, and so they never meet. So how to make detect those objects' position's value's change?
In this picture you can see that enemies' positions' value remains the same: enter image description here
Enemies' class:
import pygame
import math
class Enemy:
def __init__(
self, pos_x: float, pos_y: float, texture: pygame.Surface, speed: float
):
self.pos_x = pos_x
self.pos_y = pos_y
self.texture = texture
self.speed = speed
def move(self):
self.pos_y += self.speed
Bullets' class:
import pygame
class Bullet:
def __init__(
self, pos_x: float, pos_y: float, texture: pygame.Surface, speed: float
):
self.pos_x = pos_x
self.pos_y = pos_y
self.texture = texture
self.speed = speed
def move(self):
self.pos_y -= self.speed
Here I display enemies and bullets (in main loop):
running = True
while running:
all_event = pygame.event.get()
for event in all_event:
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
shot_sound.play()
# Bullets
bullet = Bullet(
bulletX + station.pos_x,
STATION_HEIGHT + 10,
bullet_texture,
BULLET_SPEED,
)
bullets.append(bullet)
print(f'position X={bullet.pos_x}')
# Enemies move
for enemy in enemies:
for i in range(3):
enemy.move()
for i in range(3):
enemy = Enemy(random.randrange(67, 520), -30, enemy_texture, ENEMY_SPEED)
start_time+=1
if start_time > 200:
enemies.append(enemy)
start_time = 0
The whole code you can find on my Github: enter link description here
ps. I'm sorry if this question and problem's explanation isn't well-written, but this is my first question here on stackoverflow so I'm not really experienced, I'm waiting for questions if something's not understandable.
You actually just print the position of a newly created bullet. If you want to see the position of a moving bullet, you need to move the print statement in the loop that moves the bullets:
while running:
# [...]
for enemy in enemies:
enemy.move()
print(f'enemy position Y={enemy.pos_y}')
# [...]
for bullet in bullets:
bullet.move()
print(f'bullet position Y={bullet.pos_y}')
# [...]
or
while running:
# [...]
for i, enemy in enumerate(enemies):
enemy.move()
print(f'position of enemy {i} Y={enemy.pos_y}')
# [...]
for i, bullet in enumerate(bullets):
bullet.move()
print(f'position of bullet {i} Y={bullet.pos_y}')
# [...]

PyGame rect.move movement not functioning properly

I am developing my first pygame application in the form of a brick breaker clone. For the player paddle, I am checking for key holds in the main game loop and then redrawing the player object's sprite every frame, as show in the code snippet below:
class Player():
def __init__(self):
self.sprite = pg.transform.scale(pg.image.load('49-Breakout-Tiles.png'), (61,16))
self.rect = self.sprite.get_rect()
self.rect.right += displayRect.center[0]-25
self.rect.top += displayRect.center[1]+450
self.draw(0)
def draw(self, x):
pg.draw.rect(display, black, (self.rect.x, self.rect.y, 61, 16))
self.rect.right += x
if not displayRect.contains(self.rect):
self.rect.right -= x
display.blit(self.sprite, self.rect)
#from gameloop
moveNeg, movePos = False, False
while True:
for event in pg.event.get():
if event.type == pg.KEYDOWN:
if event.key == pg.K_LEFT or event.key == pg.K_a:
moveNeg = True
if event.key == pg.K_RIGHT or event.key == pg.K_d:
movePos = True
if event.type == pg.KEYUP:
if event.key == pg.K_LEFT or event.key == pg.K_a:
moveNeg = False
if event.key == pg.K_RIGHT or event.key == pg.K_d:
movePos = False
if moveNeg:
player.draw(-1)
if movePos:
player.draw(1)
This code works fine, and also ensures that the player paddle stays within the display bounds.
However, for the ball object, I am trying to use rect.move(x,y) to move it. I have already tried with rect.right and rect.top but the ball object is still unresponsive. Here is the code I have so far:
class Ball():
def __init__(self):
self.sprite = pg.transform.scale(pg.image.load('58-Breakout-Tiles.png'), (16, 16))
self.rect = self.sprite.get_rect()
self.rect.x += displayRect.center[0]
self.rect.y += displayRect.center[1]
self.dir = [random.uniform(-1.0,1.0), random.uniform(-1.0,1.0)]
print(self.dir)
def draw(self, xy):
pg.draw.rect(display, black, (self.rect.x, self.rect.y, 16, 16))
self.rect = self.rect.move(xy[0], xy[1])
display.blit(self.sprite, self.rect)
The ball is centered when the object is initialised (as shown on lines 3/4 of the __init__ function, but I don't see why this would affect the movement of the ball's rect. Also for clarity, self.dir is used to give the ball a random starting direction, and I am aware that it is able to move upward with this current configuration.
Since I am new to pygame it completely baffles me as to why my logic is flawed so any help is much appreciated.
Thanks
pygame.Rect.move doesn't change the Rect object itself, but it returns an new Rect object (Probably the name of the method is misleading).
This means, that
self.rect.move(xy[0], xy[1])
doesn't change anything. You've to assign the rectangle which is returned by .move to "itself":
self.rect = self.rect.move(xy)
Alternatively you can use pygame.Rect.move_ip(), moves the rectangle "in place" and changes the Rect object:
self.rect.move_ip(xy[0], xy[1])

sprite collision detection and removing one sprite from group in pygame

so I need to remove one sprite from the group every time I press the - (minus) key. However, I am confused as to how to do it. Another issue I've run into is when I press the + key it is adding more than one sprite at a time. I'm guessing I need to also check for KEYUP ? I also have a bug where some of the sprites will be created on top of each and will stay stuck bouncing off one another. How can I check for existing sprites where the new will be generated? Here is my code
dragon.py
import pygame
from pygame.locals import *
class Dragon(pygame.sprite.Sprite):
def __init__(self, x,y, vx, vy):
super().__init__();
self.image = pygame.image.load("images/dragon.png").convert()
self.image.set_colorkey(pygame.Color(255,0,255))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.vx = vx
self.vy = vy
def draw(self, SCREEN):
SCREEN.blit(self.image, (self.rect.x, self.rect.y))
def move(self, SCREEN):
r_collide = self.rect.x + self.image.get_width() + self.vx >= SCREEN.get_width()
l_collide = self.rect.x + self.vx <= 0
t_collide = self.rect.y + self.vy <= 0
b_collide = self.rect.y + self.image.get_height() + self.vy >= SCREEN.get_height()
# Check collision on right and left sides of screen
if l_collide or r_collide:
self.vx *= -1
# Check collision on top and bottom sides of screen
if t_collide or b_collide:
self.vy *= -1
self.rect.x += self.vx
self.rect.y += self.vy
def bounce(self, SCREEN):
self.vy *= -1
self.vx *= -1
dragon_animation.py
import pygame
import sys
from random import *
from pygame.locals import *
from flying_dragon.dragon import Dragon
def main():
pygame.init()
FPS = 30
FPS_CLOCK = pygame.time.Clock()
''' COLOR LIST '''
WHITE = pygame.Color(255,255,255)
''' create initial window '''
window_size = (500, 500)
SCREEN = pygame.display.set_mode(window_size)
''' set the title '''
pygame.display.set_caption("Flying Dragons")
''' fill background color in white '''
SCREEN.fill(WHITE)
''' group to store dragons '''
dragons = pygame.sprite.Group()
d1 = Dragon(0,0,3,2)
d1.draw(SCREEN)
dragons.add(d1)
''' main game loop '''
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
SCREEN.fill(WHITE)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_PLUS or pygame.K_KP_PLUS:
d = Dragon(randint(1, SCREEN.get_width() - dragon.rect.x), randint(1, SCREEN.get_height()- dragon.rect.y), randint(1, 5), randint(1, 5))
dragons.add(d)
for dragon in dragons:
dragons.remove(dragon)
collisions = pygame.sprite.spritecollide(dragon, dragons, False)
dragons.add(dragon)
for dragon in collisions:
dragon.bounce(SCREEN)
for dragon in dragons:
dragon.move(SCREEN)
dragons.update(SCREEN)
dragons.draw(SCREEN)
pygame.display.update()
FPS_CLOCK.tick(FPS)
if __name__ == "__main__":
main()
if event.key == pygame.K_MINUS or pygame.K_KP_MINUS:
dragons.remove(dragons[0])
Should work for removing a sprite. Sprites aren't ordered in the group so will just delete a random one.
As another pointer, you should look at redefining your Dragon.move() function as dragon.update() then the Group.update() call will move all your dragons.
you don't need to draw the dragon immediately after it's creation before the while loop. The draw inside the while loop is sufficient.
When you press a key the event list will hold which key you are holding down and as long as this is down a dragon will be created. As the loop runs pretty fast several dragons will be created before you remove your finger from the keyboard.
also good to do
pygame.event.pump()
before the for event in pygame.event.get(): so that you clear the event list beofre the next run.
read about the pygame event pump here.
Use key = pygame.key.get_pressed() instead of event.get as it will read a key press ONCE.
can't run your code because of this error.
ImportError: No module named flying_dragon.dragon

Multiple bullets not showing up when added to Pygame sprite group and updated

I'm working on my first project in Python / Pygame, which is a shooter-style game. However, when I create multiple instances of my Bullet sprite and add them to the sprite group, only the most recent instance is shown on the screen. That is, only one bullet is showing at any given time.
I think Lines 175-180 or within the Bullet class are causing the problem.
My code:
import pygame, random , sys , time
from pygame.locals import *
# Screen dimensions
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
# Global constants
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
LIGHTBLUE = ( 0, 0, 155)
FPS = 60
class Player(pygame.sprite.Sprite):
# set speed vector of the player
change_x = 0
change_y = 0
moverate = 5
# Constructor. Pass in x and y position
def __init__(self, x, y):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
# Create player image
self.image = pygame.image.load('player.png')
self.image.set_colorkey(WHITE)
# Set a referance to the image rect.
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.y = y
def changespeed(self, x, y):
""" Change the speed of the player"""
self.change_x += x
self.change_y += y
def update(self):
""" Move the player. """
# Move left/right
self.rect.x += self.change_x
# Move up/down
self.rect.y += self.change_y
def stop(self):
""" Called when the user lets off the keyboard."""
self.change_x = 0
self.change_y = 0
self.image = pygame.image.load('player.png')
self.image.set_colorkey(WHITE)
class Enemy(pygame.sprite.Sprite):
""" This class represents the enemy sprites."""
minmoverate = 1
maxmoverate = 8
def __init__(self):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('enemyShip.png')
self.image = pygame.transform.scale(self.image, (50, 50))
self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
def reset_pos(self):
""" Reset position to the top of the screen, at a random x location.
Called by update() or the main program loop if there is a collision."""
self.rect.y = - ( SCREEN_HEIGHT / 4)
self.rect.x = random.randrange(SCREEN_WIDTH)
def update(self):
""" Move the enemies. """
# Move down, at some speed
self.rect.y += 2
# Move left and right, at some speed
self.rect.x += 0
# If enemy is too far down, reset to top of screen
if self.rect.y > SCREEN_HEIGHT:
self.reset_pos()
class Bullet(pygame.sprite.Sprite):
""" This class represents the bullet. """
def __init__(self):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([8, 20])
self.image.fill(LIGHTBLUE)
self.rect = self.image.get_rect()
def update(self):
""" Move the bullet. """
self.rect.y -= 10
class Game(object):
""" This class represents an instance of the game. If we need to
rest the game we'd just need to create a new instance of this class."""
# --- Class attributes.
# Sprite lists
enemy_list = None
bullet_list = None
all_sprites_list = None
# --- Class methods
# Set up the game
def __init__(self):
self.score = 0
self.game_over = False
# Create sprite lists
self.enemy_list = pygame.sprite.Group()
self.bullet_list = pygame.sprite.Group()
self.all_sprites_list = pygame.sprite.Group()
# Create the starting enemy ships
for i in range(15):
enemy = Enemy()
enemy.rect.x = random.randrange(SCREEN_WIDTH)
enemy.rect.y = random.randrange(-300, 20)
self.enemy_list.add(enemy)
self.all_sprites_list.add(enemy)
# Create the player
self.player = Player(SCREEN_WIDTH / 2, SCREEN_HEIGHT - (SCREEN_HEIGHT / 6))
self.all_sprites_list.add(self.player)
def process_events(self):
""" Process all of the events. Return "True" if we need to close the window."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
return True
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
return True
elif event.key == K_RETURN:
if self.game_over:
self.__init__()
elif event.key in (K_RIGHT ,K_d):
self.player.changespeed( self.moverate ,0)
elif event.key in (K_LEFT ,K_a):
self.player.changespeed( -self.moverate ,0)
elif event.key in (K_UP , K_w):
self.player.changespeed(0, -self.moverate)
elif event.key in (K_DOWN , K_s):
self.player.changespeed(0, self.moverate)
elif event.key == K_SPACE: # Fire bullet
bullet = Bullet(0
# Set bullet so it is where the player is
bullet.rect.centerx = self.player.rect.centerx
bullet.rect.y = self.player.rect.y
# Add bullet to lists
self.all_sprites_list.add(bullet)
self.bullet_list.add(bullet)
elif event.type == KEYUP:
if event.key in (K_RIGHT ,K_d):
self.player.changespeed( -self.moverate ,0)
elif event.key in (K_LEFT ,K_a):
self.player.changespeed( self.moverate ,0)
elif event.key in (K_UP , K_w):
self.player.changespeed(0, self.moverate)
elif event.key in (K_DOWN , K_s):
self.player.changespeed(0, -self.moverate)
def run_logic(self):
""" This method is run each time through the frame.
It updates positions and checks for collisions."""
enemy = Enemy()
if not self.game_over:
# Move all the sprites
self.all_sprites_list.update()
if len(self.all_sprites_list) < 17:
self.enemy_list.add(enemy)
self.all_sprites_list.add(enemy)
enemy.rect.x = random.randrange(SCREEN_WIDTH)
enemy.rect.y = random.randrange(-100, -50)
# Bullet Mechanics
for bullet in self.bullet_list:
# See if the bullets has collided with anything.
self.enemy_hit_list = pygame.sprite.spritecollide(bullet, self.enemy_list, True)
# For each enemy hit, remove bullet and enemy and add to score
for enemy in self.enemy_hit_list:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
self.score += 1
# Remove the bullet if it flies up off the screen
if bullet.rect.y < -10:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
# Player Mechanics
for enemy in self.enemy_list:
# See if player has collided with anything.
self.player_hit_list = pygame.sprite.spritecollide(self.player, self.enemy_list, True)
if len(self.player_hit_list) == 1:
# If player is hit, show game over.
self.game_over = True
def display_frame(self, screen):
""" Display everything to the screen for the game. """
screen.fill(BLACK)
if self.game_over:
# font = pygame.font.Font("Serif:, 25)
font = pygame.font.SysFont("serif", 25)
text = font.render("Game Over! You scored " + str(self.score) +" points, press Enter to restart", True, WHITE)
center_x = (SCREEN_WIDTH // 2) - (text.get_width() // 2)
center_y = (SCREEN_HEIGHT // 2) - (text.get_height() // 2)
screen.blit(text, [center_x, center_y])
if not self.game_over:
self.all_sprites_list.draw(screen)
pygame.display.flip()
def main():
""" Main program function. """
# Initialize Pygame and set up the window
pygame.init()
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
screen_rect = screen.get_rect()
pygame.display.set_caption("My Game")
pygame.mouse.set_visible(False)
# Create our objects and set the data
done = False
clock = pygame.time.Clock()
# Create an instance of the Game class
game = Game()
# Main game loop
while not done:
# Process events (keystrokes, mouse clicks, etc)
done = game.process_events()
# Update object positions, check for collisions
game.run_logic()
# Draw the current frame
game.display_frame(screen)
# Pause for the next frame
clock.tick(FPS)
# Close window and exit
pygame.quit()
# Call the main function, start up the game
if __name__ == "__main__":
main()
The problem is that you're only ever creating a single Bullet instance, which you're storing in the Game.bullet class variable. Whenever you shoot, the code moves that single bullet to the player's position, and it updates from there.
You probably want to create a new bullet for every shot. Use something like this in process_events:
elif event.key == K_SPACE: # Fire bullet
bullet = Bullet()
bullet.rect.centerx = self.player.rect.centerx
bullet.rect.y = self.player.rect.y
# Add bullet to lists
all_sprites_list.add(self.bullet)
bullet_list.add(self.bullet)
That creates a new bullet every time the space bar is pressed. If your game design specifies a limit to the number of bullets that can be "active" at once, you may need some more complex logic (or if the performance cost of creating and destroying lots of instances is too much you could write some object caching code), but this should get you on the right track.
Now, the code above doesn't do anything to remove the bullets later, so you'll probably need to handle that too or your game will bog down from the calculations involving off-screen bullets. I'd suggest putting some logic in Bullet.update() that calls self.kill() if the bullet is off the screen (or whenever makes sense for your game). The instance will be garbage collected automatically when there are no more references to it.
I'd also suggest getting rid of all of the class variables of you Game class, which are either unnecessary (they get shadowed by instance variables that are created in __init__), or broken (like bullet).

how to limit bullets fired [duplicate]

This question already exists:
How to set limit of bullets on pygame [closed]
Closed 9 years ago.
Here's the code, please help with detailed instruction. I need to know how to set limits on shooting bullets. If you could show me how to do it with my code that would be great. I'm including the player class, bullet class, main loop and shooting mech.
# This class represents the Player
class Player(pygame.sprite.Sprite):
def __init__(self):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20,20])
self.image.fill(red)
self.rect = self.image.get_rect()
# This class represents the bullet
class Bullet(pygame.sprite.Sprite):
def __init__(self):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 4])
self.image.fill(black)
self.rect = self.image.get_rect()
class Shoot(pygame.sprite.Sprite):
def __init__(self):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 4])
self.image.fill(black)
self.rect = self.image.get_rect()
# Initialize Pygame
pygame.init()
# Set the height and width of the screen
screen_width=700
screen_height=400
screen=pygame.display.set_mode([screen_width,screen_height])
# This is a list of every sprite. All blocks and the player block as well.
all_sprites_list = pygame.sprite.Group()
# List of each bullet
bullet_list = pygame.sprite.Group()
shoot_list = pygame.sprite.Group()
# Create a red player block
player = Player()
all_sprites_list.add(player)
#Loop until the user clicks the close button.
done=False
# Used to manage how fast the screen updates
clock=pygame.time.Clock()
score = 0
player.rect.y=370
bullet_count=0
# -------- Main Program Loop -----------
while done==False:
# ALL EVENT PROCESSING SHOULD GO BELOW THIS COMMENT
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done=True # Flag that we are done so we exit this loop
if event.type == KEYDOWN:
if event.key == K_LEFT:
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
if event.key == K_RIGHT:
shoot = Shoot()
shoot.rect.x = player.rect.x
shoot.rect.y = player.rect.y
all_sprites_list.add(shoot)
shoot_list.add(shoot)
# ALL EVENT PROCESSING SHOULD GO ABOVE THIS COMMENT
# ALL GAME LOGIC SHOULD GO BELOW THIS COMMENT
# Calculate mechanics for each bullet
bulletCounter = 0
for bullet in bullet_list:
bullet.rect.x -= 5
for shoot in shoot_list:
shoot.rect.x -= -5
# Remove the bullet if it flies up off the screen
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
# Get the current mouse position. This returns the position
# as a list of two numbers.
pos = pygame.mouse.get_pos()
# Set the player x position to the mouse x position
player.rect.x=pos[0]
# ALL GAME LOGIC SHOULD GO ABOVE THIS COMMENT
# ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
# Clear the screen
screen.fill(white)
# Draw all the spites
all_sprites_list.draw(screen)
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
# Limit to 20 frames per second
clock.tick(20)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
pygame.quit()
You can create a gun class which have the bullet count as a property and shooting will be a function of the class.
class Gun(object):
def __init__(self):
self.bullet_count = 5
def __shoot(self, bullet_sprite, bullet_list):
if self.bullet_count > 0:
self.bullet_count -= 1
bullet_sprite.rect.x = player.rect.x
bullet_sprite.rect.y = player.rect.y
all_sprites_list.add(bullet_sprite)
bullet_list.add(bullet_sprite)
def shoot_left(self, bullet_list):
self.__shoot(Bullet(), bullet_list)
def shoot_right(self, bullet_list):
self.__shoot(Shoot(), bullet_list)
-------------------------------------------------------
Then, before your enter your while-loop you would create an instance of the gun class and use it as follows:
if event.type == pygame.KEYDOWN and gun.bullet_count > 0:
print "KEY DOWN"
if event.key == K_LEFT:
gun.shoot_left(bullet_list)
if event.key == K_RIGHT:
gun.shoot_right(shoot_list)

Categories