python game development

python game development

Development environment: python3.7+pygame1.9.6

Compiling development software: pycharm2018.3

1, Window making of pygame

2, Game case 1: tank battle

3, Wizard test

4, Game case 2: greedy snake

5, Game case 3: Flying

6, Game case 4:2048

1, Window making of pygame

1. Install pygame

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pygame

2. Create pygame project test pygame window

pygame.init() #Reset pygame
pygame.display.set_mode((640,480))  #Set the window size to 640 * 480
pygame.display.set_caption("pygame")  #The window name is pygame

Test results:

Full code:

import pygame
from pygame.locals import *
import sys
def yx_pygame():
   pygame.init()
   pygame.display.set_mode((640,480))
   pygame.display.set_caption("pygame")
   while True:
       for event in pygame.event.get():
           if event.type==QUIT:
               pygame.quit()
               sys.exit()
           pygame.display.update()
if __name__=="__main__":
    yx_pygame()

2, Game case 1: tank battle

Use pygame to make tank game, so that the tank can control the movement according to the keyboard

Material required: Tank Photo

Operation result:

Reference code:

import os,sys,pygame
from pygame.locals import *
def control_tank(event):
    speed=[x,y]=[0,0]
    speed_offset=1
    if event.type==pygame.KEYDOWN:
        if event.key==pygame.K_LEFT:
            speed[0]-=speed_offset
        if event.key==pygame.K_RIGHT:
            speed[0]=speed_offset
        if event.key==pygame.K_UP:
            speed[1]-=speed_offset
        if event.key==pygame.K_DOWN:
            speed[1]=speed_offset
    if event.type==pygame.KEYUP:
        if event.type in[pygame.K_UP,pygame.K_DOWN,pygame.K_RIGHT,pygame.K_LEFT]:
            speed=[0,0]
    return speed
def play_tank():
    pygame.init()
    window_size=Rect(0,0,640,480)
    speed=[1,1]
    color_white=(255,255,255)
    screen=pygame.display.set_mode(window_size.size)
    pygame.display.set_caption("Tank Battle")
    tank_image=pygame.image.load('tankU.bmp')
    back_image=pygame.image.load('back_image.jpg')
    tank_rect=tank_image.get_rect()
    while True:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                pygame.quit()
                sys.exit()
            cur_speed=control_tank(event)
            tank_rect=tank_rect.move(cur_speed).clamp(window_size)
            screen.blit(back_image,(0,0))
            screen.blit(tank_image,tank_rect)
            pygame.display.update()
if __name__ == "__main__":
    play_tank()

3, Wizard test

Test results:

Reference code:

import pygame
from pygame.locals import *
class MySprite(pygame.sprite.Sprite):
    def __init__(self,target):
        pygame.sprite.Sprite.__init__(self)
        self.sprite_surface=target
        self.image=None
        self.master_image=None
        self.rect=None
        self.topleft=0,0
        self.frame=0
        self.old_fram=-1
        self.fram_width=1
        self.fram_height=1
        self.first_fram=0
        self.last_fram=0
        self.columns=1
        self.last_time=0
    def load(self,filename,width,height,columns):
        self.master_image=pygame.image.load(filename).convert_alpha()
        self.fram_width=width
        self.fram_height=height
        self.rect=0,0,width,height
        self.columns=columns
        rect=self.master_image.get_rect()
        self.last_fram=(rect.width//width)*(rect.height//height)-1
    def update(self,current_time,rate=60):
        if current_time>self.last_time+rate:
            self.frame+=1
        if self.frame>self.last_fram:
            self.frame=self.first_fram
            self.last_time=current_time
        if self.frame!=self.old_fram:
            frame_x=(self.frame%self.columns)*self.fram_width
            frame_y=(self.frame//self.columns)*self.fram_height
            rect=(frame_x,frame_y,self.fram_width,self.fram_height)
            self.image=self.master_image.subsurface(rect)
            self.old_fram=self.frame

pygame.init()
screen=pygame.display.set_mode((800,600),0,32)
pygame.display.set_caption("Wizard test")
font=pygame.font.Font(None,18)
framerate=pygame.time.Clock()
cat=MySprite(screen)
cat.load("sprite2.png",92,95,4)
group=pygame.sprite.Group()
group.add(cat)
while True:
    framerate.tick(10)
    ticks=pygame.time.get_ticks()
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()
            exit()
        key=pygame.key.get_pressed()
        if key[pygame.K_ESCAPE]:
           exit()
    screen.fill((0,0,255))

    cat.update(ticks)
    screen.blit(cat.image,cat.rect)
    pygame.display.update()

4, Game case 2: greedy snake

Case effect: through the key input of the keyboard to control the snake's movement to eat food. When the snake touches the external wall, the game ends

Design idea:

1. Set the initial position of the object

2. Judge whether to eat food, 1 for eating, 0 for not eating

3. Control the movement direction of the greedy snake, and add a section of the snake's body if it is eaten (judge whether the coordinates of the head of the snake are equal to the coordinates of the food)

4. Set game interface

Operation result:

Reference code:

import pygame,sys,time,random
from pygame.locals import *
pygame.init()
fpsClock=pygame.time.Clock()
playSurface=pygame.display.set_mode((640,480))
pygame.display.set_caption("Snake game")
redColor=pygame.Color(255,0,0)
blackColor=pygame.Color(0,0,0)
whiteColor=pygame.Color(255,255,255)
greyColor=pygame.Color(150,150,150)
snakePosition=[100,100]
snakeSegments=[[100,100],[80,100],[60,100]]
raspberryPosition=[300,300]
raspberrySpawned=1
direction='right'
changeDirection=direction

def gameOver():
    gameOverFont=pygame.font.Font('simfang.ttf',72)
    gameOverSurf=gameOverFont.render('Game Over',True,greyColor)
    gameOverRect=gameOverSurf.get_rect()
    gameOverRect.midtop=(320,10)
    playSurface.blit(gameOverSurf,gameOverRect)
    pygame.display.flip()
    time.sleep(5)
    pygame.quit()
    sys.exit()

while True:
    for event in pygame.event.get():
        if event.type==QUIT:
            pygame.quit()
            sys.exit()
        elif event.type==KEYDOWN:
            if event.key==K_RIGHT or event.key==ord('d'):
                changeDirection='right'
            if event.key==K_LEFT or event.key==ord('a'):
                changeDirection='left'
            if event.key==K_UP or event.key==ord('w'):
                changeDirection='up'
            if event.key==K_DOLLAR or event.key==ord('s'):
                changeDirection='down'
            if event.key==K_ESCAPE:
                pygame.event.post(pygame.event.Event(QUIT))
    if changeDirection=='right' and not direction=='left':
        direction=changeDirection
    if changeDirection=='left' and not direction=='right':
        direction=changeDirection
    if changeDirection=='up' and not direction=='down':
        direction=changeDirection
    if changeDirection=='down' and not direction=='up':
        direction=changeDirection
    if direction=='right':
        snakePosition[0]+=20
    if direction=='left':
        snakePosition[0]-=20
    if direction=='up':
        snakePosition[1]-=20
    if direction=='down':
        snakePosition[1]+=20

    snakeSegments.insert(0,list(snakePosition))
    if snakePosition[0]==raspberryPosition[0] and snakePosition[1]==raspberryPosition[1]:
        raspberrySpawned=0
    else:
        snakeSegments.pop()
    if raspberrySpawned==0:
        x=random.randrange(1,32)
        y=random.randrange(1,24)
        raspberryPosition=[int(x*20),int(y*20)]
    raspberrySpawned=1
    playSurface.fill(blackColor)
    for position in snakeSegments:
        pygame.draw.rect(playSurface,whiteColor,Rect(position[0],position[1],20,20))
    pygame.draw.rect(playSurface,redColor,Rect(raspberryPosition[0],raspberryPosition[1],20,20))
    pygame.display.flip()
    if snakePosition[0]>620 or snakePosition[0] < 0:
        gameOver()
    if snakePosition[1] > 460 or snakePosition[1] < 0:
        gameOver()
    for snakeBody in snakeSegments[1:]:
        if snakePosition[0]==snakeBody[0] and snakePosition[1]==snakeBody[1]:
            gameOver()
    fpsClock.tick(10)

5, Game case 3: Flying

Operation result:

design process

Initialization:

SCREEN_WIDTH=480
SCREEN_HEIGHT = 800
TYPE_SMALL=1
TYPE_MIDDLE=2
TYPE_BIG=3

Definition class:

Bullet class:
def __init__(self, bullet_img, init_pos):
    pygame.sprite.Sprite.__init__(self)
    self.image = bullet_img
    self.rect = self.image.get_rect()
    self.rect.midbottom = init_pos
    self.speed = 10
Game player:
def __init__(self, plane_img, player_rect, init_pos):
    pygame.sprite.Sprite.__init__(self)
    self.image = []                                 # List used to store player's plane pictures
    for i in range(len(player_rect)):
        self.image.append(plane_img.subsurface(player_rect[i]).convert_alpha())
    self.rect = player_rect[0]                      # Initialize the rectangle of the picture
    self.rect.topleft = init_pos                    # Initialize the coordinates of the upper left corner of the rectangle
    self.speed = 8                                  # Initialize the player's aircraft speed. Here is a certain value
    self.bullets = pygame.sprite.Group()            # A collection of bullets fired by a player's plane
    self.is_hit = False     
Enemy human:
class Enemy(pygame.sprite.Sprite):
     def __init__(self, enemy_img, enemy_down_imgs, init_pos):
         pygame.sprite.Sprite.__init__(self)
         self.image = enemy_img
         self.rect = self.image.get_rect()
         self.rect.topleft = init_pos
         self.down_imgs = enemy_down_imgs
         self.speed = 2


     def move(self):
         self.rect.top += self.speed

Reference code:

import pygame
from sys import exit
from pygame.locals import *
import random
SCREEN_WIDTH=480
SCREEN_HEIGHT = 800
TYPE_SMALL=1
TYPE_MIDDLE=2
TYPE_BIG=3

class Bullet(pygame.sprite.Sprite):
    def __init__(self, bullet_img, init_pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = bullet_img
        self.rect = self.image.get_rect()
        self.rect.midbottom = init_pos
        self.speed = 10

    def move(self):
       self.rect.top -= self.speed

class Player(pygame.sprite.Sprite):
     def __init__(self, plane_img, player_rect, init_pos):
         pygame.sprite.Sprite.__init__(self)
         self.image = []                                 # List used to store player's plane pictures
         for i in range(len(player_rect)):
             self.image.append(plane_img.subsurface(player_rect[i]).convert_alpha())
         self.rect = player_rect[0]                      # Initialize the rectangle of the picture
         self.rect.topleft = init_pos                    # Initialize the coordinates of the upper left corner of the rectangle
         self.speed = 8                                  # Initialize the player's aircraft speed. Here is a certain value
         self.bullets = pygame.sprite.Group()            # A collection of bullets fired by a player's plane
         self.is_hit = False                             # Is the player hit

     # Bullet launch
     def shoot(self, bullet_img):
         bullet = Bullet(bullet_img, self.rect.midtop)
         self.bullets.add(bullet)

     # Move up, you need to judge the boundary
     def moveUp(self):
        if self.rect.top <= 0:
            self.rect.top = 0
        else:
             self.rect.top -= self.speed

     # Move down, you need to judge the boundary
     def moveDown(self):
         if self.rect.top >= SCREEN_HEIGHT - self.rect.height:
             self.rect.top = SCREEN_HEIGHT - self.rect.height
         else:
             self.rect.top += self.speed

     # Move left, need to judge the boundary
     def moveLeft(self):
         if self.rect.left <= 0:
             self.rect.left = 0
         else:
             self.rect.left -= self.speed

     # Move right, need to judge boundary
     def moveRight(self):
         if self.rect.left >= SCREEN_WIDTH - self.rect.width:
             self.rect.left = SCREEN_WIDTH - self.rect.width
         else:
             self.rect.left += self.speed

class Enemy(pygame.sprite.Sprite):
     def __init__(self, enemy_img, enemy_down_imgs, init_pos):
         pygame.sprite.Sprite.__init__(self)
         self.image = enemy_img
         self.rect = self.image.get_rect()
         self.rect.topleft = init_pos
         self.down_imgs = enemy_down_imgs
         self.speed = 2


     def move(self):
         self.rect.top += self.speed

pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Python Fight a plane battle')


background = pygame.image.load('resources/image/background.png').convert()

game_over = pygame.image.load('resources/image/gameover.png')


plane_img = pygame.image.load('resources/image/shoot.png')

player_rect = []
player_rect.append(pygame.Rect(0, 99, 102, 126))        # Player plane picture
player_rect.append(pygame.Rect(165, 234, 102, 126))     # Player explosion picture

player_pos = [200, 600]
player = Player(plane_img, player_rect, player_pos)


bullet_rect = pygame.Rect(1004, 987, 9, 21)
bullet_img = plane_img.subsurface(bullet_rect)


enemy1_rect = pygame.Rect(534, 612, 57, 43)
enemy1_img = plane_img.subsurface(enemy1_rect)
enemy1_down_imgs = plane_img.subsurface(pygame.Rect(267, 347, 57, 43))


enemies1 = pygame.sprite.Group()


enemies_down = pygame.sprite.Group()


shoot_frequency = 0
enemy_frequency = 0


score = 0

clock = pygame.time.Clock()


running = True


while running:

    clock.tick(60)
    if not player.is_hit:
        if shoot_frequency % 15 == 0:
            player.shoot(bullet_img)
        shoot_frequency += 1
        if shoot_frequency >= 15:
            shoot_frequency = 0


    if enemy_frequency % 50 == 0:
        enemy1_pos = [random.randint(0, SCREEN_WIDTH - enemy1_rect.width), 0]
        enemy1 = Enemy(enemy1_img, enemy1_down_imgs, enemy1_pos)
        enemies1.add(enemy1)
    enemy_frequency += 1
    if enemy_frequency >= 100:
        enemy_frequency = 0

    for bullet in player.bullets:
        # Moving bullets at a fixed speed
        bullet.move()
        # Remove bullets after moving out of the screen
        if bullet.rect.bottom < 0:
            player.bullets.remove(bullet)

    for enemy in enemies1:
        #2. Move enemy aircraft
        enemy.move()
        #3. Handling of collision effect between enemy aircraft and player aircraft
        if pygame.sprite.collide_circle(enemy, player):
            enemies_down.add(enemy)
            enemies1.remove(enemy)
            player.is_hit = True
            break
        #4. Delete enemies after moving out of the screen
        if enemy.rect.top < 0:
            enemies1.remove(enemy)

    #How to deal with the effect of enemy aircraft being hit by bullets
    #Add the hit enemy object to the destroy enemy Group
    enemies1_down = pygame.sprite.groupcollide(enemies1, player.bullets, 1, 1)
    for enemy_down in enemies1_down:
        enemies_down.add(enemy_down)

    # Drawing background
    screen.fill(0)
    screen.blit(background, (0, 0))

    # Draw player plane
    if not player.is_hit:
        screen.blit(player.image[0], player.rect) #Draw the normal plane
    else:
        # Effect processing after player's plane is hit
        screen.blit(player.image[1], player.rect) #Draw the exploded plane
        running = False

    # Display of the effect of enemy aircraft being hit by bullets
    for enemy_down in enemies_down:
        enemies_down.remove(enemy_down)
        score += 1
        screen.blit(enemy_down.down_imgs, enemy_down.rect) #Draw out the exploded enemy plane


    # Display bullets
    player.bullets.draw(screen)
    # Display enemy planes
    enemies1.draw(screen)
    # Draw score
    score_font = pygame.font.Font(None, 36)
    score_text = score_font.render('score: '+str(score), True, (128, 128, 128))
    text_rect = score_text.get_rect()
    text_rect.topleft = [10, 10]
    screen.blit(score_text, text_rect)

    pygame.display.update()

    # Process game exit
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()

    # Get keyboard events (up, down, left and right buttons)
    key_pressed = pygame.key.get_pressed()

    # Handle keyboard events (move aircraft position)
    if key_pressed[K_w] or key_pressed[K_UP]:
        player.moveUp()
    if key_pressed[K_s] or key_pressed[K_DOWN]:
        player.moveDown()
    if key_pressed[K_a] or key_pressed[K_LEFT]:
        player.moveLeft()
    if key_pressed[K_d] or key_pressed[K_RIGHT]:
        player.moveRight()

# Show final score after Game Over
font = pygame.font.Font(None, 64)
text = font.render('Final Score: '+ str(score), True, (255, 0, 0))
text_rect = text.get_rect()
text_rect.centerx = screen.get_rect().centerx
text_rect.centery = screen.get_rect().centery + 24
screen.blit(game_over, (0, 0))
screen.blit(text, text_rect)

# Show score and process game exit
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    pygame.display.update()

6, Game case 4:2048

Game method: use keyboard input to control the movement of blocks. Adjacent and the same blocks can be added. When the screen is full and there are no adjacent and the same blocks, the game ends

1. Game interface settings:

PIXEL = 150
SCORE_PIXEL = 100
SIZE = 4
screen = pygame.display.set_mode((PIXEL * SIZE, PIXEL * SIZE + SCORE_PIXEL))
pygame.display.set_caption("2048")
block = [pygame.Surface((PIXEL, PIXEL)) for i in range(4)]
# Set color
block[0].fill((152, 251, 152))
block[1].fill((240, 255, 255))
block[2].fill((0, 255, 127))
block[3].fill((225, 255, 255))
score_block = pygame.Surface((PIXEL * SIZE, SCORE_PIXEL))
score_block.fill((245, 245, 245))
# Set font
map_font = pygame.font.Font(None, PIXEL)
score_font = pygame.font.Font(None, SCORE_PIXEL)
clock = pygame.time.Clock()
show(map)

2. Use the keyboard to control the game:

pressed_keys = pygame.key.get_pressed()
if pressed_keys[K_w] or pressed_keys[K_UP]:
    map.moveUp()
elif pressed_keys[K_s] or pressed_keys[K_DOWN]:
    map.moveDown()
elif pressed_keys[K_a] or pressed_keys[K_LEFT]:
    map.moveLeft()
elif pressed_keys[K_d] or pressed_keys[K_RIGHT]:
    map.moveRight()

3. End of game:

def over(self):
    for r in range(self.size):
        for c in range(self.size):
            if self.map[r][c] == 0:
                return False
    for r in range(self.size):
        for c in range(self.size - 1):
            if self.map[r][c] == self.map[r][c + 1]:
                return False
    for r in range(self.size - 1):
        for c in range(self.size):
            if self.map[r][c] == self.map[r + 1][c]:
                return False
    return True

Running screenshot:

Reference code:

import random
import sys
import pygame
from pygame.locals import *

PIXEL = 150
SCORE_PIXEL = 100
SIZE = 4


# Class of map
class Map:
    def __init__(self, size):
        self.size = size
        self.score = 0
        self.map = [[0 for i in range(size)] for i in range(size)]
        self.add()
        self.add()

    # Add 2 or 4, with 1 / 4 probability to produce 4
    def add(self):
        while True:
            p = random.randint(0, self.size * self.size - 1)
            if self.map[p // self.size][p % self.size] == 0:
                x = random.randint(0, 3) > 0 and 2 or 4
                self.map[p // self.size][p % self.size] = x
                self.score += x
                break

    # The map moves to the left, and other directions can be moved by proper rotation to return whether the map is updated or not
    def adjust(self):
        changed = False
        for a in self.map:
            b = []
            last = 0
            for v in a:
                if v != 0:
                    if v == last:
                        b.append(b.pop() << 1)
                        last = 0
                    else:
                        b.append(v)
                        last = v
            b += [0] * (self.size - len(b))
            for i in range(self.size):
                if a[i] != b[i]:
                    changed = True
            a[:] = b
        return changed

    # Rotate the map 90 degrees counter clockwise
    def rotate90(self):
        self.map = [[self.map[c][r] for c in range(self.size)] for r in reversed(range(self.size))]

    # Judge the end of the game
    def over(self):
        for r in range(self.size):
            for c in range(self.size):
                if self.map[r][c] == 0:
                    return False
        for r in range(self.size):
            for c in range(self.size - 1):
                if self.map[r][c] == self.map[r][c + 1]:
                    return False
        for r in range(self.size - 1):
            for c in range(self.size):
                if self.map[r][c] == self.map[r + 1][c]:
                    return False
        return True

    def moveUp(self):
        self.rotate90()
        if self.adjust():
            self.add()
        self.rotate90()
        self.rotate90()
        self.rotate90()

    def moveRight(self):
        self.rotate90()
        self.rotate90()
        if self.adjust():
            self.add()
        self.rotate90()
        self.rotate90()

    def moveDown(self):
        self.rotate90()
        self.rotate90()
        self.rotate90()
        if self.adjust():
            self.add()
        self.rotate90()

    def moveLeft(self):
        if self.adjust():
            self.add()


# Update screen
def show(map):
    for i in range(SIZE):
        for j in range(SIZE):
            # Background color block
            screen.blit(map.map[i][j] == 0 and block[(i + j) % 2] or block[2 + (i + j) % 2], (PIXEL * j, PIXEL * i))
            # Numerical display
            if map.map[i][j] != 0:
                map_text = map_font.render(str(map.map[i][j]), True, (106, 90, 205))
                text_rect = map_text.get_rect()
                text_rect.center = (PIXEL * j + PIXEL / 2, PIXEL * i + PIXEL / 2)
                screen.blit(map_text, text_rect)
    # Score display
    screen.blit(score_block, (0, PIXEL * SIZE))
    score_text = score_font.render((map.over() and "Game over with score " or "Score: ") + str(map.score), True,
                                   (106, 90, 205))
    score_rect = score_text.get_rect()
    score_rect.center = (PIXEL * SIZE / 2, PIXEL * SIZE + SCORE_PIXEL / 2)
    screen.blit(score_text, score_rect)
    pygame.display.update()


map = Map(SIZE)
pygame.init()
screen = pygame.display.set_mode((PIXEL * SIZE, PIXEL * SIZE + SCORE_PIXEL))
pygame.display.set_caption("2048")
block = [pygame.Surface((PIXEL, PIXEL)) for i in range(4)]
# Set color
block[0].fill((152, 251, 152))
block[1].fill((240, 255, 255))
block[2].fill((0, 255, 127))
block[3].fill((225, 255, 255))
score_block = pygame.Surface((PIXEL * SIZE, SCORE_PIXEL))
score_block.fill((245, 245, 245))
# Set font
map_font = pygame.font.Font(None, PIXEL)
score_font = pygame.font.Font(None, SCORE_PIXEL)
clock = pygame.time.Clock()
show(map)

while not map.over():
    # 12 is the experimental parameter
    clock.tick(12)
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
    # Receive player action
    pressed_keys = pygame.key.get_pressed()
    if pressed_keys[K_w] or pressed_keys[K_UP]:
        map.moveUp()
    elif pressed_keys[K_s] or pressed_keys[K_DOWN]:
        map.moveDown()
    elif pressed_keys[K_a] or pressed_keys[K_LEFT]:
        map.moveLeft()
    elif pressed_keys[K_d] or pressed_keys[K_RIGHT]:
        map.moveRight()
    show(map)

# Game over
pygame.time.delay(3000)

Tags: Python pip

Posted on Fri, 13 Mar 2020 08:01:26 -0700 by akano