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.
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.
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
Many sample games are included in pygame. Let's try one.
python -m pygame.examples.aliens
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.
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.
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.
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.
The parts unique to the game engine are explained below.
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.
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.
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