超级玛丽封面完工制作,谁说新手不能学哒??!

2023-05-16

超级玛丽之工具、环境的搭建

  • 所用参考文档🐍
  • 项目搭建的目录列表🦋
  • 本次博客内容主要呈现的效果图展示🍬
  • 文件代码分析🤾‍♀️
    • tools.py内容和说明😼
      • 说明
      • 代码
    • setup.py内容和说明
      • 代码
    • mainmenu.py内容和说明
      • 代码
      • 变态玛丽的代码(就只是这个多了些东西而已啦)
    • info.py内容说明
      • 代码
    • load_screen内容说明
      • 代码
    • coin.py内容说明
      • 代码
    • Invariant.py内容和说明
      • 代码
    • main.py内容和说明
      • 代码
  • 最终效果展示

所用参考文档🐍

这里使用的还是官方的文档,里面涵盖所有的Pygame的方法使用和说明,写代码时打开在旁边非常方便:Pygame官方文档

项目搭建的目录列表🦋

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
本篇博客主要就是对这几个文件进行说明,后续当然会往里头增加内容,level.py在这里还没有写入噢,大家别急,level.py在后续就是真正的大BOSS啦,大家先处理好前面的封面等制作吧!😼

本次博客内容主要呈现的效果图展示🍬

这次要做的就是我们最重要的封面~~~~~~下面是效果

在这里插入图片描述

变态版本~~~
在这里插入图片描述
请把好帅,我要做出来打在评论区上(都有都有的下面都有,封面代码我都准备好啦,本身是动态的,等下面大家做完了就可以看到效果了,这个工程也是非常大的,大家要坚持住👩‍🦰)
在这里插入图片描述

文件代码分析🤾‍♀️

tools.py内容和说明😼

说明

tools这个文件是非常非常重要的,是后面所有的基础和工具,所以大家一定要搞定它🤺因为它用到了一个技能,最重要的一个就是“抠图”技能,下载了素材包的朋友一定发现了,很多东西都在一张图片里面,我们要的只是其中的几个而已,所以需要“抠”出来

代码

import pygame
import os
class Game:
    def __init__(self, state_dict, start_state):
        self.screen = pygame.display.get_surface()  ##获取当前显示的Surface的对象
        self.clock = pygame.time.Clock()
        self.keys = pygame.key.get_pressed()  # return bools(just a simple judges)
        self.state_dict = state_dict     # 状态转移字典  常用对象的字典来传递
        self.state = self.state_dict[start_state]  ##初始的状态  在这里-----‘main_mune’

    def update(self):  ##状态更新
        if self.state.finished:  ##判断目前的状态是否结束
            game_info = self.state.game_info
            next_state = self.state.next
            self.state.finished = False
            self.state = self.state_dict[next_state]
            self.state.start(game_info)  ##传给下一个阶段的start方法
        self.state.update(self.screen, self.keys)

    def run(self):
        while True:  ##event事件
            for event in pygame.event.get():  ###pygame.event.get()从队列中获取事件
                if event.type == pygame.QUIT:
                    pygame.display.quit()
                    quit()
                elif event.type == pygame.KEYDOWN:
                    self.keys = pygame.key.get_pressed()
                elif event.type == pygame.KEYUP:
                    self.keys = pygame.key.get_pressed()
            self.update()
            pygame.display.update()
            self.clock.tick(40)

def load_graphics(path, accept=('.jpg', '.png', '.gif', '.bmp')):
    graphics = {}
    for pic in os.listdir(path):
        name, ext = os.path.splitext(pic)
        if ext.lower() in accept:
            img = pygame.image.load(os.path.join(path, pic))
            if img.get_alpha():
                img = img.convert_alpha()
            else:
                img = img.convert()
            graphics[name] = img
    return graphics

def get_image(sheet, x, y, width, height, colorkey, scale):
    image = pygame.Surface((width, height))
    image.blit(sheet, (0, 0), (x, y, width, height))  ##绘制一个图像在另一个图像上方
    image.set_colorkey(colorkey)  # 扣图 set_colorkey(colorkey)  设置背景为透明
    image = pygame.transform.scale(image, (int(width * scale), int(height * scale)))
    return image

setup.py内容和说明

这个函数没有特别重要的作用,主要是为了辅助tools.py而创立

代码

import pygame as pg
from . import Invariant as I
from . import tools
pg.init()
SCREEN = pg.display.set_mode((I.SCREEN_W, I.SCREEN_H))##封装
GRAPHICS = tools.load_graphics('resources/graphics')

mainmenu.py内容和说明

代码

from state import tools, Invariant as I, setup
import pygame
from source import info

class MainMenu():
    def __init__(self):
        game_info = {  ##设置初始的状态(可以自行修改哈哈哈哈)
            'score': 0,
            'coin': 0,
            'lives': 3,
            'player_state': 'small'
        }
        self.start(game_info)

    def start(self, game_info):  ##初始化封面内容
        self.game_info = game_info
        self.setup_background()    ##设置背景、地图信息
        self.setup_player()
        self.setup_cursor()
        self.info = info.Info('main_menu', self.game_info)
        self.finished = False    ##判断某一个状态是否结束
        self.next = 'load_screen'  ##下一个状态

    def setup_background(self):
        self.background = setup.GRAPHICS['level_1']
        self.background_rect = self.background.get_rect()
        self.background = pygame.transform.scale(self.background, (int(self.background_rect.width * I.BG_MULIT),
                                                                   int(self.background_rect.height * I.BG_MULIT)))
        self.viewport = setup.SCREEN.get_rect()
        self.caption = tools.get_image(setup.GRAPHICS['title_screen'], 1, 60, 176, 88, (255, 0, 220), I.BG_MULIT)

    def setup_player(self):
        self.player_image = tools.get_image(setup.GRAPHICS['mario_bros'], 178, 32, 12, 16, (0, 0, 0), I.PLAYER_MULIT)

    def setup_cursor(self):  ## 设置光标的位置
        self.cursor = pygame.sprite.Sprite()
        self.cursor.image = tools.get_image(setup.GRAPHICS['item_objects'], 160, 48, 16, 16, (0,0,0), 1.5)
        rect = self.cursor.image.get_rect()
        rect.x, rect.y = (300, 360)
        self.cursor.rect = rect
        self.cursor.state = '1P' #状态机

    def update_cursor(self, keys):
        if keys[pygame.K_UP]:
            self.cursor.state = '1P'
            self.cursor.rect.y = 360
        elif keys[pygame.K_DOWN]:
            self.cursor.state = '2P'
            self.cursor.rect.y = 405
        elif keys[pygame.K_RETURN]:
            self.reset_game_info()  ##每次按下回车的时候  游戏的数据就又从最开始的数据开始游戏
            if self.cursor.state == '1P':
                self.finished = True
            elif self.cursor.state == '2P':
                self.finished = True

    def update(self, surface, keys):## 画布
        surface.blit(self.background, self.viewport)
        surface.blit(self.caption, (300, 100))
        surface.blit(self.cursor.image, self.cursor.rect)
        surface.blit(self.player_image, (250, 490))

        self.info.update()
        self.info.draw(surface)
        self.update_cursor(keys)


    def reset_game_info(self):
        self.game_info.update({  ##死亡之后重新回复的状态
            'score': 0,
            'coin': 0,
            'lives': 3,
            'player_state': 'small'
        })

变态玛丽的代码(就只是这个多了些东西而已啦)

from state import tools, Invariant as I, setup
import pygame
from source import info


#先更新、后绘图的原则
class MainMenu:
    def __init__(self):  ##马里奥初始的各种设定
        game_info = {
            'score': 0,
            'coin': 0,
            'lives': 3,
            'player_state': 'small'
        }
        self.start(game_info)


    def start(self, game_info):
        self.game_info = game_info    ##传递初始的一些信息
        self.setup_background()
        self.setup_player()
        self.setup_cursor()
        self.info = info.Info('main_menu', self.game_info)
        self.finished = False
        self.next = 'load_screen'

    def setup_background(self):
        self.background = setup.GRAPHICS['level_2']
        self.background_rect = self.background.get_rect()
        self.background = pygame.transform.scale(self.background, (int(self.background_rect.width*I.BG_MULIT),
                                                                               int(self.background_rect.height*I.BG_MULIT)))
        self.viewport = setup.SCREEN.get_rect()
        self.caption = tools.get_image(setup.GRAPHICS['title_screen'], 1, 60, 176, 88, (255, 0, 220), I.BG_MULIT)


    def setup_player(self):
        self.player_image   = tools.get_image(setup.GRAPHICS['mario_bros'], 178, 32, 12, 16, (0, 0, 0), I.PLAYER_MULIT)
        self.player_image_1 = tools.get_image(setup.GRAPHICS['mario_bros'], 192, 80, 16, 17, (0, 0, 0), I.PLAYER_MULIT)
        self.player_image_2 = tools.get_image(setup.GRAPHICS['mario_bros'], 143, 127, 16, 16, (0, 0, 0), I.PLAYER_MULIT)
        self.player_image_3 = tools.get_image(setup.GRAPHICS['mario_bros'], 78, 176, 16, 16, (0, 0, 0), I.PLAYER_MULIT)
        self.player_image_4 = tools.get_image(setup.GRAPHICS['smb_enemies_sheet'], 85, 58, 23, 27, (0, 0, 0), I.PLAYER_MULIT)
        self.player_image_5 = tools.get_image(setup.GRAPHICS['smb_enemies_sheet'], 0, 0, 19, 23, (0, 0, 0), I.PLAYER_MULIT)
        self.player_image_6 = tools.get_image(setup.GRAPHICS['mario'], 463, 359, 29, 26, (239, 228, 176), I.PLAYER_MULIT)
        self.player_image_7 = tools.get_image(setup.GRAPHICS['mario'], 289, 624, 22, 35, (239, 228, 176), I.PLAYER_MULIT)
        self.player_image_8 = tools.get_image(setup.GRAPHICS['mario'], 15, 1254, 25, 26, (239, 228, 176), I.PLAYER_MULIT)
        self.player_image_9 = tools.get_image(setup.GRAPHICS['mario'], 29, 1784, 19, 34, (239, 228, 176), I.PLAYER_MULIT)
        self.player_image_10 = tools.get_image(setup.GRAPHICS['mario'], 565, 1077, 28, 19, (239, 228, 176), I.PLAYER_MULIT)
        self.player_image_11 = tools.get_image(setup.GRAPHICS['mario'], 487, 1409, 18, 35, (239, 228, 176), I.PLAYER_MULIT)
        self.player_image_12 = tools.get_image(setup.GRAPHICS['smb_custom_enemies'], 117, 475, 21, 30, (163, 73, 164), I.PLAYER_MULIT)
        self.player_image_13 = tools.get_image(setup.GRAPHICS['smb_custom_enemies'], 444, 310, 48, 83, (163, 73, 164), I.PLAYER_MULIT)
        self.player_image_14 = tools.get_image(setup.GRAPHICS['smb_custom_enemies'], 424, 832, 87, 68, (163, 73, 164), I.MARIO_P)
        self.player_image_15 = tools.get_image(setup.GRAPHICS['smb_custom_enemies'], 95, 347, 18, 25, (163, 73, 164), I.PLAYER_MULIT)
        self.player_image_15_flip = pygame.transform.flip(self.player_image_15, True, False)
        self.skill = tools.get_image(setup.GRAPHICS['smb_custom_enemies'], 116, 353, 9, 9, (163, 73, 164), I.PLAYER_MULIT)
    def setup_cursor(self):  ## 设置光标的位置
        self.cursor = pygame.sprite.Sprite()
        self.cursor.image = tools.get_image(setup.GRAPHICS['item_objects'], 160, 48, 16, 16, (255, 255, 255), 1.5)
        rect = self.cursor.image.get_rect()
        rect.x, rect.y = (300, 360)
        self.cursor.rect = rect
        self.cursor.state = '1P' #状态机

    def update_cursor(self, keys):
        if keys[pygame.K_UP]:
            self.cursor.state = '1P'
            self.cursor.rect.y = 360
        elif keys[pygame.K_DOWN]:
            self.cursor.state = '2P'
            self.cursor.rect.y = 405
        elif keys[pygame.K_RETURN]:
            self.reset_game_info()  ##每次按下回车的时候  游戏的数据就又从最开始的数据开始游戏
            if self.cursor.state == '1P':
                self.finished = True
            elif self.cursor.state == '2P':
                self.finished = True


    def update(self, surface, keys):
       surface.blit(self.background, self.viewport)
       surface.blit(self.caption, (300, 100))
       surface.blit(self.cursor.image, self.cursor.rect)
       surface.blit(self.player_image_4, (600, 460))
       surface.blit(self.player_image_5, (700, 480))
       surface.blit(self.player_image_6, (200, 200))
       surface.blit(self.player_image_7, (150, 300))
       surface.blit(self.player_image_8, (100, 200))
       surface.blit(self.player_image_9, (40, 433))
       surface.blit(self.player_image_10, (50, 100))
       surface.blit(self.player_image_12, (850, 450))
       surface.blit(self.player_image_13, (850, 200))
       surface.blit(self.player_image_14, (300, 430))
       surface.blit(self.player_image_15_flip, (770, 430))
       surface.blit(self.skill, (730, 460))

       self.info.update()
       self.info.draw(surface)
       self.update_cursor(keys)


    def reset_game_info(self):
        self.game_info.update({
            'score': 0,
            'coin': 0,
            'lives': 3,
            'player_state': 'small'
        })


info.py内容说明

代码

import pygame

from state import tools, Invariant as I,setup
from source import coin
pygame.font.init()   ##字体字体~~
class Info():
    def __init__(self, state, game_info):
        self.state = state
        self.game_info = game_info
        self.create_state_labels() #用来传递每个阶段特定的数值信息
        self.create_info_labels()   #用来传递特定的金币啊时间信息等信息
        self.flash_coin = coin.FlashingCoin()

    def create_state_labels(self):
        self.state_labels = []
        if self.state == 'main_menu':
            self.state_labels.append((self.create_label('1 have fun'), (400, 360)))
            self.state_labels.append((self.create_label('2 have fun'), (400, 405)))
            self.state_labels.append((self.create_label('TOP - '), (410, 450)))
            self.state_labels.append((self.create_label('000000'), (500, 450)))
        elif self.state == 'load_screen':
            self.state_labels.append((self.create_label('WORLD'), (380, 200)))
            self.state_labels.append((self.create_label('1 -- 1'), (530, 200)))
            self.state_labels.append((self.create_label('X     {}'.format(self.game_info['lives'])), (480, 280)))
            self.player_image = tools.get_image(setup.GRAPHICS['mario_bros'], 178, 32, 12, 16, (0, 0, 0), I.BG_MULIT)
        elif self.state == 'game_over':
            self.state_labels.append((self.create_label('Game Over'), (380, 300)))

    def create_info_labels(self):
        self.info_labels = []
        self.info_labels.append((self.create_label('MARIO'), (75, 30)))
        self.info_labels.append((self.create_label('WORLD'), (450, 30)))
        self.info_labels.append((self.create_label('TIME'), (625, 30)))
        self.info_labels.append((self.create_label('000000'), (75, 55)))
        self.info_labels.append((self.create_label('x00'), (300, 55)))
        self.info_labels.append((self.create_label('1 - 1'), (480, 55)))

    def create_label(self, label, size=40, width_scale=1, height_scale=1):
        font = pygame.font.SysFont(I.Font,size)
        label_image = font.render(label, 1, (255, 255, 255))
        rect = label_image.get_rect()
        label_image = pygame.transform.scale(label_image, (int(rect.width*width_scale), int(rect.height*height_scale)))
        return label_image

    def update(self):
        self.flash_coin.update()


    def draw(self, surface):#用来显示
        for label in self.state_labels:
            surface.blit(label[0], label[1])
        for label in self.info_labels:
            surface.blit(label[0], label[1])
        surface.blit(self.flash_coin.image, self.flash_coin.rect)
        if self.state == 'load_screen':
            surface.blit(self.player_image, (400, 270))


load_screen内容说明

代码

import pygame
from source import info

class LoadScreen:
    def start(self, game_info):
        self.game_info = game_info
        self.finished = False

        self.duration = 2000
        self.timer = 0
        self.info = info.Info('load_screen', self.game_info)

    def update(self, surface, keys):
        self.draw(surface)
        if self.timer == 0:
            self.timer = pygame.time.get_ticks()
        elif pygame.time.get_ticks() - self.timer > self.duration:
            self.finished = True
            self.timer = 0


    def draw(self, surface):
        surface.fill((0, 0, 0))
        self.info.draw(surface)

coin.py内容说明

代码

import pygame

from state import tools, Invariant as I, setup
class FlashingCoin(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.frames = []
        self.frame_index = 0
        frame_rects = [(1, 160, 5, 8), (9, 160, 5, 8), (17, 160, 5, 8), (9, 160, 5, 8)]
        self.load_frames(frame_rects)
        self.image = self.frames[self.frame_index]
        self.rect = self.image.get_rect()
        self.rect.x = 280
        self.rect.y = 50
        self.timer = 0


    def load_frames(self, frame_rects):
        sheet = setup.GRAPHICS['item_objects']
        for frame_rect in frame_rects:  ##加载每个图片
            self.frames.append(tools.get_image(sheet, *frame_rect, (0, 0, 0), I.BG_MULIT))

    def update(self):
        self.current_time = pygame.time.get_ticks()  #返回此时的时间
        frame_durations = [325, 125, 125, 125]    ##每个图片停留的时间
        if self.timer == 0:  #说明此时是起始状态
            self.timer = self.current_time
        elif self.current_time - self.timer > frame_durations[self.frame_index]:
            self.frame_index += 1
            self.frame_index %= 4  #循环
            self.timer = self.current_time  #更新
        self.image = self.frames[self.frame_index]

Invariant.py内容和说明

就是存放常用的一些变量而已🥴

代码

SCREEN_W, SCREEN_H = 1000, 600
SCREEN_SIZE = (SCREEN_W, SCREEN_H)
GROUND_HEIGHT = SCREEN_H - 62

BG_MULIT = 2.68
BRICK_MULIT = 2.69
ENEMY_MULIT = 2.5
ENEMY_SPEED = 1
MG_MULIT =0.21
PLAYER_MULIT = 3
MONSTER = 0.8
Font = 'Fixedsys.ttf'##使用这个是因为这个和超级玛丽游戏的字体比较像,大家也可以使用其他的字体
MARIO_P = 1.6
GRAVITY = 1.0
ANTI_GRAVITY = 0.3

main.py内容和说明

代码

from state import tools, main_menu,load_screen

def main():
    state_dict = {
        'main_menu':main_menu.MainMenu(),
        'load_screen': load_screen.LoadScreen(),
    }
    game = tools.Game(state_dict, 'main_menu')
    game.run()

if __name__ == '__main__':
    main()

最终效果展示

在这里插入图片描述

当然了,最后结束的时候是会有警告的,因为没有下一个状态了嘛,下一个就到了我们最重要的部分啦---->level.py~😆😆

我个人认为对于如果是pygame新手的话,会有一定的难度,里面很多细节的实现我会单独弄博客来说明,比如抠图是怎么实现的之类的,现在只是将主要的部分代码给大家,有任何问题欢迎私信,评论
ppp:记得点赞、关注、评论噢🎀

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

超级玛丽封面完工制作,谁说新手不能学哒??! 的相关文章

随机推荐