The cover of Super Mario is finished, who said novices can’t learn it !

Super Mario tools and environment construction

Reference documents used ๐Ÿ

The official documentation is still used here, which covers the use and description of all Pygame methods. It is very convenient to open it when writing code: Pygame official documentation

List of directories built by the project ๐Ÿฆ‹

This blog is mainly to explain these files. Of course, content will be added to it later. Level.py has not been written here yet. Donโ€™t worry, level.py will be the real big BOSS in the follow-up, everyone first. Deal with the front cover and other production! ๐Ÿ˜ผ

The main renderings of the content of this blog are displayed ๐Ÿฌ

What we have to do this time is our most important cover~~~~~~The following is the effect

Perverted version~~~
Please put it so handsome, I will make it and put it in the comment area (there are all of them below, I have prepared the cover code, it is dynamic, and you can see the effect when everyone is done below, this The project is also very big, everyone should persevere ๐Ÿ‘ฉโ€๐Ÿฆฐ)

File code analysis ๐Ÿคพโ€โ™€๏ธ

tools.py content and description ๐Ÿ˜ผ

illustrate

The tools file is very, very important, it is all the foundation and tools behind, so you must get it done๐Ÿคบ Because it uses a skill, the most important one is the “cutout” skill, friends who have downloaded the material package must find it Now, a lot of things are in a picture, we only want a few of them, so we need to “cut” them out

code

import pygame
import us
class  Game : 
    def  __init__ ( self , state_dict, start_state) :
         self .screen = pygame.display.get_surface()   ##Get the currently displayed Surface object 
        self .clock = pygame.time.Clock()
         self .keys = pygame. key.get_pressed()   # return bools(just a simple judges) 
        self .state_dict = state_dict      # The dictionary of state transfer dictionary commonly used objects to pass 
        self .state = self .state_dict[start_state]   ##The initial state is here---- - 'main_mune'

    def  update ( self ) :   ##Status update 
        if  self .state.finished :   ##Determine whether the current state is over 
            game_info = self .state.game_info
            next_state = self.state.next
            self.state.finished = False
            self.state = self.state_dict[next_state]
        self.state.update(self.screen, self.keys)

    def  run ( self ) :
         while  True:   ##event event 
            for event in pygame.event.get():   ###pygame.event.get() get event from queue 
                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))   ##Draw an image on top of another 
    image.set_colorkey(colorkey)   # Snapshot set_colorkey(colorkey) Set the background to transparent
    image = pygame.transform.scale(image, (int(width * scale), int(height * scale)))
    return image

setup.py content and description

This function does not have a particularly important role, it is mainly created to assist tools.py

code

import pygame as pg
from . import Invariant as I
from . import tools
pg.init()
GRAPHICS = tools.load_graphics('resources/graphics')

mainmenu.py content and description

code

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

class MainMenu():
    def __init__(self):
        game_info = {   ##Set the initial state (you can modify it by yourself hahaha) 
            'score' : 0 ,
             'coin' : 0 ,
             'lives' : 3 ,
             'player_state' : 'small'
        }
        self.start(game_info)

    def  start ( self , game_info) :   ##Initialize cover content 
        self .game_info = game_info
         self .setup_background()     ##Set background, map information 
        self .setup_player()
         self .setup_cursor()
         self .info = info.Info( 'main_menu ' , self .game_info)
         self .finished = False     ##Determine whether a state ends 
        self .next = 'load_screen' ## The next state  

    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 ) :   ## Set the cursor position 
        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

    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()   ##Every time you press Enter, the game data starts the game from the beginning data 
            if  self .cursor.state == '1P' :
                 self .finished = True
            elif self.cursor.state == '2P':
                self.finished = True

        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({   ##Restored state after death 
            'score' : 0 ,
             'coin' : 0 ,
             'lives' : 3 ,
             'player_state' : 'small' 
        })

Perverted Mary’s code (it’s just a little more stuff)

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


#The principle of updating first and drawing later 
class  MainMenu : 
    def  __init__ ( self ) :   ##Mario initial various settings
        game_info = {
            'score': 0,
            'coin': 0,
            'lives': 3,
            'player_state': 'small'
        }
        self.start(game_info)


    def start(self, 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)
        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

    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()   ##Every time you press Enter, the game data starts the game from the beginning data 
            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 content description

code

import pygame

from state import tools, Invariant as I,setup
from source import coin
pygame.font.init()    ##Font font~~ 
class  Info (): 
    def  __init__ ( self , state, game_info) :
         self .state = state
         self .game_info = game_info
         self .create_state_labels() #Used to pass each stage Specific numerical information 
        self .create_info_labels() #Used    to pass information such as specific gold coins and time information 
        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()


        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 content description

code

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 content description

code

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']
            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() #Return   the time 
        frame_durations = [ 325 , 125 , 125 , 125 ]     ##The duration of each picture 
        if  self .timer == 0 :   #Indicate that this is the starting state 
            self .timer = self .current_time
        elif self.current_time - self.timer > frame_durations[self.frame_index]:
            self.frame_index += 1
        self.image = self.frames[self.frame_index]

Invariant.py content and description

It is just to store some commonly used variables๐Ÿฅด

code

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

BG_REPEAT = 2.68
BRICK_REPEAT = 2.69
ENEMY_REPEAT = 2.5
ENEMY_SPEED = 1
MG_REPEAT =0.21
PLAYER_REPEAT = 3
MONSTER = 0.8
Font = 'Fixedsys.ttf' ##Use this because it is similar to the font of the Super Mario game, you can also use other fonts
MARIO_P = 1.6
GRAVITY = 1.0
ANTI_GRAVITY = 0.3

main.py content and description

code

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()

final effect display

Of course, there will be a warning at the end, because there is no next state, the next one will come to our most important part—->level.py~๐Ÿ˜†๐Ÿ˜†

I personally think that if you are new to pygame, there will be a certain degree of difficulty. I will explain the implementation of many details in a separate blog, such as how the map is implemented and so on. Now I just give you the main part of the code. Any questions welcome private message, comment

ppp: Remember to like, follow and comment๐ŸŽ€

Leave a Comment

Your email address will not be published. Required fields are marked *