24. Using Sprites to Shoot¶
How do we get sprites that we can shoot?

Coins shooting¶
24.1. Getting Started¶
First, let’s go back to a program to start with.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | import random
import arcade
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
SPRITE_SCALING_LASER = 0.8
COIN_COUNT = 50
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
BULLET_SPEED = 5
class MyGame(arcade.Window):
""" Main application class. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprites and Bullets Demo")
# Variables that will hold sprite lists
self.player_list = None
self.coin_list = None
# Set up the player info
self.player_sprite = None
self.score = 0
# Don't show the mouse cursor
self.set_mouse_visible(False)
arcade.set_background_color(arcade.color.AMAZON)
def setup(self):
""" Set up the game and initialize the variables. """
# Sprite lists
self.player_list = arcade.SpriteList()
self.coin_list = arcade.SpriteList()
# Set up the player
self.score = 0
# Image from kenney.nl
self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50
self.player_sprite.center_y = 70
self.player_list.append(self.player_sprite)
# Create the coins
for i in range(COIN_COUNT):
# Create the coin instance
# Coin image from kenney.nl
coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)
# Position the coin
coin.center_x = random.randrange(SCREEN_WIDTH)
coin.center_y = random.randrange(SCREEN_HEIGHT)
# Add the coin to the lists
self.coin_list.append(coin)
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
def on_draw(self):
"""
Render the screen.
"""
# This command has to happen before we start drawing
arcade.start_render()
# Draw all the sprites.
self.coin_list.draw()
self.player_list.draw()
# Render the text
arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE, 14)
def on_mouse_motion(self, x, y, dx, dy):
"""
Called whenever the mouse moves.
"""
self.player_sprite.center_x = x
self.player_sprite.center_y = y
def on_mouse_press(self, x, y, button, modifiers):
"""
Called whenever the mouse button is clicked.
"""
pass
def update(self, delta_time):
""" Movement and game logic """
# Call update on all sprites
self.coin_list.update()
def main():
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
If you run this program, the player should move around the screen, and their should be coins. But not much else is happening yet.
Next, we need a ‘shooting’ image:

laserBlue01.png¶
Download this image (originally from Kenney.nl) and make sure it is in the same folder as your code.
24.2. Keeping The Player At The Bottom¶
Right now the player can move anywhere on the screen. We want to keep that sprite fixed to the bottom of the screen.
To do that, just remove the line of code for moving the player on the y-axis.
The player will keep the same y value that we set back in the setup
method.
def on_mouse_motion(self, x, y, dx, dy):
"""
Called whenever the mouse moves.
"""
self.player_sprite.center_x = x
# REMOVE THIS LINE: self.player_sprite.center_y = y
24.3. Moving The Coins Up¶
We want all the coins above the player. So we can adjust the starting y locations to have a starting point of 150 instead of 0. That will keep them above the player.
# Create the coins
for i in range(COIN_COUNT):
# Create the coin instance
# Coin image from kenney.nl
coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)
# Position the coin
coin.center_x = random.randrange(SCREEN_WIDTH)
coin.center_y = random.randrange(150, SCREEN_HEIGHT)
# Add the coin to the lists
self.coin_list.append(coin)
24.4. Set Up Bullet List¶
We need to create a list to manage the bullets. There are four places we need to
add this bullet_list
code:
Create the
bullet_list
variable (Line 26)Create an instance of
SpriteList
(Line 44)Draw the bullet list (Line 83)
Update the bullet list (Line 105)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | import random
import arcade
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
SPRITE_SCALING_LASER = 0.8
COIN_COUNT = 50
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
BULLET_SPEED = 5
class MyGame(arcade.Window):
""" Main application class. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprites and Bullets Demo")
# Variables that will hold sprite lists
self.player_list = None
self.coin_list = None
self.bullet_list = None
# Set up the player info
self.player_sprite = None
self.score = 0
# Don't show the mouse cursor
self.set_mouse_visible(False)
arcade.set_background_color(arcade.color.AMAZON)
def setup(self):
""" Set up the game and initialize the variables. """
# Sprite lists
self.player_list = arcade.SpriteList()
self.coin_list = arcade.SpriteList()
self.bullet_list = arcade.SpriteList()
# Set up the player
self.score = 0
# Image from kenney.nl
self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50
self.player_sprite.center_y = 70
self.player_list.append(self.player_sprite)
# Create the coins
for i in range(COIN_COUNT):
# Create the coin instance
# Coin image from kenney.nl
coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)
# Position the coin
coin.center_x = random.randrange(SCREEN_WIDTH)
coin.center_y = random.randrange(150, SCREEN_HEIGHT)
# Add the coin to the lists
self.coin_list.append(coin)
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
def on_draw(self):
"""
Render the screen.
"""
# This command has to happen before we start drawing
arcade.start_render()
# Draw all the sprites.
self.coin_list.draw()
self.player_list.draw()
self.bullet_list.draw()
# Render the text
arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE, 14)
def on_mouse_motion(self, x, y, dx, dy):
"""
Called whenever the mouse moves.
"""
self.player_sprite.center_x = x
def on_mouse_press(self, x, y, button, modifiers):
"""
Called whenever the mouse button is clicked.
"""
pass
def update(self, delta_time):
""" Movement and game logic """
# Call update on all sprites
self.coin_list.update()
self.bullet_list.update()
def main():
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
24.5. Creating Bullets¶
We need to
create bullets when the user presses the mouse button. We can add an
on_mouse_press
method to do something when the user presses the mouse button:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
This will create a bullet, but the bullet will default to the lower left corner. You can just barely see it.
We can give the bullet a position:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = x
bullet.center_y = y
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
But this isn’t what we want either. The code above puts the laser where we click the mouse. We want the laser to be where the player is. That’s easy:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = self.player_sprite.center_x
bullet.center_y = self.player_sprite.center_y
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
We can even start the bullet a bit ABOVE the player:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = self.player_sprite.center_x
bullet.center_y = self.player_sprite.center_y + 30
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
We can make the bullet move up using the constant BULLET_SPEED
which
we set to 5 at the top of the program:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = self.player_sprite.center_x
bullet.center_y = self.player_sprite.center_y + 30
bullet.change_y = BULLET_SPEED
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
We can rotate the bullet so it isn’t sideways using the angle
attribute
built into the Sprite
class:
def on_mouse_press(self, x, y, button, modifiers):
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
bullet.center_x = self.player_sprite.center_x
bullet.center_y = self.player_sprite.center_y + 30
bullet.change_y = BULLET_SPEED
bullet.angle = 90
# Add the bullet to the appropriate list
self.bullet_list.append(bullet)
24.6. Bullet Collisions¶
Now that we have bullets, how do we get them to collide with the coins?
We add the following to our applications update
method:
# Loop through each bullet
for bullet in self.bullet_list:
# Check this bullet to see if it hit a coin
hit_list = arcade.check_for_collision_with_list(bullet, self.coin_list)
# If it did, get rid of the bullet
if len(hit_list) > 0:
bullet.remove_from_sprite_lists()
# For every coin we hit, add to the score and remove the coin
for coin in hit_list:
coin.remove_from_sprite_lists()
self.score += 1
# If the bullet flies off-screen, remove it.
if bullet.bottom > SCREEN_HEIGHT:
bullet.remove_from_sprite_lists()
We loop through each bullet with a for
loop. Then we check to see if the
bullet is hitting any of the coins. If it is, we get rid of the coin. We get
rid of the bullet.
We also check to see if the bullet flies off the top of the screen. If it does, we get rid of the bullet. This is easy to forget, but if you do, it will cause the computer to slow down because you are tracking thousands of bullets that have long ago left the space we care about.
Here’s the full example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | import random
import arcade
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
SPRITE_SCALING_LASER = 0.8
COIN_COUNT = 50
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
BULLET_SPEED = 5
class MyGame(arcade.Window):
""" Main application class. """
def __init__(self):
""" Initializer """
# Call the parent class initializer
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprites and Bullets Demo")
# Variables that will hold sprite lists
self.player_list = None
self.coin_list = None
self.bullet_list = None
# Set up the player info
self.player_sprite = None
self.score = 0
# Don't show the mouse cursor
self.set_mouse_visible(False)
arcade.set_background_color(arcade.color.AMAZON)
def setup(self):
""" Set up the game and initialize the variables. """
# Sprite lists
self.player_list = arcade.SpriteList()
self.coin_list = arcade.SpriteList()
self.bullet_list = arcade.SpriteList()
# Set up the player
self.score = 0
# Image from kenney.nl
self.player_sprite = arcade.Sprite("character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50
self.player_sprite.center_y = 70
self.player_list.append(self.player_sprite)
# Create the coins
for i in range(COIN_COUNT):
# Create the coin instance
# Coin image from kenney.nl
coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)
# Position the coin
coin.center_x = random.randrange(SCREEN_WIDTH)
coin.center_y = random.randrange(120, SCREEN_HEIGHT)
# Add the coin to the lists
self.coin_list.append(coin)
# Set the background color
arcade.set_background_color(arcade.color.AMAZON)
def on_draw(self):
"""
Render the screen.
"""
# This command has to happen before we start drawing
arcade.start_render()
# Draw all the sprites.
self.coin_list.draw()
self.bullet_list.draw()
self.player_list.draw()
# Render the text
arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE, 14)
def on_mouse_motion(self, x, y, dx, dy):
"""
Called whenever the mouse moves.
"""
self.player_sprite.center_x = x
def on_mouse_press(self, x, y, button, modifiers):
"""
Called whenever the mouse button is clicked.
"""
# Create a bullet
bullet = arcade.Sprite("laserBlue01.png", SPRITE_SCALING_LASER)
# The image points to the right, and we want it to point up. So
# rotate it.
bullet.angle = 90
# Position the bullet
bullet.center_x = self.player_sprite.center_x
bullet.bottom = self.player_sprite.top
# Add the bullet to the appropriate lists
self.bullet_list.append(bullet)
def update(self, delta_time):
""" Movement and game logic """
# Call update on all sprites
self.coin_list.update()
self.bullet_list.update()
# Loop through each bullet
for bullet in self.bullet_list:
# Check this bullet to see if it hit a coin
hit_list = arcade.check_for_collision_with_list(bullet, self.coin_list)
# If it did, get rid of the bullet
if len(hit_list) > 0:
bullet.remove_from_sprite_lists()
# For every coin we hit, add to the score and remove the coin
for coin in hit_list:
coin.remove_from_sprite_lists()
self.score += 1
# If the bullet flies off-screen, remove it.
if bullet.bottom > SCREEN_HEIGHT:
bullet.remove_from_sprite_lists()
def main():
window = MyGame()
window.setup()
arcade.run()
if __name__ == "__main__":
main()
|
24.7. Other Examples¶
Here are some other examples from Arcade Academy and its Example List: