python小游戏——推箱子代码开源

简介: python小游戏——推箱子代码开源

一.效果呈现

二.主代码

'''
Function:
    推箱子小游戏
'''
import os
import sys
import cfg
import pygame
from modules import *
from itertools import chain
'''游戏地图'''
class gameMap():
    def __init__(self, num_cols, num_rows):
        self.walls = []
        self.boxes = []
        self.targets = []
        self.num_cols = num_cols
        self.num_rows = num_rows
    '''增加游戏元素'''
    def addElement(self, elem_type, col, row):
        if elem_type == 'wall':
            self.walls.append(elementSprite('wall.png', col, row, cfg))
        elif elem_type == 'box':
            self.boxes.append(elementSprite('box.png', col, row, cfg))
        elif elem_type == 'target':
            self.targets.append(elementSprite('target.png', col, row, cfg))
    '''画游戏地图'''
    def draw(self, screen):
        for elem in self.elemsIter():
            elem.draw(screen)
    '''游戏元素迭代器'''
    def elemsIter(self):
        for elem in chain(self.targets, self.walls, self.boxes):
            yield elem
    '''该关卡中所有的箱子是否都在指定位置, 在的话就是通关了'''
    def levelCompleted(self):
        for box in self.boxes:
            is_match = False
            for target in self.targets:
                if box.col == target.col and box.row == target.row:
                    is_match = True
                    break
            if not is_match:
                return False
        return True
    '''某位置是否可到达'''
    def isValidPos(self, col, row):
        if col >= 0 and row >= 0 and col < self.num_cols and row < self.num_rows:
            block_size = cfg.BLOCKSIZE
            temp1 = self.walls + self.boxes
            temp2 = pygame.Rect(col * block_size, row * block_size, block_size, block_size)
            return temp2.collidelist(temp1) == -1
        else:
            return False
    '''获得某位置的box'''
    def getBox(self, col, row):
        for box in self.boxes:
            if box.col == col and box.row == row:
                return box
        return None
'''游戏界面'''
class gameInterface():
    def __init__(self, screen):
        self.screen = screen
        self.levels_path = cfg.LEVELDIR
        self.initGame()
    '''导入关卡地图'''
    def loadLevel(self, game_level):
        with open(os.path.join(self.levels_path, game_level), 'r') as f:
            lines = f.readlines()
        # 游戏地图
        self.game_map = gameMap(max([len(line) for line in lines]) - 1, len(lines))
        # 游戏surface
        height = cfg.BLOCKSIZE * self.game_map.num_rows
        width = cfg.BLOCKSIZE * self.game_map.num_cols
        self.game_surface = pygame.Surface((width, height))
        self.game_surface.fill(cfg.BACKGROUNDCOLOR)
        self.game_surface_blank = self.game_surface.copy()
        for row, elems in enumerate(lines):
            for col, elem in enumerate(elems):
                if elem == 'p':
                    self.player = pusherSprite(col, row, cfg)
                elif elem == '*':
                    self.game_map.addElement('wall', col, row)
                elif elem == '#':
                    self.game_map.addElement('box', col, row)
                elif elem == 'o':
                    self.game_map.addElement('target', col, row)
    '''游戏初始化'''
    def initGame(self):
        self.scroll_x = 0
        self.scroll_y = 0
    '''将游戏界面画出来'''
    def draw(self, *elems):
        self.scroll()
        self.game_surface.blit(self.game_surface_blank, dest=(0, 0))
        for elem in elems:
            elem.draw(self.game_surface)
        self.screen.blit(self.game_surface, dest=(self.scroll_x, self.scroll_y))
    '''因为游戏界面面积>游戏窗口界面, 所以需要根据人物位置滚动'''
    def scroll(self):
        x, y = self.player.rect.center
        width = self.game_surface.get_rect().w
        height = self.game_surface.get_rect().h
        if (x + cfg.SCREENSIZE[0] // 2) > cfg.SCREENSIZE[0]:
            if -1 * self.scroll_x + cfg.SCREENSIZE[0] < width:
                self.scroll_x -= 2
        elif (x + cfg.SCREENSIZE[0] // 2) > 0:
            if self.scroll_x < 0:
                self.scroll_x += 2
        if (y + cfg.SCREENSIZE[1] // 2) > cfg.SCREENSIZE[1]:
            if -1 * self.scroll_y + cfg.SCREENSIZE[1] < height:
                self.scroll_y -= 2
        elif (y + 250) > 0:
            if self.scroll_y < 0:
                self.scroll_y += 2
'''某一关卡的游戏主循环'''
def runGame(screen, game_level):
    clock = pygame.time.Clock()
    game_interface = gameInterface(screen)
    game_interface.loadLevel(game_level)
    font_path = os.path.join(cfg.FONTDIR, 'simkai.ttf')
    text = '按R键重新开始本关'
    font = pygame.font.Font(font_path, 15)
    text_render = font.render(text, 1, (255, 255, 255))
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit(0)
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    next_pos = game_interface.player.move('left', is_test=True)
                    if game_interface.game_map.isValidPos(*next_pos):
                        game_interface.player.move('left')
                    else:
                        box = game_interface.game_map.getBox(*next_pos)
                        if box:
                            next_pos = box.move('left', is_test=True)
                            if game_interface.game_map.isValidPos(*next_pos):
                                game_interface.player.move('left')
                                box.move('left')
                    break
                if event.key == pygame.K_RIGHT:
                    next_pos = game_interface.player.move('right', is_test=True)
                    if game_interface.game_map.isValidPos(*next_pos):
                        game_interface.player.move('right')
                    else:
                        box = game_interface.game_map.getBox(*next_pos)
                        if box:
                            next_pos = box.move('right', is_test=True)
                            if game_interface.game_map.isValidPos(*next_pos):
                                game_interface.player.move('right')
                                box.move('right')
                    break
                if event.key == pygame.K_DOWN:
                    next_pos = game_interface.player.move('down', is_test=True)
                    if game_interface.game_map.isValidPos(*next_pos):
                        game_interface.player.move('down')
                    else:
                        box = game_interface.game_map.getBox(*next_pos)
                        if box:
                            next_pos = box.move('down', is_test=True)
                            if game_interface.game_map.isValidPos(*next_pos):
                                game_interface.player.move('down')
                                box.move('down')
                    break
                if event.key == pygame.K_UP:
                    next_pos = game_interface.player.move('up', is_test=True)
                    if game_interface.game_map.isValidPos(*next_pos):
                        game_interface.player.move('up')
                    else:
                        box = game_interface.game_map.getBox(*next_pos)
                        if box:
                            next_pos = box.move('up', is_test=True)
                            if game_interface.game_map.isValidPos(*next_pos):
                                game_interface.player.move('up')
                                box.move('up')
                    break
                if event.key == pygame.K_r:
                    game_interface.initGame()
                    game_interface.loadLevel(game_level)
        game_interface.draw(game_interface.player, game_interface.game_map)
        if game_interface.game_map.levelCompleted():
            return
        screen.blit(text_render, (5, 5))
        pygame.display.flip()
        clock.tick(100)
'''主函数'''
def main():
    pygame.init()
    pygame.mixer.init()
    pygame.display.set_caption('推箱子 —— 源码基地:#959755565#')
    screen = pygame.display.set_mode(cfg.SCREENSIZE)
    pygame.mixer.init()
    audio_path = os.path.join(cfg.AUDIODIR, 'EineLiebe.mp3')
    pygame.mixer.music.load(audio_path)
    pygame.mixer.music.set_volume(0.4)
    pygame.mixer.music.play(-1)
    startInterface(screen, cfg)
    for level_name in sorted(os.listdir(cfg.LEVELDIR)):
        runGame(screen, level_name)
        switchInterface(screen, cfg)
    endInterface(screen, cfg)
'''run'''
if __name__ == '__main__':
    main()

三.cfg

'''配置文件'''

import os



'''屏幕大小'''

SCREENSIZE = (500, 500)

'''block大小'''

BLOCKSIZE = 50

'''levels所在文件夹'''

LEVELDIR = os.path.join(os.getcwd(), 'resources/levels')

'''图片所在文件夹'''

IMAGESDIR = os.path.join(os.getcwd(), 'resources/images')

'''字体所在文件夹'''

FONTDIR = os.path.join(os.getcwd(), 'resources/font')

'''音频所在文件夹'''

AUDIODIR = os.path.join(os.getcwd(), 'resources/audios')

'''背景颜色'''

BACKGROUNDCOLOR = (45, 45, 45)

四.README


# Introduction

https://mp.weixin.qq.com/s/y6CZd4h3uo7602LrI7aFdQ


# Environment

```

OS: Windows10

Python: Python3.5+(have installed necessary dependencies)

```


# Usage

```

Step1:

pip install -r requirements.txt

Step2:

run "python Game12.py"

```


# Game Display

![giphy](demonstration/running.gif)


相关文章
|
11天前
|
缓存 监控 测试技术
Python中的装饰器:功能扩展与代码复用的利器###
本文深入探讨了Python中装饰器的概念、实现机制及其在实际开发中的应用价值。通过生动的实例和详尽的解释,文章展示了装饰器如何增强函数功能、提升代码可读性和维护性,并鼓励读者在项目中灵活运用这一强大的语言特性。 ###
|
15天前
|
缓存 开发者 Python
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第35天】装饰器在Python中是一种强大的工具,它允许开发者在不修改原有函数代码的情况下增加额外的功能。本文旨在通过简明的语言和实际的编码示例,带领读者理解装饰器的概念、用法及其在实际编程场景中的应用,从而提升代码的可读性和复用性。
|
11天前
|
Python
探索Python中的装饰器:简化代码,提升效率
【10月更文挑战第39天】在编程的世界中,我们总是在寻找使代码更简洁、更高效的方法。Python的装饰器提供了一种强大的工具,能够让我们做到这一点。本文将深入探讨装饰器的基本概念,展示如何通过它们来增强函数的功能,同时保持代码的整洁性。我们将从基础开始,逐步深入到装饰器的高级用法,让你了解如何利用这一特性来优化你的Python代码。准备好让你的代码变得更加优雅和强大了吗?让我们开始吧!
18 1
|
12天前
|
存储 缓存 监控
掌握Python装饰器:提升代码复用性与可读性的利器
在本文中,我们将深入探讨Python装饰器的概念、工作原理以及如何有效地应用它们来增强代码的可读性和复用性。不同于传统的函数调用,装饰器提供了一种优雅的方式来修改或扩展函数的行为,而无需直接修改原始函数代码。通过实际示例和应用场景分析,本文旨在帮助读者理解装饰器的实用性,并鼓励在日常编程实践中灵活运用这一强大特性。
|
14天前
|
机器学习/深度学习 数据采集 人工智能
探索机器学习:从理论到Python代码实践
【10月更文挑战第36天】本文将深入浅出地介绍机器学习的基本概念、主要算法及其在Python中的实现。我们将通过实际案例,展示如何使用scikit-learn库进行数据预处理、模型选择和参数调优。无论你是初学者还是有一定基础的开发者,都能从中获得启发和实践指导。
31 2
|
2月前
|
人工智能 数据挖掘 数据处理
揭秘Python编程之美:从基础到进阶的代码实践之旅
【9月更文挑战第14天】本文将带领读者深入探索Python编程语言的魅力所在。通过简明扼要的示例,我们将揭示Python如何简化复杂问题,提升编程效率。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往高效编码世界的大门。让我们开始这段充满智慧和乐趣的Python编程之旅吧!
|
6月前
|
算法 编译器 开发者
如何提高Python代码的性能:优化技巧与实践
本文探讨了如何提高Python代码的性能,重点介绍了一些优化技巧与实践方法。通过使用适当的数据结构、算法和编程范式,以及利用Python内置的性能优化工具,可以有效地提升Python程序的执行效率,从而提升整体应用性能。本文将针对不同场景和需求,分享一些实用的优化技巧,并通过示例代码和性能测试结果加以说明。
|
1月前
|
大数据 Python
Python 高级编程:深入探索高级代码实践
本文深入探讨了Python的四大高级特性:装饰器、生成器、上下文管理器及并发与并行编程。通过装饰器,我们能够在不改动原函数的基础上增添功能;生成器允许按需生成值,优化处理大数据;上下文管理器确保资源被妥善管理和释放;多线程等技术则助力高效完成并发任务。本文通过具体代码实例详细解析这些特性的应用方法,帮助读者提升Python编程水平。
96 5
|
3月前
|
机器学习/深度学习 Python
时间序列特征提取:从理论到Python代码实践
时间序列是一种特殊的存在。这意味着你对表格数据或图像进行的许多转换/操作/处理技术对于时间序列来说可能根本不起作用。
60 1
时间序列特征提取:从理论到Python代码实践
|
1月前
|
数据采集 机器学习/深度学习 数据处理
Python编程之魔法:从基础到进阶的代码实践
在编程的世界里,Python以其简洁和易读性而闻名。本文将通过一系列精选的代码示例,引导你从Python的基础语法出发,逐步探索更深层次的应用,包括数据处理、网络爬虫、自动化脚本以及机器学习模型的构建。每个例子都将是一次新的发现,带你领略Python编程的魅力。无论你是初学者还是希望提升技能的开发者,这些示例都将是你的宝贵财富。让我们开始这段Python编程之旅,一起揭开它的魔法面纱。
下一篇
无影云桌面