✅作者简介:华为开发者联盟优质内容创作者、CSDN内容合伙人、GitHub专业技术人员 个人主页:北雨·寒冰~ 的CSDN博客 系列专栏:PyGame 个人格言:书山有路勤为径,学海无涯苦作舟

 

目录

前言

看效果

1.基础设置(tools部分)

2.设置背景音乐以及场景中的文字(setup部分)

3.设置游戏规则(load_screen)

4.设置游戏内菜单等(main_menu)

5.main()

6.调用以上函数实现

前言

最近在家上网课,闲得无聊,就想到用PyGame包自制一个“超级马里奥”的小游戏,在同学面前秀一手。

今天,寒冰就带大家来看看“超级马里奥”的全编写过程!

(当然pip install pygame应该不用我说了吧。。。)

也阔以“直接跳到文末”下载资源!!!

看效果

 1.基础设置(tools部分)

这个部分设置马里奥以及游戏中蘑菇等怪的的移动设置

import os

import pygame as pg

keybinding = {

'action':pg.K_s,

'jump':pg.K_a,

'left':pg.K_LEFT,

'right':pg.K_RIGHT,

'down':pg.K_DOWN

}

class Control(object):

"""Control class for entire project. Contains the game loop, and contains

the event_loop which passes events to States as needed. Logic for flipping

states is also found here."""

def __init__(self, caption):

self.screen = pg.display.get_surface()

self.done = False

self.clock = pg.time.Clock()

self.caption = caption

self.fps = 60

self.show_fps = False

self.current_time = 0.0

self.keys = pg.key.get_pressed()

self.state_dict = {}

self.state_name = None

self.state = None

def setup_states(self, state_dict, start_state):

self.state_dict = state_dict

self.state_name = start_state

self.state = self.state_dict[self.state_name]

def update(self):

self.current_time = pg.time.get_ticks()

if self.state.quit:

self.done = True

elif self.state.done:

self.flip_state()

self.state.update(self.screen, self.keys, self.current_time)

def flip_state(self):

previous, self.state_name = self.state_name, self.state.next

persist = self.state.cleanup()

self.state = self.state_dict[self.state_name]

self.state.startup(self.current_time, persist)

self.state.previous = previous

def event_loop(self):

for event in pg.event.get():

if event.type == pg.QUIT:

self.done = True

elif event.type == pg.KEYDOWN:

self.keys = pg.key.get_pressed()

self.toggle_show_fps(event.key)

elif event.type == pg.KEYUP:

self.keys = pg.key.get_pressed()

self.state.get_event(event)

def toggle_show_fps(self, key):

if key == pg.K_F5:

self.show_fps = not self.show_fps

if not self.show_fps:

pg.display.set_caption(self.caption)

def main(self):

"""Main loop for entire program"""

while not self.done:

self.event_loop()

self.update()

pg.display.update()

self.clock.tick(self.fps)

if self.show_fps:

fps = self.clock.get_fps()

with_fps = "{} - {:.2f} FPS".format(self.caption, fps)

pg.display.set_caption(with_fps)

class _State(object):

def __init__(self):

self.start_time = 0.0

self.current_time = 0.0

self.done = False

self.quit = False

self.next = None

self.previous = None

self.persist = {}

def get_event(self, event):

pass

def startup(self, current_time, persistant):

self.persist = persistant

self.start_time = current_time

def cleanup(self):

self.done = False

return self.persist

def update(self, surface, keys, current_time):

pass

def load_all_gfx(directory, colorkey=(255,0,255), accept=('.png', 'jpg', 'bmp')):

graphics = {}

for pic in os.listdir(directory):

name, ext = os.path.splitext(pic)

if ext.lower() in accept:

img = pg.image.load(os.path.join(directory, pic))

if img.get_alpha():

img = img.convert_alpha()

else:

img = img.convert()

img.set_colorkey(colorkey)

graphics[name]=img

return graphics

def load_all_music(directory, accept=('.wav', '.mp3', '.ogg', '.mdi')):

songs = {}

for song in os.listdir(directory):

name,ext = os.path.splitext(song)

if ext.lower() in accept:

songs[name] = os.path.join(directory, song)

return songs

def load_all_fonts(directory, accept=('.ttf')):

return load_all_music(directory, accept)

def load_all_sfx(directory, accept=('.wav','.mpe','.ogg','.mdi')):

effects = {}

for fx in os.listdir(directory):

name, ext = os.path.splitext(fx)

if ext.lower() in accept:

effects[name] = pg.mixer.Sound(os.path.join(directory, fx))

return effects

2.设置背景音乐以及场景中的文字(setup部分)

该部分主要设置场景中的背景音乐,以及字体的显示等设置 

import os

import pygame as pg

from . import tools

from .import constants as c

ORIGINAL_CAPTION = c.ORIGINAL_CAPTION

os.environ['SDL_VIDEO_CENTERED'] = '1'

pg.init()

pg.event.set_allowed([pg.KEYDOWN, pg.KEYUP, pg.QUIT])

pg.display.set_caption(c.ORIGINAL_CAPTION)

SCREEN = pg.display.set_mode(c.SCREEN_SIZE)

SCREEN_RECT = SCREEN.get_rect()

FONTS = tools.load_all_fonts(os.path.join("resources","fonts"))

MUSIC = tools.load_all_music(os.path.join("resources","music"))

GFX = tools.load_all_gfx(os.path.join("resources","graphics"))

SFX = tools.load_all_sfx(os.path.join("resources","sound"))

 3.设置游戏规则(load_screen)

from .. import setup, tools

from .. import constants as c

from .. import game_sound

from ..components import info

class LoadScreen(tools._State):

def __init__(self):

tools._State.__init__(self)

def startup(self, current_time, persist):

self.start_time = current_time

self.persist = persist

self.game_info = self.persist

self.next = self.set_next_state()

info_state = self.set_overhead_info_state()

self.overhead_info = info.OverheadInfo(self.game_info, info_state)

self.sound_manager = game_sound.Sound(self.overhead_info)

def set_next_state(self):

"""Sets the next state"""

return c.LEVEL1

def set_overhead_info_state(self):

"""sets the state to send to the overhead info object"""

return c.LOAD_SCREEN

def update(self, surface, keys, current_time):

"""Updates the loading screen"""

if (current_time - self.start_time) < 2400:

surface.fill(c.BLACK)

self.overhead_info.update(self.game_info)

self.overhead_info.draw(surface)

elif (current_time - self.start_time) < 2600:

surface.fill(c.BLACK)

elif (current_time - self.start_time) < 2635:

surface.fill((106, 150, 252))

else:

self.done = True

class GameOver(LoadScreen):

"""A loading screen with Game Over"""

def __init__(self):

super(GameOver, self).__init__()

def set_next_state(self):

"""Sets next state"""

return c.MAIN_MENU

def set_overhead_info_state(self):

"""sets the state to send to the overhead info object"""

return c.GAME_OVER

def update(self, surface, keys, current_time):

self.current_time = current_time

self.sound_manager.update(self.persist, None)

if (self.current_time - self.start_time) < 7000:

surface.fill(c.BLACK)

self.overhead_info.update(self.game_info)

self.overhead_info.draw(surface)

elif (self.current_time - self.start_time) < 7200:

surface.fill(c.BLACK)

elif (self.current_time - self.start_time) < 7235:

surface.fill((106, 150, 252))

else:

self.done = True

class TimeOut(LoadScreen):

"""Loading Screen with Time Out"""

def __init__(self):

super(TimeOut, self).__init__()

def set_next_state(self):

"""Sets next state"""

if self.persist[c.LIVES] == 0:

return c.GAME_OVER

else:

return c.LOAD_SCREEN

def set_overhead_info_state(self):

"""Sets the state to send to the overhead info object"""

return c.TIME_OUT

def update(self, surface, keys, current_time):

self.current_time = current_time

if (self.current_time - self.start_time) < 2400:

surface.fill(c.BLACK)

self.overhead_info.update(self.game_info)

self.overhead_info.draw(surface)

else:

self.done = True

 4.设置游戏内菜单等(main_menu)

import pygame as pg

from .. import setup, tools

from .. import constants as c

from .. components import info, mario

class Menu(tools._State):

def __init__(self):

"""Initializes the state"""

tools._State.__init__(self)

persist = {c.COIN_TOTAL: 0,

c.SCORE: 0,

c.LIVES: 3,

c.TOP_SCORE: 0,

c.CURRENT_TIME: 0.0,

c.LEVEL_STATE: None,

c.CAMERA_START_X: 0,

c.MARIO_DEAD: False}

self.startup(0.0, persist)

def startup(self, current_time, persist):

"""Called every time the game's state becomes this one. Initializes

certain values"""

self.next = c.LOAD_SCREEN

self.persist = persist

self.game_info = persist

self.overhead_info = info.OverheadInfo(self.game_info, c.MAIN_MENU)

self.sprite_sheet = setup.GFX['title_screen']

self.setup_background()

self.setup_mario()

self.setup_cursor()

def setup_cursor(self):

"""Creates the mushroom cursor to select 1 or 2 player game"""

self.cursor = pg.sprite.Sprite()

dest = (220, 358)

self.cursor.image, self.cursor.rect = self.get_image(

24, 160, 8, 8, dest, setup.GFX['item_objects'])

self.cursor.state = c.PLAYER1

def setup_mario(self):

"""Places Mario at the beginning of the level"""

self.mario = mario.Mario()

self.mario.rect.x = 110

self.mario.rect.bottom = c.GROUND_HEIGHT

def setup_background(self):

"""Setup the background image to blit"""

self.background = setup.GFX['level_1']

self.background_rect = self.background.get_rect()

self.background = pg.transform.scale(self.background,

(int(self.background_rect.width*c.BACKGROUND_MULTIPLER),

int(self.background_rect.height*c.BACKGROUND_MULTIPLER)))

self.viewport = setup.SCREEN.get_rect(bottom=setup.SCREEN_RECT.bottom)

self.image_dict = {}

self.image_dict['GAME_NAME_BOX'] = self.get_image(

1, 60, 176, 88, (170, 100), setup.GFX['title_screen'])

def get_image(self, x, y, width, height, dest, sprite_sheet):

"""Returns images and rects to blit onto the screen"""

image = pg.Surface([width, height])

rect = image.get_rect()

image.blit(sprite_sheet, (0, 0), (x, y, width, height))

if sprite_sheet == setup.GFX['title_screen']:

image.set_colorkey((255, 0, 220))

image = pg.transform.scale(image,

(int(rect.width*c.SIZE_MULTIPLIER),

int(rect.height*c.SIZE_MULTIPLIER)))

else:

image.set_colorkey(c.BLACK)

image = pg.transform.scale(image,

(int(rect.width*3),

int(rect.height*3)))

rect = image.get_rect()

rect.x = dest[0]

rect.y = dest[1]

return (image, rect)

def update(self, surface, keys, current_time):

"""Updates the state every refresh"""

self.current_time = current_time

self.game_info[c.CURRENT_TIME] = self.current_time

self.update_cursor(keys)

self.overhead_info.update(self.game_info)

surface.blit(self.background, self.viewport, self.viewport)

surface.blit(self.image_dict['GAME_NAME_BOX'][0],

self.image_dict['GAME_NAME_BOX'][1])

surface.blit(self.mario.image, self.mario.rect)

surface.blit(self.cursor.image, self.cursor.rect)

self.overhead_info.draw(surface)

def update_cursor(self, keys):

"""Update the position of the cursor"""

input_list = [pg.K_RETURN, pg.K_a, pg.K_s]

if self.cursor.state == c.PLAYER1:

self.cursor.rect.y = 358

if keys[pg.K_DOWN]:

self.cursor.state = c.PLAYER2

for input in input_list:

if keys[input]:

self.reset_game_info()

self.done = True

elif self.cursor.state == c.PLAYER2:

self.cursor.rect.y = 403

if keys[pg.K_UP]:

self.cursor.state = c.PLAYER1

def reset_game_info(self):

"""Resets the game info in case of a Game Over and restart"""

self.game_info[c.COIN_TOTAL] = 0

self.game_info[c.SCORE] = 0

self.game_info[c.LIVES] = 3

self.game_info[c.CURRENT_TIME] = 0.0

self.game_info[c.LEVEL_STATE] = None

self.persist = self.game_info

5.main()

from . import setup,tools

from .states import main_menu,load_screen,level1

from . import constants as c

def main():

"""Add states to control here."""

run_it = tools.Control(setup.ORIGINAL_CAPTION)

state_dict = {c.MAIN_MENU: main_menu.Menu(),

c.LOAD_SCREEN: load_screen.LoadScreen(),

c.TIME_OUT: load_screen.TimeOut(),

c.GAME_OVER: load_screen.GameOver(),

c.LEVEL1: level1.Level1()}

run_it.setup_states(state_dict, c.MAIN_MENU)

run_it.main()

6.调用以上函数实现

import sys

import pygame as pg

from 小游戏.超级玛丽.data.main import main

import cProfile

if __name__=='__main__':

main()

pg.quit()

sys.exit()

在这里主要给大家展示主体的代码,完整资源戳我领取!!

结束语 

今天的分享就到这里啦~,感谢你的观看,拜拜喽~

参考阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: