[PYTHON] Create a game UI from scratch with pygame2!

Overview

This article is the 14th day article of Future Advent Calendar 2019. Yesterday's article was by @RuyPKG Even newcomers want to have fun! ~ Preparation of minutes ~.

The other day, at an in-house study session, @shibukawa introduced the game engine, which was the reason for writing this article. I wanted a board game UI implemented in Python, and it was difficult to express the movement with HTML expression, so I decided to touch pygame, which is a Python game engine.

What is pygame

A cross-platform game engine that can be run on Python. If you can write the graphic part of the game in Python, it is very convenient because you can embed the game logic written in Python as it is.

Regarding this pygame, development stopped once in 2009 and it has not been running for a while, so many people who know pygame may have switched. However, development for the release of pygame2 will be active in 2019, and it is likely that this version of pygame2 will be released within the next year. Starting with 2.0.0.dev6, python3.8 is also supported and I'm looking forward to it. I feel that it will attract attention in the future.

environment

Environment

Refer to the official pygame Getting Started to proceed with the environment construction.

Install pygame via pip. At this time, if you do not specify the version, the latest stable version 1.9.6 will be included, so be careful. (1.9.6 only supports up to python3.6)

pip install pygame==2.0.0.dev6

Try moving the sample

Many sample games are included in pygame. Let's try one.

python -m pygame.examples.aliens
Screen Shot 2019-12-14 at 19.40.09.png

Something like an Invaders game has been run! A list of samples and what kind of game each is in README of git example folder, so it is interesting to try various things.

Make a sample from 1

While deciphering the sample, I will draw the code myself. This time, I will aim for a sample that just writes characters in the background.

Process flow

Unlike the static screen, when drawing with the game engine, it is necessary to update the screen at high speed. Therefore, the process is performed as follows.

  1. Initialization of image loading, etc.
  2. Clear the screen and draw the background image
  3. Update the position and value of the object displayed on the screen and draw
  4. Reflection of screen updates
  5. Return to 2

In the game engine, the objects displayed on the screen are drawn using sprites, so they are drawn at the time of implementation using a class that inherits the sprite class. If you're curious about sprites, check them out. It is interesting because there is a historical background such as the story of hardware implementation to speed up drawing, but I think that there is no particular problem even if you do not know it.

import os
import pygame as pg

# game constants
SCREENRECT = pg.Rect(0, 0, 640, 480)
SCORE = 0

main_dir = os.path.split(os.path.abspath(__file__))[0]


def load_image(file):
    """ loads an image, prepares it for play
    """
    file = os.path.join(main_dir, "data", file)
    try:
        surface = pg.image.load(file)
    except pg.error:
        raise SystemExit('Could not load image "%s" %s' % (file, pg.get_error()))
    return surface.convert()

class Score(pg.sprite.Sprite):
    """ to keep track of the score.
    """

    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.font = pg.font.Font(None, 40)
        self.font.set_italic(1)
        self.color = pg.Color("white")
        self.lastscore = -1
        self.update()
        self.rect = self.image.get_rect().move(10, 450)

    def update(self):
        """ We only update the score in update() when it has changed.
        """
        if SCORE != self.lastscore:
            self.lastscore = SCORE
            msg = "Score: %d" % SCORE
            self.image = self.font.render(msg, 0, self.color)

def main(winstyle=0):
    pg.init()
    # Set the display mode
    winstyle = 0  # |FULLSCREEN
    bestdepth = pg.display.mode_ok(SCREENRECT.size, winstyle, 32)
    screen = pg.display.set_mode(SCREENRECT.size, winstyle, bestdepth)

    # create the background, tile the bgd image
    bgdtile = load_image("background.jpg ")
    background = pg.Surface(SCREENRECT.size)
    background.blit(bgdtile, (0, 0))
    screen.blit(bgdtile, (0, 0))
    pg.display.flip()

    # Initialize Game Groups
    all = pg.sprite.RenderUpdates()

    # Create Some Starting Values
    clock = pg.time.Clock()
    global SCORE
    if pg.font:
        all.add(Score())

    # Run our main loop whilst the player is alive.
    while True:
        all.clear(screen, background)
        SCORE += 123456789
        all.update()

        # draw the scene
        dirty = all.draw(screen)
        pg.display.update(dirty)

        # cap the framerate at 40fps. Also called 40HZ or 40 times per second.
        clock.tick(40)


if __name__ == "__main__":
    main()

It is necessary to prepare the background image (background.jpg) under data. It's a bit long, but if you run the above sample, you can draw the background and display the characters as shown below.

Screen Shot 2019-12-14 at 21.30.41.png

The parts unique to the game engine are explained below.

Sprite grouping

all = pg.sprite.RenderUpdates() #Creating a Sprite group
all.add(Score()) #Add to Sprite group
all.update() #Bulk update of Sprite group
all.draw(screen) #Drawing a Sprite group

Pygame has a feature that allows you to group sprites so that you can easily update and draw all the elements on the screen or the elements of a particular group (eg enemy characters only) all at once. .. There are various types of Sprite groups, such as ordered groups and groups for single sprites, and it is best to use them according to the purpose. You can check the list in Official Documents.

Specify screen refresh rate

clock = pg.time.Clock() #Clock generation
clock.tick(40) #Using Clock 1/Wait for processing until 40 seconds have passed

When moving an object, you have to wait if the process finishes too early to move it at the same speed regardless of the weight of the process. To achieve this, pygame uses a Clock object. Just create a Clock object and call clock.tick (), and it will sleep for the time according to the frame rate from the previous call, which is very convenient.

Finally

In addition to the drawing function introduced this time, pygame has

There are various functions such as. It's so convenient to be able to write a UI that updates in real time in Python, so I can't wait for the official release of pygame2!

Recommended Posts

Create a game UI from scratch with pygame2!
Create a machine learning environment from scratch with Winsows 10
Create games with Pygame
Create a decision tree from 0 with Python (1. Overview)
Create a homepage with django
Create a heatmap with pyqtgraph
Balloon splitting game with pygame
Create a directory with python
Create a game to control puzzle & dragons drops using pygame
Create an environment for "Deep Learning from scratch" with Docker
Create a life game that is manually updated with tkinter
[Learning record] Create a mysterious dungeon game with Pyhton's Tkinter
How to make a simple Flappy Bird game with pygame
Build a bulletin board app from scratch with Django. (Part 2)
Build a bulletin board app from scratch with Django. (Part 3)
Create folders from '01' to '12' with python
Create a pandas Dataframe from a string.
Create a virtual environment with Python!
Create a poisson stepper with numpy.random
Achieve a Netflix-like UI with FlexSlider2
Create a file uploader with Django
Deploy Django + React from scratch to GKE (3) Create a GCP project
Create an application by classifying with Pygame
How to create a clone from Github
Create a Python function decorator with Class
Let's make a shiritori game with Python
Create wordcloud from your tweet with python3
Build a blockchain with Python ① Create a class
Create a dummy image with Python + PIL.
[Python] Create a virtual environment with Anaconda
Let's create a free group with Python
Create a tool to automatically furigana with html using Mecab from Python3
Create a GUI app with Python's Tkinter
Business efficiency starting from scratch with Python
Create a large text file with shellscript
Create a star system with Blender 2.80 script
Create a virtual environment with Python_Mac version
Create a standings from JFL match results
Create a VM with a YAML file (KVM)
Create a simple web app with flask
Create a word frequency counter with Python 3.4
Create a stack with a queue and a queue with a stack (from LetCode / Implement Stack using Queues, Implement Queue using Stacks)
Create a deb file from a python package
How to create a repository from media
I made a life game with Numpy
Create a Connecting Nearest Neighbor with NetworkX
Create a web service with Docker + Flask
Create a dataframe from excel using pandas
Create a private repository with AWS CodeArtifact
Create a car meter with raspberry pi
Create a devilish picture with Blender scripts
I made a roguelike game with Python
Create a matrix with PythonGUI (text box)
Create a decision tree from 0 with Python and understand it (5. Information Entropy)
Create a graph with borders removed with matplotlib
Let's make an A to B conversion web application with Flask! From scratch ...
Create a UI that replaces VBA with PySimpleGUI (file dialog, list, log output)
Create a frame with transparent background with tkinter [Python]
Edit Excel from Python to create a PivotTable
Microservices with GCP on RoR starting from scratch
Connect Scratch X and Digispark with a bottle