@robsean
This commit is contained in:
Xingyu Wang 2020-01-25 22:07:02 +08:00
parent d52a68e3c2
commit a5ee878da3

View File

@ -1,6 +1,6 @@
[#]: collector: (lujun9972) [#]: collector: (lujun9972)
[#]: translator: (robsean) [#]: translator: (robsean)
[#]: reviewer: ( ) [#]: reviewer: (wxy)
[#]: publisher: ( ) [#]: publisher: ( )
[#]: url: ( ) [#]: url: ( )
[#]: subject: (Enable your Python game player to run forward and backward) [#]: subject: (Enable your Python game player to run forward and backward)
@ -9,10 +9,11 @@
使你的 Python 游戏玩家能够向前和向后跑 使你的 Python 游戏玩家能够向前和向后跑
====== ======
使用 Pygame 模块来使你的 Python 平台开启侧滚效果,来让你的玩家自由奔跑。 > 使用 Pygame 模块来使你的 Python 平台开启侧滚效果,来让你的玩家自由奔跑。
![Gaming artifacts with joystick, GameBoy, paddle][1]
这是仍在进行中的关于使用 Pygame 模块来在 Python 3 中在创建电脑游戏的第八部分。先前的文章是: ![](https://img.linux.net.cn/data/attachment/album/202001/25/220636x5mabbl47xvtsk55.jpg)
这是仍在进行中的关于使用 Pygame 模块来在 Python 3 中在创建电脑游戏的第九部分。先前的文章是:
* [通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程][2] * [通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程][2]
* [使用 Python 和 Pygame 模块构建一个游戏框架][3] * [使用 Python 和 Pygame 模块构建一个游戏框架][3]
@ -23,9 +24,7 @@
* [在你的 Python 游戏中模拟引力][7] * [在你的 Python 游戏中模拟引力][7]
* [为你的 Python 平台类游戏添加跳跃功能][8] * [为你的 Python 平台类游戏添加跳跃功能][8]
在这一系列关于使用 [Pygame][10] 模块来在 [Python 3][9] 中创建电脑游戏的先前文章中,你已经设计了你的关卡设计布局,但是你的关卡的一些部分可能已近超出你的屏幕的可视区域。在平台类游戏中,这个问题的普遍解决方案是,像术语“<ruby>侧滚<rt>side-scroller</rt></ruby>”表明的一样,滚动。
在这一系列关于使用 [Pygame][10] 模块来在 [Python 3][9]中创建电脑游戏的先前条目中,你已经设计了你的层设计布局,但是你的层的一些部分可能已近超出你的可视屏幕。在平台类游戏中,这个问题的普遍解决方案是,像术语"侧滚动"表明的一样,滚动。
滚动的关键是当玩家精灵接近屏的幕边缘时,使在玩家精灵周围的平台移动。这样给予一种错觉,屏幕是一个在游戏世界中穿梭追拍的"摄像机"。 滚动的关键是当玩家精灵接近屏的幕边缘时,使在玩家精灵周围的平台移动。这样给予一种错觉,屏幕是一个在游戏世界中穿梭追拍的"摄像机"。
@ -33,8 +32,7 @@
### 在侧滚动条中放置卷轴 ### 在侧滚动条中放置卷轴
如果你希望你的玩家能够后退,你需要一个触发点来向前和向后。这两个点仅仅是两个变量。设置它们各个距各个屏幕边缘大约 100 或 200 像素。在你的 **setup** 部分中创建变量。在下面的代码中,前两行用于背景说明,所以仅需要添加这行后的代码: 如果你希望你的玩家能够后退,你需要一个触发点来向前和向后。这两个点仅仅是两个变量。设置它们各个距各个屏幕边缘大约 100 或 200 像素。在你的设置部分中创建变量。在下面的代码中,前两行用于上下文说明,所以仅需要添加这行后的代码:
``` ```
player_list.add(player) player_list.add(player)
@ -43,8 +41,7 @@ forwardX  = 600
backwardX = 230 backwardX = 230
``` ```
在主循环中,查看你的玩家精灵是否在 **前进****后退** 滚动点处。如果是这样,向左或向右移动使用的平台,取决于世界是向前或向后移动。在下面的代码中,代码的最后三行仅供你参考: 在主循环中,查看你的玩家精灵是否在 `forwardx``backwardx` 滚动点处。如果是这样,向左或向右移动使用的平台,取决于世界是向前或向后移动。在下面的代码中,代码的最后三行仅供你参考:
``` ```
        # scroll the world forward         # scroll the world forward
@ -71,16 +68,13 @@ backwardX = 230
![Scrolling the world in Pygame][11] ![Scrolling the world in Pygame][11]
滚动工作像预期的一样,但是你可能注意到一个发生的小问题,当你滚动你的玩家和非玩家精灵周围的世界时:敌人精灵不随同世界滚动。除非你愿意。 滚动像预期的一样工作,但是你可能注意到一个发生的小问题,当你滚动你的玩家和非玩家精灵周围的世界时:敌人精灵不随同世界滚动。除非你要你的敌人精灵要无休止地追逐你的玩家,你需要修改敌人代码,以便当你的玩家快速撤退时,敌人被留在后面。
你的敌人精灵要无休止地追逐你的玩家你需要修改敌人代码以便当你的玩家快速撤退时敌人被留在hz后面。
### 敌人卷轴 ### 敌人卷轴
在你的主循环中,你必需为你的敌人的位置的卷轴平台应用相同的规则。因为你的游戏世界将(很可能)有不止一个敌人在其中,该规则被应用于你的敌人列表,而不是一个单独的敌人精灵。 这是分组类似元素到列表中的优点之一。 在你的主循环中,你必须对卷轴平台为你的敌人的位置的应用相同的规则。因为你的游戏世界将(很可能)有不止一个敌人在其中,该规则应该被应用于你的敌人列表,而不是一个单独的敌人精灵。这是分组类似元素到列表中的优点之一。
前两行用于背景注释,所以只需添加这两行后面的代码到你的主循环中:
前两行用于上下文注释,所以只需添加这两行后面的代码到你的主循环中:
``` ```
    # scroll the world forward     # scroll the world forward
@ -95,7 +89,6 @@ backwardX = 230
来滚向另一个方向: 来滚向另一个方向:
``` ```
    # scroll the world backward     # scroll the world backward
    if player.rect.x <= backwardx:     if player.rect.x <= backwardx:
@ -111,7 +104,6 @@ backwardX = 230
这里是到目前为止你已经为这个 Python 平台所写所有的代码: 这里是到目前为止你已经为这个 Python 平台所写所有的代码:
``` ```
#!/usr/bin/env python3 #!/usr/bin/env python3
# draw a world # draw a world
@ -126,7 +118,7 @@ backwardX = 230
# GNU All-Permissive License # GNU All-Permissive License
# Copying and distribution of this file, with or without modification, # Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright # are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.  This file is offered as-is, # notice and this notice are preserved. This file is offered as-is,
# without any warranty. # without any warranty.
import pygame import pygame
@ -138,207 +130,207 @@ Objects
''' '''
class Platform(pygame.sprite.Sprite): class Platform(pygame.sprite.Sprite):
    # x location, y location, img width, img height, img file     # x location, y location, img width, img height, img file
    def __init__(self,xloc,yloc,imgw,imgh,img): def __init__(self,xloc,yloc,imgw,imgh,img):
        pygame.sprite.Sprite.__init__(self) pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(os.path.join('images',img)).convert() self.image = pygame.image.load(os.path.join('images',img)).convert()
        self.image.convert_alpha() self.image.convert_alpha()
        self.rect = self.image.get_rect() self.rect = self.image.get_rect()
        self.rect.y = yloc self.rect.y = yloc
        self.rect.x = xloc self.rect.x = xloc
class Player(pygame.sprite.Sprite): class Player(pygame.sprite.Sprite):
    ''' '''
    Spawn a player Spawn a player
    ''' '''
    def __init__(self): def __init__(self):
        pygame.sprite.Sprite.__init__(self) pygame.sprite.Sprite.__init__(self)
        self.movex = 0 self.movex = 0
        self.movey = 0 self.movey = 0
        self.frame = 0 self.frame = 0
        self.health = 10 self.health = 10
        self.collide_delta = 0 self.collide_delta = 0
        self.jump_delta = 6 self.jump_delta = 6
        self.score = 1 self.score = 1
        self.images = [] self.images = []
        for i in range(1,9): for i in range(1,9):
            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert() img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            img.convert_alpha() img.convert_alpha()
            img.set_colorkey(ALPHA) img.set_colorkey(ALPHA)
            self.images.append(img) self.images.append(img)
            self.image = self.images[0] self.image = self.images[0]
            self.rect  = self.image.get_rect() self.rect = self.image.get_rect()
    def jump(self,platform_list): def jump(self,platform_list):
        self.jump_delta = 0 self.jump_delta = 0
    def gravity(self): def gravity(self):
        self.movey += 3.2 # how fast player falls self.movey += 3.2 # how fast player falls
       
        if self.rect.y > worldy and self.movey >= 0:
            self.movey = 0
            self.rect.y = worldy-ty
       
    def control(self,x,y):
        '''
        control player movement
        '''
        self.movex += x
        self.movey += y
       
    def update(self):
        '''
        Update sprite position
        '''
       
        self.rect.x = self.rect.x + self.movex
        self.rect.y = self.rect.y + self.movey
        # moving left if self.rect.y > worldy and self.movey >= 0:
        if self.movex < 0: self.movey = 0
            self.frame += 1 self.rect.y = worldy-ty
            if self.frame > ani*3:
                self.frame = 0
            self.image = self.images[self.frame//ani]
        # moving right def control(self,x,y):
        if self.movex > 0: '''
            self.frame += 1 control player movement
            if self.frame > ani*3: '''
                self.frame = 0 self.movex += x
            self.image = self.images[(self.frame//ani)+4] self.movey += y
        # collisions def update(self):
        enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False) '''
        for enemy in enemy_hit_list: Update sprite position
            self.health -= 1 '''
            #print(self.health)
self.rect.x = self.rect.x + self.movex
self.rect.y = self.rect.y + self.movey
# moving left
if self.movex < 0:
self.frame += 1
if self.frame > ani*3:
self.frame = 0
self.image = self.images[self.frame//ani]
# moving right
if self.movex > 0:
self.frame += 1
if self.frame > ani*3:
self.frame = 0
self.image = self.images[(self.frame//ani)+4]
# collisions
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
for enemy in enemy_hit_list:
self.health -= 1
#print(self.health)
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
for p in plat_hit_list:
self.collide_delta = 0 # stop jumping
self.movey = 0
if self.rect.y > p.rect.y:
self.rect.y = p.rect.y+ty
else:
self.rect.y = p.rect.y-ty
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
for g in ground_hit_list:
self.movey = 0
self.rect.y = worldy-ty-ty
self.collide_delta = 0 # stop jumping
if self.rect.y > g.rect.y:
self.health -=1
print(self.health)
if self.collide_delta < 6 and self.jump_delta < 6:
self.jump_delta = 6*2
self.movey -= 33 # how high to jump
self.collide_delta += 6
self.jump_delta += 6
        plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
        for p in plat_hit_list:
            self.collide_delta = 0 # stop jumping
            self.movey = 0
            if self.rect.y > p.rect.y:
                self.rect.y = p.rect.y+ty
            else:
                self.rect.y = p.rect.y-ty
           
        ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
        for g in ground_hit_list:
            self.movey = 0
            self.rect.y = worldy-ty-ty
            self.collide_delta = 0 # stop jumping
            if self.rect.y > g.rect.y:
                self.health -=1
                print(self.health)
               
        if self.collide_delta < 6 and self.jump_delta < 6:
            self.jump_delta = 6*2
            self.movey -= 33  # how high to jump
            self.collide_delta += 6
            self.jump_delta    += 6
           
class Enemy(pygame.sprite.Sprite): class Enemy(pygame.sprite.Sprite):
    ''' '''
    Spawn an enemy Spawn an enemy
    ''' '''
    def __init__(self,x,y,img): def __init__(self,x,y,img):
        pygame.sprite.Sprite.__init__(self) pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(os.path.join('images',img)) self.image = pygame.image.load(os.path.join('images',img))
        self.movey = 0 self.movey = 0
        #self.image.convert_alpha() #self.image.convert_alpha()
        #self.image.set_colorkey(ALPHA) #self.image.set_colorkey(ALPHA)
        self.rect = self.image.get_rect() self.rect = self.image.get_rect()
        self.rect.x = x self.rect.x = x
        self.rect.y = y self.rect.y = y
        self.counter = 0 self.counter = 0
               
    def move(self):
        '''
        enemy movement
        '''
        distance = 80
        speed = 8
        self.movey += 3.2 def move(self):
        '''
        if self.counter >= 0 and self.counter <= distance: enemy movement
            self.rect.x += speed '''
        elif self.counter >= distance and self.counter <= distance*2: distance = 80
            self.rect.x -= speed speed = 8
        else:
            self.counter = 0
       
        self.counter += 1
        if not self.rect.y >= worldy-ty-ty: self.movey += 3.2
            self.rect.y += self.movey
        plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False) if self.counter >= 0 and self.counter <= distance:
        for p in plat_hit_list: self.rect.x += speed
            self.movey = 0 elif self.counter >= distance and self.counter <= distance*2:
            if self.rect.y > p.rect.y: self.rect.x -= speed
                self.rect.y = p.rect.y+ty else:
            else: self.counter = 0
                self.rect.y = p.rect.y-ty
self.counter += 1
if not self.rect.y >= worldy-ty-ty:
self.rect.y += self.movey
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
for p in plat_hit_list:
self.movey = 0
if self.rect.y > p.rect.y:
self.rect.y = p.rect.y+ty
else:
self.rect.y = p.rect.y-ty
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
for g in ground_hit_list:
self.rect.y = worldy-ty-ty
        ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
        for g in ground_hit_list:
            self.rect.y = worldy-ty-ty
       
class Level(): class Level():
    def bad(lvl,eloc): def bad(lvl,eloc):
        if lvl == 1: if lvl == 1:
            enemy = Enemy(eloc[0],eloc[1],'yeti.png') # spawn enemy enemy = Enemy(eloc[0],eloc[1],'yeti.png') # spawn enemy
            enemy_list = pygame.sprite.Group() # create enemy group enemy_list = pygame.sprite.Group() # create enemy group
            enemy_list.add(enemy)              # add enemy to group enemy_list.add(enemy) # add enemy to group
           
        if lvl == 2:
            print("Level " + str(lvl) )
        return enemy_list if lvl == 2:
print("Level " + str(lvl) )
    def loot(lvl,lloc): return enemy_list
        print(lvl)
    def ground(lvl,gloc,tx,ty): def loot(lvl,lloc):
        ground_list = pygame.sprite.Group() print(lvl)
        i=0
        if lvl == 1:
            while i < len(gloc):
                ground = Platform(gloc[i],worldy-ty,tx,ty,'ground.png')
                ground_list.add(ground)
                i=i+1
        if lvl == 2: def ground(lvl,gloc,tx,ty):
            print("Level " + str(lvl) ) ground_list = pygame.sprite.Group()
i=0
if lvl == 1:
while i < len(gloc):
ground = Platform(gloc[i],worldy-ty,tx,ty,'ground.png')
ground_list.add(ground)
i=i+1
        return ground_list if lvl == 2:
print("Level " + str(lvl) )
    def platform(lvl,tx,ty): return ground_list
        plat_list = pygame.sprite.Group()
        ploc = []
        i=0
        if lvl == 1:
            ploc.append((0,worldy-ty-128,3))
            ploc.append((300,worldy-ty-256,3))
            ploc.append((500,worldy-ty-128,4))
            while i < len(ploc): def platform(lvl,tx,ty):
                j=0 plat_list = pygame.sprite.Group()
                while j <= ploc[i][2]: ploc = []
                    plat = Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'ground.png') i=0
                    plat_list.add(plat) if lvl == 1:
                    j=j+1 ploc.append((0,worldy-ty-128,3))
                print('run' + str(i) + str(ploc[i])) ploc.append((300,worldy-ty-256,3))
                i=i+1 ploc.append((500,worldy-ty-128,4))
        if lvl == 2: while i < len(ploc):
            print("Level " + str(lvl) ) j=0
while j <= ploc[i][2]:
plat = Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'ground.png')
plat_list.add(plat)
j=j+1
print('run' + str(i) + str(ploc[i]))
i=i+1
        return plat_list if lvl == 2:
print("Level " + str(lvl) )
return plat_list
''' '''
Setup Setup
@ -347,12 +339,12 @@ worldx = 960
worldy = 720 worldy = 720
fps = 40 # frame rate fps = 40 # frame rate
ani = 4  # animation cycles ani = 4 # animation cycles
clock = pygame.time.Clock() clock = pygame.time.Clock()
pygame.init() pygame.init()
main = True main = True
BLUE  = (25,25,200) BLUE = (25,25,200)
BLACK = (23,23,23 ) BLACK = (23,23,23 )
WHITE = (254,254,254) WHITE = (254,254,254)
ALPHA = (0,255,0) ALPHA = (0,255,0)
@ -378,8 +370,8 @@ ty = 64 #tile size
i=0 i=0
while i <= (worldx/tx)+tx: while i <= (worldx/tx)+tx:
    gloc.append(i*tx) gloc.append(i*tx)
    i=i+1 i=i+1
enemy_list = Level.bad( 1, eloc ) enemy_list = Level.bad( 1, eloc )
ground_list = Level.ground( 1,gloc,tx,ty ) ground_list = Level.ground( 1,gloc,tx,ty )
@ -389,63 +381,63 @@ plat_list = Level.platform( 1,tx,ty )
Main loop Main loop
''' '''
while main == True: while main == True:
    for event in pygame.event.get(): for event in pygame.event.get():
        if event.type == pygame.QUIT: if event.type == pygame.QUIT:
            pygame.quit(); sys.exit() pygame.quit(); sys.exit()
            main = False main = False
        if event.type == pygame.KEYDOWN: if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT or event.key == ord('a'): if event.key == pygame.K_LEFT or event.key == ord('a'):
                print("LEFT") print("LEFT")
                player.control(-steps,0) player.control(-steps,0)
            if event.key == pygame.K_RIGHT or event.key == ord('d'): if event.key == pygame.K_RIGHT or event.key == ord('d'):
                print("RIGHT") print("RIGHT")
                player.control(steps,0) player.control(steps,0)
            if event.key == pygame.K_UP or event.key == ord('w'): if event.key == pygame.K_UP or event.key == ord('w'):
                print('jump') print('jump')
        if event.type == pygame.KEYUP: if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == ord('a'): if event.key == pygame.K_LEFT or event.key == ord('a'):
                player.control(steps,0) player.control(steps,0)
            if event.key == pygame.K_RIGHT or event.key == ord('d'): if event.key == pygame.K_RIGHT or event.key == ord('d'):
                player.control(-steps,0) player.control(-steps,0)
            if event.key == pygame.K_UP or event.key == ord('w'): if event.key == pygame.K_UP or event.key == ord('w'):
                player.jump(plat_list) player.jump(plat_list)
            if event.key == ord('q'): if event.key == ord('q'):
                pygame.quit() pygame.quit()
                sys.exit() sys.exit()
                main = False main = False
    # scroll the world forward # scroll the world forward
    if player.rect.x >= forwardx: if player.rect.x >= forwardx:
        scroll = player.rect.x - forwardx scroll = player.rect.x - forwardx
        player.rect.x = forwardx player.rect.x = forwardx
        for p in plat_list: for p in plat_list:
            p.rect.x -= scroll p.rect.x -= scroll
        for e in enemy_list: for e in enemy_list:
            e.rect.x -= scroll e.rect.x -= scroll
               
    # scroll the world backward
    if player.rect.x <= backwardx:
        scroll = backwardx - player.rect.x
        player.rect.x = backwardx
        for p in plat_list:
            p.rect.x += scroll
        for e in enemy_list:
            e.rect.x += scroll
    world.blit(backdrop, backdropbox) # scroll the world backward
    player.gravity() # check gravity if player.rect.x <= backwardx:
    player.update() scroll = backwardx - player.rect.x
    player_list.draw(world) #refresh player position player.rect.x = backwardx
    enemy_list.draw(world)  # refresh enemies for p in plat_list:
    ground_list.draw(world)  # refresh enemies p.rect.x += scroll
    plat_list.draw(world)   # refresh platforms for e in enemy_list:
    for e in enemy_list: e.rect.x += scroll
        e.move()
    pygame.display.flip() world.blit(backdrop, backdropbox)
    clock.tick(fps) player.gravity() # check gravity
player.update()
player_list.draw(world) #refresh player position
enemy_list.draw(world) # refresh enemies
ground_list.draw(world) # refresh enemies
plat_list.draw(world) # refresh platforms
for e in enemy_list:
e.move()
pygame.display.flip()
clock.tick(fps)
``` ```
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -455,21 +447,21 @@ via: https://opensource.com/article/19/12/python-platformer-game-run
作者:[Seth Kenlon][a] 作者:[Seth Kenlon][a]
选题:[lujun9972][b] 选题:[lujun9972][b]
译者:[robsean](https://github.com/robsean) 译者:[robsean](https://github.com/robsean)
校对:[校对者ID](https://github.com/校对者ID) 校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth [a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972 [b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/open_gaming_games_roundup_news.png?itok=KM0ViL0f (Gaming artifacts with joystick, GameBoy, paddle) [1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/open_gaming_games_roundup_news.png?itok=KM0ViL0f (Gaming artifacts with joystick, GameBoy, paddle)
[2]: https://opensource.com/article/17/10/python-101 [2]: https://linux.cn/article-9071-1.html
[3]: https://opensource.com/article/17/12/game-framework-python [3]: https://linux.cn/article-10850-1.html
[4]: https://opensource.com/article/17/12/game-python-add-a-player [4]: https://linux.cn/article-10858-1.html
[5]: https://opensource.com/article/17/12/game-python-moving-player [5]: https://linux.cn/article-10874-1.html
[6]: https://opensource.com/article/18/5/pygame-enemy [6]: https://linux.cn/article-10883-1.html
[7]: https://opensource.com/article/19/11/simulate-gravity-python [7]: https://linux.cn/article-11780-1.html
[8]: https://opensource.com/article/19/12/jumping-python-platformer-game [8]: https://linux.cn/article-11790-1.html
[9]: https://www.python.org/ [9]: https://www.python.org/
[10]: https://www.pygame.org/news [10]: https://www.pygame.org/news
[11]: https://opensource.com/sites/default/files/uploads/pygame-scroll.jpg (Scrolling the world in Pygame) [11]: https://opensource.com/sites/default/files/uploads/pygame-scroll.jpg (Scrolling the world in Pygame)
[12]:https://opensource.com/article/18/7/put-platforms-python-game [12]:https://linux.cn/article-10902-1.html