Python game project - Alien Invasion

1, Install Pygame

Enter at the terminal:

pip install --user pygame

2, Start game project

(1) Create Pygame window and respond to user input

Create a file named alien_ The file of invasion.py is the main running file of the program.

import sys

import pygame

class AlienInvasion:
    def __init__(self):
        pygame.init()  # Initialize the game and create game resources
        self.screen = pygame.display.set_mode((1200, 800))  # Set game screen size
        pygame.display.set_caption("Alien Invasion")  # Set game name
        self.bg_color = (230, 230, 230)  # Set background color

    def run_game(self):
        while True:
            for event in pygame.event.get():  # Monitor keyboard and mouse
                if event.type == pygame.QUIT:  # Is the close key pressed
                    sys.exit()  # Exit the game

            self.screen.fill(self.bg_color)  # Cycle through the screen each time
            pygame.display.flip()  # Update screen


if __name__ == '__main__':
    ai = AlienInvasion()
    ai.run_game()

(2) Create settings class

Create a file named settings.py to import new settings when new features are added to the game. Also put the color, size, etc. we set above into this file:

class Settings:

    def __init__(self):
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)

(3) Add ship image

Create a new Images folder and add the ship file ship.bmp to it.

 

class Ship:
    def __init__(self, ai_game):
        self.screen = ai_game.screen  # Initialize spacecraft
        self.screen_rect = ai_game.screen.get_rect()  # Set initial position

        self.image = pygame.image.load('Images/ship.bmp')  # import images
        self.rect = self.image.get_rect()  # Specify ship location

        self.rect.midbottom = self.screen_rect.midbottom  # Put it in the center at the bottom of the screen

    def blitme(self):
        self.screen.blit(self.image, self.rect)

  Then write it into the main function and click Run to see the spacecraft in the center of the screen:

 

(4) Mobile spacecraft

Make it move continuously: when pressed, trigger a flag bit to true. Supplementary points:

KEYDOWN: triggered when the user presses any key on the keyboard.

KEYUP: triggered when the user releases the key on the keyboard.

In check_ Add to event:

def _check_event(self):
    for event in pygame.event.get():  # Monitor keyboard and mouse
        if event.type == pygame.QUIT:  # Is the close key pressed
        sys.exit()  # Exit the game
    elif event.type == pygame.KEYDOWN:
        if event.key == pygame.K_RIGHT:
        self.ship.moving_right = True
    elif event.type == pygame.KEYUP:
        if event.key == pygame.K_RIGHT:
        self.ship.moving_right = False

  The flag bit added is self.ship.moving_right, respond when the user presses the right button, set it to False when it is released, and add an update function to the class of the spacecraft:

def update(self):
    if self.moving_right:
        self.rect.x += 1

Similarly, we can set up, down, left and right buttons, and set them not to exceed the screen size:

def update(self):
        if self.moving_right and self.rect.right < self.screen_rect.right:
            self.rect.x += 1
        elif self.moving_left and self.rect.left > 0:
            self.rect.x -= 1
        elif self.moving_up:
            self.rect.y -= 1
        elif self.moving_down:
            self.rect.y += 1
    def _check_event(self):
        for event in pygame.event.get():  # Monitor keyboard and mouse
            if event.type == pygame.QUIT:  # Is the close key pressed
                sys.exit()  # Exit the game
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    self.ship.moving_right = True
                elif event.key == pygame.K_LEFT:
                    self.ship.moving_left = True
                elif event.key == pygame.K_UP:
                    self.ship.moving_up = True
                elif event.key == pygame.K_DOWN:
                    self.ship.moving_down = True
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    self.ship.moving_right = False
                elif event.key == pygame.K_LEFT:
                    self.ship.moving_left = False
                elif event.key == pygame.K_UP:
                    self.ship.moving_up = False
                elif event.key == pygame.K_DOWN:
                    self.ship.moving_down = False

You can also set the speed of the spaceship, and add in the settings:

#Spacecraft speed
        self.ship_speed = 1.5

After that, change 1 in the update speed to self.settings.ship_ Before replacing the speed, do the following:

(5) Press Q to exit the game

Add the following statement to the operation of pressing the key:

                elif event.key == pygame.K_q:
                    sys.exit()

  (6) Full screen game

        # display
        # self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))  # Set game screen size
        self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
        self.settings.screen_width = self.screen.get_rect().width
        self.settings.screen_height = self.screen.get_rect().height

Mask the initial display, and then add the above three sentences.

(7) Add Bullet class

import pygame
from pygame.sprite import Sprite

class Bullet(Sprite)

    def __init__(self,ai_game):
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.color = self.settings.bullet_color

        self.rect = pygame.Rect(0,0,self.settings.bullet_width,self.settings.screen_height)  #Create a rectangle representing the bullet at (0, 0) and set the correct position
        self.rect.midtop = ai_game.ship.rect.midtop #Located in the middle and upper part of the spacecraft

        self.y = float(self.rect.y)

    def update(self):
        self.y -= self.settings.bullet_speed    #Move the bullet up
        self.rect.y = self.y

    def draw_bullet(self):
        pygame.draw.rect(self.screen,self.color,self.rect)  #Draw bullets

  After that, create a group for storing bullets in the function:

This group is used to store all valid bullets in order to manage the bullets fired. It is an instance of the pyGame. Sprite. Group class. pygame.sprite.Group is similar to a list, but provides additional features to help develop games. In the main loop, this group is used to draw bullets on the screen and update the position of each bullet.

(8) Fire

When the space button is pressed, a bullet is created and fired. Write when pressed:

                elif event.key == pygame.K_SPACE:
                    self._fire_bullet()

  Then define a new method:

    def _fire_bullet(self):
        new_bullet = Bullet(self)
        self.bullets.add(new_bullet)

The method add () is similar to append (), but is written specifically for Pygame marshalling.

Finally, to display the bullet, we need to write in the update screen:

        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

The method bullets.sprites() returns a list containing all the sprites in the grouped bullets. To draw and fire all bullets on the screen, traverse the sprites in the group bullets, and then call draw_bullet().

(9) Delete missing bullets

At present, the bullet will disappear at the top of the screen, but it does not mean that it has been deleted, because our screen does not contain them, they still exist. Their y-axis coordinates will get smaller and smaller. For the screen we built, the coordinates in the upper left corner are (0, 0), and the lower right corner is the width and height we set.

We need to delete the missing bullets, otherwise the game will do more and more unnecessary work, and the process will be slower and slower. When it reaches the top, the bullet's button value will be equal to 0.

New method:

    def _delete_bullet(self):
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)

When traversing a list using a for loop, python requires that the length of the list remain unchanged throughout the loop, so you need to make a copy. Use the method copy () to set the for loop, and delete the original bullet. Finally, run_game can be called.

(10) Limit the number of bullets

Add in setting:

self.bullets_allowed = 10

  Limit the maximum number of bullets to 10. Add the following to the function generating bullets:

    def _fire_bullet(self):
        if len(self.bullets) < self.settings.self.bullets_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

(11) Add aliens

Create the file alien.py. And write Alien classes to add Alien images.

import pygame
from pygame.sprite import Sprite


class Alien(Sprite):

    def __init__(self, ai_game):
        super.__init__()
        self.screen = ai_game.screen
        self.image = pygame.image.load('Images/alien.png')
        self.rect = self.image.get_rect()
        
        #Each alien was initially attached in the upper left corner of the screen
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height
        
        #Store the exact horizontal position of aliens
        self.x = float(self.rect.x)

  Back to alien_ Modification in invasion.py:

  Add method:

    def _creat_fleet(self):
        alien = Alien(self)
        self.aliens.add(alien)

Then add in the update screen:

  Then you can see the appearance of aliens on the screen:

(12) Create a group of Aliens

In order to set the space and width of aliens, we calculate the space between aliens and then display it.

Modify the generated function to:

    def _creat_fleet(self):
        alien = Alien(self)
        alien_width = alien.rect.width
        available_space_x = self.settings.screen_width - (2*alien_width)
        number_aliens_x = available_space_x // (2*alien_width)
        for alien_number in range(number_aliens_x):
            alien = Alien(self)
            alien.x = alien_width + 2*alien_width*alien_number
            alien.rect.x = alien.x
            self.aliens.add(alien)

After completing the work of rows, do the work of columns:

    def _creat_fleet(self):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size

        # Calculation line
        available_space_x = self.settings.screen_width - (2 * alien_width)
        number_aliens_x = available_space_x // (2 * alien_width)

        # Calculation column
        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height - (3 * alien_height) - ship_height)
        number_rows = available_space_y // (2 * alien_height)
        
        for row_number in range(number_rows):
            for alien_number in range(number_aliens_x):
                self._creat_alien(alien_number,row_number)

Finally, a display method is designed to input the calculated columns and rows into the method:

    def _creat_alien(self, alien_number, row_number):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)

The last image displayed is as follows:

 

(13) Make aliens move

Add the alien movement speed setting in setting.py and alien.py

self.settings = ai_game.settings

  Can be referenced. Then write alien movement:

    def update(self):
        self.x += self.settings.alien_speed
        self.rect.x = self.x

Then put it in the main function and update it. After running this code, the alien will disappear on the right edge:

 

(14) Make aliens move down when they reach the edge

Setting to make aliens move down and then left after hitting the right edge of the screen.

We need to set the following variables:

 

  Edge function detected:

    def check_edges(self):
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right or self.rect <= 0:
            return True

Finally, let's write another way to move down and change the direction of alien movement:

    def _check_fleet_edges(self):
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

In this way, the function of aliens moving down can be realized.

(15) Collision detection

 collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)

The function sprite. Groupcollapse () compares the rect of each element in one group with the rect of each element in another group, and returns a dictionary in which each key is a bullet, and the associated value is the alien hit by the bullet. Set to True to delete, False to retain.

At this point, if you don't shoot aliens, you will go all the way down and finally disappear at the bottom. When a bullet hits an alien, both the alien and the bullet disappear.

Keywords: Python Pycharm pygame

Added by jtjohnson260 on Tue, 23 Nov 2021 05:01:14 +0200