The repository with the game (and some updates).
The Screen
Let’s start with making a window
import pygame as pg pg.init() screen = pg.display.set_mode((600, 400)) loop = 1 while loop: for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 pg.quit()
This is the way to make a window that you can close properly (without checking the QUIT action, you should force the closing of the window). There is nothing in the window, of course.
The Enemy
Let’s create an enemy with a simple class for position (x, y) and image (image). The sprite will have 3 attributes for now: x and y for the position (0, 0 is at the right left corner of the screen that is 800 px of width and 600 px of height… the 800 px is on the extreme right of the screen, the 600 px is at the bottom).
This is the class for the eneny
class Enemy: def __init__(self): self.x = 300 self.y = 10 self.go = 'right' self.image = pg.image.load("enemy.png") enemy = Enemy()
This is how to show the image on the screen
loop = 1 while loop: screen.blit(enemy.image, (enemy.x, enemy.y)) for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 pg.display.update() pg.quit()
This is the whole code for the moment
import pygame as pg pg.init() screen = pg.display.set_mode((600, 400)) # ==================== class Enemy: def __init__(self): self.x = 300 self.y = 10 self.go = 'right' self.image = pg.image.load("enemy.png") enemy = Enemy() # ==================== loop = 1 while loop: screen.blit(enemy.image, (enemy.x, enemy.y)) for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 pg.display.update() pg.quit()
This is the enemy image (use another image with the same name if you want something nicer).
and a little update of the enemy …
Moving the Alien aka the enemy
Now, we do not want the movement to be very complex, right? It is just a tutorial for a very basic stuff. Let’s give the alien/enemy the simplest movement ever. It will go from left to right and reappear on the left when he disappears on the right.
We will use this simple code in the while loop:
if enemy.x < 600: enemy.x += .05 else: enemy.x = -100
the while loop now is this (the first 15 lines are unchanged):
loop = 1 while loop: if enemy.x < 600: enemy.x += .05 else: enemy.x = -100 screen.blit(enemy.image, (enemy.x, enemy.y)) for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 pg.display.update() pg.quit()
Substitute the Enemy class with a Sprite class
Now we create a more abstract class for the sprites, so that you can use it also for the player, not only for the enemy. We rename the class Enemy to Sprite and we pass to it the name of the file image and the position (x, y), that can be different for the Enemy and the Sprite, of course.
<table>
<td><td>
</table>
class Sprite: def __init__(self, image, x, y): self.x = x self.y = y self.go = 'right' self.image = pg.image.load(image) # pass: image, starting x and y position enemy = Sprite("enemy.png", 300, 10) player = Sprite("player.png", 300, 350)
In the while loop we show the sprite like this:
screen.blit(enemy.image, (enemy.x, enemy.y)) screen.blit(player.image, (player.x, player.y))
The player image I ‘made’ is this (use your onw):
a “second version”
For the enemy nothing changed in the while loop. Now we have the player shown on the screen, but we cannot move it yet.
Moving the player
We need to move it with 2 keys… but we could also use the movement of the mouse?
loop = 1 while loop: if enemy.x < 600: enemy.x += .05 else: enemy.x = -100 if player.dir == "left": if player.x > 0: player.x -= .1 if player.dir == "right": if player.x < 560: player.x += .1 screen.blit(enemy.image, (enemy.x, enemy.y)) screen.blit(player.image, (player.x, player.y)) for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 if event.type == pg.KEYDOWN: keys = pg.key.get_pressed() if keys[K_LEFT]: player.dir = "left" if keys[K_RIGHT]: player.dir = "right" if event.type == pg.KEYUP: player.dir = "stop" pg.display.update() pg.quit()
Let’s fire: introducing another sprite, the bullet
Now we are going to fire, but we will not harm the enemy… yet. What we did is just create another sprite with the same class Sprite with a new image, in a position that is next to the top of the player starship and then move it together the ship, so that they seem the same object. Then when we press the up arrow key, the bullet is fired and goes up until the top. In the next paragraph we will see how to destroy the enemy ship.
import pygame as pg from pygame.locals import * pg.init() screen = pg.display.set_mode((600, 400)) # ==================== class Sprite: def __init__(self, img, x, y): self.x = x self.y = y self.dir = 'stop' self.image = pg.image.load(img) enemy = Sprite("enemy.png", 0, 10) player = Sprite("player.png", 250, 300) bullet = Sprite("bullet.png", 298, 295) loop = 1 # ==================== THE WHILE LOOP ======== while loop: screen.fill((0, 0, 0)) if enemy.x < 600: enemy.x += .1 else: enemy.x = -100 if bullet.dir == "up": bullet.y -= 1 if bullet.y < 0: bullet.y = 295 bullet.dir = "stop" if player.dir == "left": if player.x > 0: player.x -= .1 bullet.x -= .1 if player.dir == "right": if player.x < 495: player.x += .1 bullet.x += .1 screen.blit(enemy.image, (enemy.x, enemy.y)) screen.blit(player.image, (player.x, player.y)) screen.blit(bullet.image, (bullet.x, bullet.y)) for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 if event.type == pg.KEYDOWN: keys = pg.key.get_pressed() if keys[K_UP]: print("fire") bullet.dir = "up" if keys[K_RIGHT]: player.dir = "right" if keys[K_LEFT]: player.dir = "left" if event.type == pg.KEYUP: player.dir = "stop" pg.display.update() pg.quit()
Let’s check when the enemy is hit
Now we know when the enemy is hit. In the next paragraph we will make the enemy fall down, add sounds and increase score, making another enemy appear.
import pygame as pg from pygame.locals import * pg.init() screen = pg.display.set_mode((600, 400)) # ==================== class Sprite: def __init__(self, img, x, y): self.x = x self.y = y self.dir = 'stop' self.image = pg.image.load(img) self.w, self.h = self.image.get_rect().size self.update() def update(self): self.rect = pg.Rect(self.x, self.y, self.w, self.h) enemy = Sprite("enemy.png", 0, 10) player = Sprite("player.png", 250, 300) bullet = Sprite("bullet.png", 298, 295) loop = 1 # ==================== THE WHILE LOOP ======== while loop: screen.fill((0, 0, 0)) if enemy.x < 600: enemy.x += .1 else: enemy.x = -100 bullet.update() enemy.update() if bullet.dir == "up": bullet.y -= 1 if bullet.rect.colliderect(enemy.rect): print("You hit the enemy...good job!") bullet.y = 295 bullet.dir = "stop" if bullet.y < 0: bullet.y = 295 bullet.dir = "stop" if player.dir == "left": if player.x > 0: player.x -= .1 bullet.x -= .1 if player.dir == "right": if player.x < 495: player.x += .1 bullet.x += .1 screen.blit(enemy.image, (int(enemy.x), int(enemy.y))) screen.blit(player.image, (int(player.x), int(player.y))) screen.blit(bullet.image, (int(bullet.x), int(bullet.y))) for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 if event.type == pg.KEYDOWN: keys = pg.key.get_pressed() if keys[K_UP]: print("fire") bullet.dir = "up" if keys[K_RIGHT]: player.dir = "right" if keys[K_LEFT]: player.dir = "left" if event.type == pg.KEYUP: player.dir = "stop" pg.display.update() pg.quit()
The final stage… the game is here
Now, finally, the game is over.
import pygame as pg from pygame.locals import * from random import random, randrange pg.init() screen = pg.display.set_mode((600, 400)) # ==================== class Sprite: def __init__(self, img, x, y): self.x = x self.y = y self.dir = 'stop' self.image = pg.image.load(img) self.w, self.h = self.image.get_rect().size self.start = y self.update() def update(self): self.rect = pg.Rect(int(self.x), int(self.y), int(self.w), int(self.h)) enemy = Sprite("enemy.png", 0, 10) player = Sprite("player.png", 250, 350) bullet = Sprite("bullet.png", 280, 345) loop = 1 go = .1 score = 0 charged = 1 # ==================== THE WHILE LOOP ======== tragitto = 1000 count = tragitto # Whe the enemy's hit hit = 0 while loop: if hit == 1: enemy.y += .1 if enemy.y > 400: enemy.y = 10 enemy.x = randrange(1, 500) hit = 0 screen.fill((0, 0, 0)) count -= 1 if count == 0: if random() > .5: go = -.1 else: go = .1 count = tragitto enemy.x += go if enemy.x > 600: enemy.x = -100 if enemy.x < 0: enemy.x = 600 bullet.update() enemy.update() if bullet.dir == "up": bullet.y -= .1 if bullet.rect.colliderect(enemy.rect): score += 10 print("Score = " + str(score)) hit = 1 bullet.y = bullet.start bullet.dir = "stop" charged = 1 bullet.x = player.x + 30 elif bullet.y < 0: bullet.y = bullet.start bullet.x = player.x + 30 bullet.dir = "stop" charged = 1 if player.dir == "left": if player.x > 0: player.x -= .1 if bullet.dir == "stop": bullet.x -= .1 if player.dir == "right": if player.x < 495: player.x += .1 if bullet.dir == "stop": bullet.x += .1 screen.blit(enemy.image, (int(enemy.x), int(enemy.y))) screen.blit(player.image, (int(player.x), int(player.y))) screen.blit(bullet.image, (int(bullet.x), int(bullet.y))) for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 if charged: if event.type == pg.KEYDOWN: if event.key == K_UP: bullet.dir = "up" charged = 0 if pg.key.get_pressed(): keys = pg.key.get_pressed() # if keys[K_UP]: if keys[K_RIGHT]: player.dir = "right" if keys[K_LEFT]: player.dir = "left" # if event.type == pg.KEYUP: # player.dir = "stop" pg.display.update() pg.quit()
Making the ship stop… when you do not press the key
I decided to not make the ship move continuosly. In the code you can see the change is here:
if keys[K_RIGHT]: player.dir = "right" elif keys[K_LEFT]: player.dir = "left" else: player.dir = "stop"
So, if you press right or left it will go, otherwise player.dir will be set to “stop”, so it is neither right or left and it will not affect the change of the position on the x axe. Notice that now I put the images in the folder imgs, so to load them you have to put them into a folder called imgs or change the code pygame.image.load(“imgs/…”) without imgs/ at the start of the name of the file.
import pygame as pg from pygame.locals import * from random import random, randrange class Sprite: def __init__(self, img, x, y): self.x = x self.y = y self.dir = 'stop' self.image = pg.image.load(img) self.w, self.h = self.image.get_rect().size self.start = y self.update() def update(self): self.rect = pg.Rect(int(self.x), int(self.y), int(self.w), int(self.h)) pg.init() screen = pg.display.set_mode((600, 400)) # ============= SPRITES enemy = Sprite("imgs/enemy.png", 0, 10) player = Sprite("imgs/player.png", 250, 350) bullet = Sprite("imgs/bullet.png", 280, 345) # Movement speed go = .1 # The score score = 0 # When 1 you can fire the bullet charged = 1 # This is the time to randomly change enemy path direction tragitto = 1000 count = tragitto # Whe the enemy's hit hit = 0 # ==================== THE WHILE LOOP ======== loop = 1 while loop: if hit == 1: enemy.y += .1 if enemy.y > 400: enemy.y = 10 enemy.x = randrange(1, 500) screen.fill((0, 0, 0)) count -= 1 if count == 0: if random() > .5: go = -.1 else: go = .1 count = tragitto enemy.x += go if enemy.x > 600: enemy.x = -100 if enemy.x < 0: enemy.x = 600 bullet.update() enemy.update() if bullet.dir == "up": bullet.y -= .1 if bullet.rect.colliderect(enemy.rect): score += 10 print("Score = " + str(score)) hit = 1 bullet.y = bullet.start bullet.dir = "stop" charged = 1 bullet.x = player.x + 30 elif bullet.y < 0: bullet.y = bullet.start bullet.x = player.x + 30 bullet.dir = "stop" charged = 1 if player.dir == "left": if player.x > 0: player.x -= .1 if bullet.dir == "stop": bullet.x -= .1 if player.dir == "right": if player.x < 495: player.x += .1 if bullet.dir == "stop": bullet.x += .1 screen.blit(enemy.image, (int(enemy.x), int(enemy.y))) screen.blit(player.image, (int(player.x), int(player.y))) screen.blit(bullet.image, (int(bullet.x), int(bullet.y))) for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 if charged: if event.type == pg.KEYDOWN: if event.key == K_UP: bullet.dir = "up" charged = 0 if pg.key.get_pressed(): keys = pg.key.get_pressed() # if keys[K_UP]: if keys[K_RIGHT]: player.dir = "right" elif keys[K_LEFT]: player.dir = "left" else: player.dir = "stop" # if event.type == pg.KEYUP: # player.dir = "stop" pg.display.update() pg.quit()
The repository with the game stuffs
Depository updates
31.1.2020: you can find a version with audio in the folder sg3.
The version with sounds (of folder sg3 in the repository above).
import pygame as pg from pygame.locals import * from random import random, randrange class Sprite(pg.sprite.Sprite): def __init__(self, img, x, y): pg.sprite.Sprite.__init__(self) self.x = x self.y = y self.dir = 'stop' self.image = pg.image.load(img) self.w, self.h = self.image.get_rect().size self.start = y self.update() def update(self): self.rect = pg.Rect(int(self.x), int(self.y), int(self.w), int(self.h)) def music_init(): "Initialize sounds avoiding delay" pg.mixer.pre_init(44100, -16, 1, 512) pg.init() pg.mixer.quit() pg.mixer.init(22050, -16, 2, 512) pg.mixer.set_num_channels(32) music_init() screen = pg.display.set_mode((600, 400), pg.RESIZABLE) pg.display.set_caption("Game") clock = pg.time.Clock() # ============= SPRITES enemy = Sprite("imgs/enemy.png", 30, 50) player = Sprite("imgs/player.png", 250, 350) bullet = Sprite("imgs/bullet.png", 272, 345) # Movement speed go = 1 # The score score = 0 # When 1 you can fire the bullet charged = 1 # This is the time to randomly change enemy path direction tragitto = 100 count = tragitto # Whe the enemy's hit hit = 0 def game_sounds(): "Loads the sounds for the game" sounds_list = "fire", "hit" sound_dic = {} for sound in sounds_list: sound_path = f"audio/{sound}.wav" print(sound_path) sound_dic[sound] = pg.mixer.Sound(sound_path) return sound_dic sounds_dic = game_sounds() def create_fonts(font_sizes_list): fonts = [] for size in font_sizes_list: fonts.append(pg.font.SysFont("Arial", size)) return fonts def _display(fnt, what, color, where): text_to_show = fnt.render(what, 0, pg.Color(color)) screen.blit(text_to_show, where) def display_fps(): _display( fonts[0], what=str(int(clock.get_fps())), color="white", where=(0, 0)) def display_score(): _display( fonts[0], what="Score " + str(score), color="white", where=(300, 0)) fonts = create_fonts([32, 16, 14, 8]) sound = pg.mixer.Sound.play # ==================== THE WHILE LOOP ======== def enemy_back(): global hit enemy.y = 10 enemy.x = randrange(1, 500) hit = 0 loop = 1 while loop: # When enemy's hit falls down and can hit the player if hit == 1: sound(sounds_dic["hit"]) tragitto = 20 enemy.y += 1 # if bullet.rect.colliderect(enemy.rect): # score += 100 # enemy.y = 10 # enemy.x = randrange(1, 500) # hit = 0 # print("You killed it definitively") if enemy.rect.colliderect(player.rect): print("You died!") hit = 0 enemy.y = 10 enemy.x = randrange(1, 500) score -= 10 tragitto = 100 if enemy.y > 400: enemy.y = 10 enemy.x = randrange(1, 500) hit = 0 score -= 20 print("Your score is" + str(score)) print("Alien reached the Earth") tragitto = 100 if hit == 2: sound(sounds_dic["hit"]) print("You killed the alien") enemy.x = randrange(1, 500) enemy.y = 30 score += 50 hit = 0 tragitto = 100 screen.fill((0, 0, 0)) display_fps() display_score() count -= 1 if count == 0: if random() > .5: if enemy.x > 0: go = -1 else: if enemy.x < 600: go = 1 count = tragitto enemy.x += go # if enemy.x > 600: # enemy.x = -100 # if enemy.x < 0: # enemy.x = 600 bullet.update() enemy.update() player.update() if bullet.dir == "up": bullet.y -= 2 if bullet.rect.colliderect(enemy.rect): score += 10 print("Score = " + str(score)) hit += 1 bullet.y = bullet.start bullet.dir = "stop" charged = 1 bullet.x = player.x + 22 elif bullet.y < 0: bullet.y = bullet.start bullet.x = player.x + 22 bullet.dir = "stop" charged = 1 if player.dir == "left": if player.x > 0: player.x -= 1 if bullet.dir == "stop": bullet.x -= 1 if player.dir == "right": if player.x < 550: player.x += 1 if bullet.dir == "stop": bullet.x += 1 screen.blit(enemy.image, (int(enemy.x), int(enemy.y))) screen.blit(player.image, (int(player.x), int(player.y))) screen.blit(bullet.image, (int(bullet.x), int(bullet.y))) for event in pg.event.get(): if event.type == pg.QUIT: loop = 0 if charged: if event.type == pg.KEYDOWN: if event.key == K_UP: sound(sounds_dic["fire"]) bullet.dir = "up" charged = 0 if pg.key.get_pressed(): keys = pg.key.get_pressed() # if keys[K_UP]: if keys[K_RIGHT]: player.dir = "right" elif keys[K_LEFT]: player.dir = "left" else: player.dir = "stop" # if event.type == pg.KEYUP: # player.dir = "stop" clock.tick(240) pg.display.update() pg.quit()