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中装饰器的概念、实现机制及其在实际开发中的应用价值。通过生动的实例和详尽的解释,文章展示了装饰器如何增强函数功能、提升代码可读性和维护性,并鼓励读者在项目中灵活运用这一强大的语言特性。 ###
|
14天前
|
缓存 开发者 Python
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第35天】装饰器在Python中是一种强大的工具,它允许开发者在不修改原有函数代码的情况下增加额外的功能。本文旨在通过简明的语言和实际的编码示例,带领读者理解装饰器的概念、用法及其在实际编程场景中的应用,从而提升代码的可读性和复用性。
|
11天前
|
Python
探索Python中的装饰器:简化代码,提升效率
【10月更文挑战第39天】在编程的世界中,我们总是在寻找使代码更简洁、更高效的方法。Python的装饰器提供了一种强大的工具,能够让我们做到这一点。本文将深入探讨装饰器的基本概念,展示如何通过它们来增强函数的功能,同时保持代码的整洁性。我们将从基础开始,逐步深入到装饰器的高级用法,让你了解如何利用这一特性来优化你的Python代码。准备好让你的代码变得更加优雅和强大了吗?让我们开始吧!
18 1
|
11天前
|
存储 缓存 监控
掌握Python装饰器:提升代码复用性与可读性的利器
在本文中,我们将深入探讨Python装饰器的概念、工作原理以及如何有效地应用它们来增强代码的可读性和复用性。不同于传统的函数调用,装饰器提供了一种优雅的方式来修改或扩展函数的行为,而无需直接修改原始函数代码。通过实际示例和应用场景分析,本文旨在帮助读者理解装饰器的实用性,并鼓励在日常编程实践中灵活运用这一强大特性。
|
13天前
|
机器学习/深度学习 数据采集 人工智能
探索机器学习:从理论到Python代码实践
【10月更文挑战第36天】本文将深入浅出地介绍机器学习的基本概念、主要算法及其在Python中的实现。我们将通过实际案例,展示如何使用scikit-learn库进行数据预处理、模型选择和参数调优。无论你是初学者还是有一定基础的开发者,都能从中获得启发和实践指导。
29 2
|
6月前
|
设计模式 前端开发 数据库
Django是一个用Python编写的开源Web应用框架
Django是一个用Python编写的开源Web应用框架
57 1
|
5天前
|
存储 数据挖掘 开发者
Python编程入门:从零到英雄
在这篇文章中,我们将一起踏上Python编程的奇幻之旅。无论你是编程新手,还是希望拓展技能的开发者,本教程都将为你提供一条清晰的道路,引导你从基础语法走向实际应用。通过精心设计的代码示例和练习,你将学会如何用Python解决实际问题,并准备好迎接更复杂的编程挑战。让我们一起探索这个强大的语言,开启你的编程生涯吧!
|
11天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
下一篇
无影云桌面