用Python写个超级小恐龙跑酷游戏,上班摸鱼我能玩一天

Posted 程序猿中的BUG

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Python写个超级小恐龙跑酷游戏,上班摸鱼我能玩一天相关的知识,希望对你有一定的参考价值。

目录

啥也不多说,先来一个效果图展示 

工具使用

游戏思路解析

项目整体的框架搭建

创建小恐龙对象

创建障碍物对象

创建地板对象

游戏的基本配置信息


啥也不多说,先来一个效果图展示 

工具使用

开发环境:win10、python3.7 开发工具:pycharm 工具包:pygame

游戏思路解析

准备相对应的游戏图片 准备相对应的音频数据

项目整体的框架搭建

创建小恐龙对象

import pygame


'''小恐龙'''
class Dinosaur(pygame.sprite.Sprite):
    def __init__(self, imagepaths, position=(40, 147), size=[(44, 47), (59, 47)], **kwargs):
        pygame.sprite.Sprite.__init__(self)
        # 导入所有图片
        self.images = []
        image = pygame.image.load(imagepaths[0])
        for i in range(5):
            self.images.append(pygame.transform.scale(image.subsurface((i*88, 0), (88, 95)), size[0]))
        image = pygame.image.load(imagepaths[1])
        for i in range(2):
            self.images.append(pygame.transform.scale(image.subsurface((i*118, 0), (118, 95)), size[1]))
        self.image_idx = 0
        self.image = self.images[self.image_idx]
        self.rect = self.image.get_rect()
        self.rect.left, self.rect.bottom = position
        self.mask = pygame.mask.from_surface(self.image)
        # 定义一些必要的变量
        self.init_position = position
        self.refresh_rate = 5
        self.refresh_counter = 0
        self.speed = 11.5
        self.gravity = 0.6
        self.is_jumping = False
        self.is_ducking = False
        self.is_dead = False
        self.movement = [0, 0]
    '''跳跃'''
    def jump(self, sounds):
        if self.is_dead or self.is_jumping:
            return
        sounds['jump'].play()
        self.is_jumping = True
        self.movement[1] = -1 * self.speed
    '''低头'''
    def duck(self):
        if self.is_jumping or self.is_dead:
            return
        self.is_ducking = True
    '''不低头'''
    def unduck(self):
        self.is_ducking = False
    '''死掉了'''
    def die(self, sounds):
        if self.is_dead:
            return
        sounds['die'].play()
        self.is_dead = True
    '''将恐龙画到屏幕'''
    def draw(self, screen):
        screen.blit(self.image, self.rect)
    '''载入当前状态的图片'''
    def loadImage(self):
        self.image = self.images[self.image_idx]
        rect = self.image.get_rect()
        rect.left, rect.top = self.rect.left, self.rect.top
        self.rect = rect
        self.mask = pygame.mask.from_surface(self.image)
    '''更新小恐龙'''
    def update(self):
        if self.is_dead:
            self.image_idx = 4
            self.loadImage()
            return
        if self.is_jumping:
            self.movement[1] += self.gravity
            self.image_idx = 0
            self.loadImage()
            self.rect = self.rect.move(self.movement)
            if self.rect.bottom >= self.init_position[1]:
                self.rect.bottom = self.init_position[1]
                self.is_jumping = False
        elif self.is_ducking:
            if self.refresh_counter % self.refresh_rate == 0:
                self.refresh_counter = 0
                self.image_idx = 5 if self.image_idx == 6 else 6
                self.loadImage()
        else:
            if self.refresh_counter % self.refresh_rate == 0:
                self.refresh_counter = 0
                if self.image_idx == 1:
                    self.image_idx = 2
                elif self.image_idx == 2:
                    self.image_idx = 3
                else:
                    self.image_idx = 1
                self.loadImage()
        self.refresh_counter += 1

创建障碍物对象

  • 仙人掌

  • 飞龙

import random
import pygame


'''仙人掌'''
class Cactus(pygame.sprite.Sprite):
    def __init__(self, imagepaths, position=(600, 147), sizes=[(40, 40), (40, 40)], **kwargs):
        pygame.sprite.Sprite.__init__(self)
        # 导入图片
        self.images = []
        image = pygame.image.load(imagepaths[0])
        for i in range(3):
            self.images.append(pygame.transform.scale(image.subsurface((i*101, 0), (101, 101)), sizes[0]))
        image = pygame.image.load(imagepaths[1])
        for i in range(3):
            self.images.append(pygame.transform.scale(image.subsurface((i*68, 0), (68, 70)), sizes[1]))
        self.image = random.choice(self.images)
        self.rect = self.image.get_rect()
        self.rect.left, self.rect.bottom = position
        self.mask = pygame.mask.from_surface(self.image)
        # 定义一些必要的变量
        self.speed = -10
    '''画到屏幕上'''
    def draw(self, screen):
        screen.blit(self.image, self.rect)
    '''更新'''
    def update(self):
        self.rect = self.rect.move([self.speed, 0])
        if self.rect.right < 0:
            self.kill()


'''飞龙'''
class Ptera(pygame.sprite.Sprite):
    def __init__(self, imagepath, position, size=(46, 40), **kwargs):
        pygame.sprite.Sprite.__init__(self)
        # 导入图片
        self.images = []
        image = pygame.image.load(imagepath)
        for i in range(2):
            self.images.append(pygame.transform.scale(image.subsurface((i*92, 0), (92, 81)), size))
        self.image_idx = 0
        self.image = self.images[self.image_idx]
        self.rect = self.image.get_rect()
        self.rect.left, self.rect.centery = position
        self.mask = pygame.mask.from_surface(self.image)
        # 定义一些必要的变量
        self.speed = -10
        self.refresh_rate = 10
        self.refresh_counter = 0
    '''画到屏幕上'''
    def draw(self, screen):
        screen.blit(self.image, self.rect)
    '''更新'''
    def update(self):
        if self.refresh_counter % self.refresh_rate == 0:
            self.refresh_counter = 0
            self.image_idx = (self.image_idx + 1) % len(self.images)
            self.loadImage()
        self.rect = self.rect.move([self.speed, 0])
        if self.rect.right < 0:
            self.kill()
        self.refresh_counter += 1
    '''载入当前状态的图片'''
    def loadImage(self):
        self.image = self.images[self.image_idx]
        rect = self.image.get_rect()
        rect.left, rect.top = self.rect.left, self.rect.top
        self.rect = rect
        self.mask = pygame.mask.from_surface(self.image)

创建地板对象

import pygame


'''地板'''
class Ground(pygame.sprite.Sprite):
    def __init__(self, imagepath, position, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        # 导入图片
        self.image_0 = pygame.image.load(imagepath)
        self.rect_0 = self.image_0.get_rect()
        self.rect_0.left, self.rect_0.bottom = position
        self.image_1 = pygame.image.load(imagepath)
        self.rect_1 = self.image_1.get_rect()
        self.rect_1.left, self.rect_1.bottom = self.rect_0.right, self.rect_0.bottom
        # 定义一些必要的参数
        self.speed = -10
    '''更新地板'''
    def update(self):
        self.rect_0.left += self.speed
        self.rect_1.left += self.speed
        if self.rect_0.right < 0:
            self.rect_0.left = self.rect_1.right
        if self.rect_1.right < 0:
            self.rect_1.left = self.rect_0.right
    '''将地板画到屏幕'''
    def draw(self, screen):
        screen.blit(self.image_0, self.rect_0)
        screen.blit(self.image_1, self.rect_1)

游戏的基本配置信息

'''配置文件'''
import os


'''屏幕大小'''
SCREENSIZE = (600, 150)
'''FPS'''
FPS = 60
'''音频素材路径'''
AUDIO_PATHS = {
    'die': os.path.join(os.getcwd(), 'resources/audios/die.wav'),
    'jump': os.path.join(os.getcwd(), 'resources/audios/jump.wav'),
    'point': os.path.join(os.getcwd(), 'resources/audios/point.wav')
}
'''图片素材路径'''
IMAGE_PATHS = {
    'cacti': [
        os.path.join(os.getcwd(), 'resources/images/cacti-big.png'),
        os.path.join(os.getcwd(), 'resources/images/cacti-small.png')
    ],
    'cloud': os.path.join(os.getcwd(), 'resources/images/cloud.png'),
    'dino': [
        os.path.join(os.getcwd(), 'resources/images/dino.png'),
        os.path.join(os.getcwd(), 'resources/images/dino_ducking.png')
    ],
    'gameover': os.path.join(os.getcwd(), 'resources/images/gameover.png'),
    'ground': os.path.join(os.getcwd(), 'resources/images/ground.png'),
    'numbers': os.path.join(os.getcwd(), 'resources/images/numbers.png'),
    'ptera': os.path.join(os.getcwd(), 'resources/images/ptera.png'),
    'replay': os.path.join(os.getcwd(), 'resources/images/replay.png')
}
'''背景颜色'''
BACKGROUND_COLOR = (235, 235, 235)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
```

设定游戏开始界面
```python
import sys
import pygame
from modules.sprites.dinosaur import Dinosaur


'''游戏开始界面'''
def GameStartInterface(screen, sounds, cfg):
    dino = Dinosaur(cfg.IMAGE_PATHS['dino'])
    ground = pygame.image.load(cfg.IMAGE_PATHS['ground']).subsurface((0, 0), (83, 19))
    rect = ground.get_rect()
    rect.left, rect.bottom = cfg.SCREENSIZE[0]/20, cfg.SCREENSIZE[1]
    clock = pygame.time.Clock()
    press_flag = False
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
                    press_flag = True
                    dino.jump(sounds)
        dino.update()
        screen.fill(cfg.BACKGROUND_COLOR)
        screen.blit(ground, rect)
        dino.draw(screen)
        pygame.display.update()
        clock.tick(cfg.FPS)
        if (not dino.is_jumping) and press_flag:
            return True

```
游戏结束界面
```python
import sys
import pygame


'''游戏结束界面'''
def GameEndInterface(screen, cfg):
    replay_image = pygame.image.load(cfg.IMAGE_PATHS['replay'])
    replay_image = pygame.transform.scale(replay_image, (35, 31))
    replay_image_rect = replay_image.get_rect()
    replay_image_rect.centerx = cfg.SCREENSIZE[0] / 2
    replay_image_rect.top = cfg.SCREENSIZE[1] * 0.52
    gameover_image = pygame.image.load(cfg.IMAGE_PATHS['gameover'])
    gameover_image = pygame.transform.scale(gameover_image, (190, 11))
    gameover_image_rect = gameover_image.get_rect()
    gameover_image_rect.centerx = cfg.SCREENSIZE[0] / 2
    gameover_image_rect.centery = cfg.SCREENSIZE[1] * 0.35
    clock = pygame.time.Clock()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
                    return True
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                if replay_image_rect.collidepoint(mouse_pos):
                    return True
        screen.blit(replay_image, replay_image_rect)
        screen.blit(gameover_image, gameover_image_rect)
        pygame.display.update()
        clock.tick(cfg.FPS)
```

项目运行文件
```python
import cfg
import sys
import random
import pygame
from modules.interfaces.gameend import GameEndInterface
from modules.interfaces.gamestart import GameStartInterface
from modules.sprites.dinosaur import Dinosaur
from modules.sprites.obstacle import Cactus, Ptera
from modules.sprites.scene import Ground


'''main'''
def main(highest_score):
    # 游戏初始化
    pygame.init()
    screen = pygame.display.set_mode(cfg.SCREENSIZE)
    pygame.display.set_caption('九歌')
    # 导入所有声音文件
    sounds = {}
    for key, value in cfg.AUDIO_PATHS.items():
        sounds[key] = pygame.mixer.Sound(value)
    # 游戏开始界面
    GameStartInterface(screen, sounds, cfg)
    # 定义一些游戏中必要的元素和变量
    score = 0
    # score_board = Scoreboard(cfg.IMAGE_PATHS['numbers'], position=(534, 15), bg_color=cfg.BACKGROUND_COLOR)
    highest_score = highest_score
    # highest_score_board = Scoreboard(cfg.IMAGE_PATHS['numbers'], position=(435, 15), bg_color=cfg.BACKGROUND_COLOR, is_highest=True)
    dino = Dinosaur(cfg.IMAGE_PATHS['dino'])
    ground = Ground(cfg.IMAGE_PATHS['ground'], position=(0, cfg.SCREENSIZE[1]))
    cloud_sprites_group = pygame.sprite.Group()
    cactus_sprites_group = pygame.sprite.Group()
    ptera_sprites_group = pygame.sprite.Group()
    add_obstacle_timer = 0
    score_timer = 0
    # 游戏主循环
    clock = pygame.time.Clock()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
                    dino.jump(sounds)
                elif event.key == pygame.K_DOWN:
                    dino.duck()
            elif event.type == pygame.KEYUP and event.key == pygame.K_DOWN:
                dino.unduck()
        screen.fill(cfg.BACKGROUND_COLOR)
        # --随机添加仙人掌/飞龙
        add_obstacle_timer += 1
        if add_obstacle_timer > random.randrange(50, 150):
            add_obstacle_timer = 0
            random_value = random.randrange(0, 10)
            if random_value >= 5 and random_value <= 7:
                cactus_sprites_group.add(Cactus(cfg.IMAGE_PATHS['cacti']))
            else:
                position_ys = [cfg.SCREENSIZE[1]*0.82, cfg.SCREENSIZE[1]*0.75, cfg.SCREENSIZE[1]*0.60, cfg.SCREENSIZE[1]*0.20]
                ptera_sprites_group.add(Ptera(cfg.IMAGE_PATHS['ptera'], position=(600, random.choice(position_ys))))
        # --更新游戏元素
        dino.update()
        ground.update()
        cloud_sprites_group.update()
        cactus_sprites_group.update()
        ptera_sprites_group.update()
        score_timer += 1
        if score_timer > (cfg.FPS//12):
            score_timer = 0
            score += 1
            score = min(score, 99999)
            if score > highest_score:
                highest_score = score
            if score % 100 == 0:
                sounds['point'].play()
            if score % 1000 == 0:
                ground.speed -= 1
                for item in cloud_sprites_group:
                    item.speed -= 1
                for item in cactus_sprites_group:
                    item.speed -= 1
                for item in ptera_sprites_group:
                    item.speed -= 1
        # --碰撞检测
        for item in cactus_sprites_group:
            if pygame.sprite.collide_mask(dino, item):
                dino.die(sounds)
        for item in ptera_sprites_group:
            if pygame.sprite.collide_mask(dino, item):
                dino.die(sounds)
        # --将游戏元素画到屏幕上
        dino.draw(screen)
        ground.draw(screen)
        cloud_sprites_group.draw(screen)
        cactus_sprites_group.draw(screen)
        ptera_sprites_group.draw(screen)
        # --更新屏幕
        pygame.display.update()
        clock.tick(cfg.FPS)
        # --游戏是否结束
        if dino.is_dead:
            break
    # 游戏结束界面
    return GameEndInterface(screen, cfg), highest_score


'''run'''
if __name__ == '__main__':
    highest_score = 0
    while True:
        flag, highest_score = main(highest_score)
        if not flag: break
```

❀微信扫一扫关注公众号加入学习交流技术解答小天地+q裙:881744585

以上是关于用Python写个超级小恐龙跑酷游戏,上班摸鱼我能玩一天的主要内容,如果未能解决你的问题,请参考以下文章

30个Python小游戏,上班摸鱼我能玩一天内附源码

30个Python小游戏,上班摸鱼我能玩一天内附源码

30个Python小游戏,上班摸鱼我能玩一天内附源码

为了上班摸鱼我用Python制作十五个小游戏,普通到地狱级难度,看看你能挑战到哪内附源码

Python游戏篇:细节之大型游戏爆炸效果(附代码)

Python游戏篇:细节之大型游戏爆炸效果(附代码)