zoukankan      html  css  js  c++  java
  • demo 代码

    有两个文件constants.py 和 state_demo.py
    constants.py 保存了所有的字符串定义和常量

    constants.py
    GAME_TIME_OUT 表示游戏的超时时间,这边为了demo演示,设成了5秒,实际是300秒。

    SCREEN_HEIGHT = 600
    SCREEN_WIDTH = 800
    SCREEN_SIZE = (SCREEN_WIDTH,SCREEN_HEIGHT)

    ORIGINAL_CAPTION = "Super Mario Bros"

    GAME_TIME_OUT = 5

    ## COLORS ##
    # R G B
    BLACK = ( 0, 0, 0)

    SIZE_MULTIPLIER = 2.5
    BRICK_SIZE_MULTIPLIER = 2.69
    BACKGROUND_MULTIPLER = 2.679
    GROUND_HEIGHT = SCREEN_HEIGHT - 62

    #STATES FOR ENTIRE GAME
    MAIN_MENU = 'main menu'
    LOAD_SCREEN = 'load screen'
    TIME_OUT = 'time out'
    GAME_OVER = 'game over'
    LEVEL = 'level'

    #MAIN MENU CURSOR STATES
    PLAYER1 = '1 PLAYER GAME'
    PLAYER2 = '2 PLAYER GAME'

    #GAME INFO DICTIONARY KEYS
    COIN_TOTAL = 'coin total'
    SCORE = 'score'
    TOP_SCORE = 'top score'
    LIVES = 'lives'
    CURRENT_TIME = 'current time'
    LEVEL_NUM = 'level num'
    PLAYER_NAME = 'player name'
    PLAYER_MARIO = 'mario'
    PLAYER_LUIGI = 'luigi'

    ITEM_SHEET = 'item_objects'
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    state_demo.py
    上面讲的状态类,状态机类都放在这里。

    import os
    import pygame as pg
    from abc import ABC, abstractmethod
    import constants as c


    class State():
    def __init__(self):
    self.start_time = 0.0
    self.current_time = 0.0
    self.done = False
    self.next = None
    self.persist = {}

    @abstractmethod
    def startup(self, current_time, persist):
    '''abstract method'''

    def cleanup(self):
    self.done = False
    return self.persist

    @abstractmethod
    def update(sefl, surface, keys, current_time):
    '''abstract method'''

    class Menu(State):
    def __init__(self):
    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_NUM: 1,
    c.PLAYER_NAME: c.PLAYER_MARIO}
    self.startup(0.0, persist)

    def startup(self, current_time, persist):
    self.next = c.LOAD_SCREEN
    self.persist = persist
    self.game_info = persist
    self.overhead_info = Info(self.game_info, c.MAIN_MENU)

    self.setup_background()
    self.setup_player()
    self.setup_cursor()

    def setup_background(self):
    self.background = 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 = SCREEN.get_rect(bottom=SCREEN_RECT.bottom)
    self.image_dict = {}
    image = get_image(GFX['title_screen'], 1, 60, 176, 88,
    (255, 0, 220), c.SIZE_MULTIPLIER)
    rect = image.get_rect()
    rect.x, rect.y = (170, 100)
    self.image_dict['GAME_NAME_BOX'] = (image, rect)

    def setup_player(self):
    self.player_list = []
    player_rect_info = [(178, 32, 12, 16), (178, 128, 12, 16)]
    for rect in player_rect_info:
    image = get_image(GFX['mario_bros'],
    *rect, c.BLACK, 2.9)
    rect = image.get_rect()
    rect.x, rect.bottom = 110, c.GROUND_HEIGHT
    self.player_list.append((image, rect))
    self.player_index = 0

    def setup_cursor(self):
    self.cursor = pg.sprite.Sprite()
    self.cursor.image = get_image(GFX[c.ITEM_SHEET], 24, 160, 8, 8, c.BLACK, 3)
    rect = self.cursor.image.get_rect()
    rect.x, rect.y = (220, 358)
    self.cursor.rect = rect
    self.cursor.state = c.PLAYER1

    def update(self, surface, keys, current_time):
    self.current_time = current_time
    self.game_info[c.CURRENT_TIME] = self.current_time
    self.player_image = self.player_list[self.player_index][0]
    self.player_rect = self.player_list[self.player_index][1]
    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.player_image, self.player_rect)
    surface.blit(self.cursor.image, self.cursor.rect)
    self.overhead_info.draw(surface)

    def update_cursor(self, keys):
    if self.cursor.state == c.PLAYER1:
    self.cursor.rect.y = 358
    if keys[pg.K_DOWN]:
    self.cursor.state = c.PLAYER2
    self.player_index = 1
    self.game_info[c.PLAYER_NAME] = c.PLAYER_LUIGI
    elif self.cursor.state == c.PLAYER2:
    self.cursor.rect.y = 403
    if keys[pg.K_UP]:
    self.cursor.state = c.PLAYER1
    self.player_index = 0
    self.game_info[c.PLAYER_NAME] = c.PLAYER_MARIO
    if keys[pg.K_RETURN]:
    self.done = True

    class LoadScreen(State):
    def __init__(self):
    State.__init__(self)
    self.time_list = [2400, 2600, 2635]

    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_info_state()
    self.overhead_info = Info(self.game_info, info_state)

    def set_next_state(self):
    return c.LEVEL

    def set_info_state(self):
    return c.LOAD_SCREEN

    def update(self, surface, keys, current_time):
    if (current_time - self.start_time) < self.time_list[0]:
    surface.fill(c.BLACK)
    self.overhead_info.update(self.game_info)
    self.overhead_info.draw(surface)
    elif (current_time - self.start_time) < self.time_list[1]:
    surface.fill(c.BLACK)
    elif (current_time - self.start_time) < self.time_list[2]:
    surface.fill((106, 150, 252))
    else:
    self.done = True

    class GameOver(LoadScreen):
    def __init__(self):
    LoadScreen.__init__(self)
    self.time_list = [3000, 3200, 3235]

    def set_next_state(self):
    return c.MAIN_MENU

    def set_info_state(self):
    return c.GAME_OVER

    class TimeOut(LoadScreen):
    def __init__(self):
    LoadScreen.__init__(self)
    self.time_list = [2400, 2600, 2635]

    def set_next_state(self):
    if self.persist[c.LIVES] == 0:
    return c.GAME_OVER
    else:
    return c.LOAD_SCREEN

    def set_info_state(self):
    return c.TIME_OUT

    class Level(State):
    def __init__(self):
    State.__init__(self)

    def startup(self, current_time, persist):
    self.game_info = persist
    self.persist = self.game_info
    self.player = None
    self.overhead_info = Info(self.game_info, c.LEVEL)
    self.setup_background()

    def setup_background(self):
    self.background = GFX['level_1']
    self.bg_rect = self.background.get_rect()
    self.background = pg.transform.scale(self.background,
    (int(self.bg_rect.width*c.BACKGROUND_MULTIPLER),
    int(self.bg_rect.height*c.BACKGROUND_MULTIPLER)))
    self.bg_rect = self.background.get_rect()

    self.level = pg.Surface((self.bg_rect.w, self.bg_rect.h)).convert()
    self.viewport = SCREEN.get_rect(bottom=self.bg_rect.bottom)

    def update(self, surface, keys, current_time):
    self.game_info[c.CURRENT_TIME] = self.current_time = current_time
    self.overhead_info.update(self.game_info, self.player)
    if self.overhead_info.time <= 0:
    self.update_game_info()
    self.done = True
    self.draw(surface)

    def update_game_info(self):
    self.persist[c.LIVES] -= 1

    if self.persist[c.LIVES] == 0:
    self.next = c.GAME_OVER
    elif self.overhead_info.time == 0:
    self.next = c.TIME_OUT
    else:
    self.next = c.LOAD_SCREEN

    def draw(self, surface):
    self.level.blit(self.background, self.viewport, self.viewport)
    surface.blit(self.level, (0,0), self.viewport)
    self.overhead_info.draw(surface)

    class Character(pg.sprite.Sprite):
    def __init__(self, image):
    pg.sprite.Sprite.__init__(self)
    self.image = image
    self.rect = self.image.get_rect()

    class Info():
    def __init__(self, game_info, state):
    self.coin_total = game_info[c.COIN_TOTAL]
    self.total_lives = game_info[c.LIVES]
    self.state = state
    self.game_info = game_info

    self.create_font_image_dict()
    self.create_info_labels()
    self.create_state_labels()
    self.flashing_coin = FlashCoin(280, 53)

    def create_font_image_dict(self):
    self.image_dict = {}
    image_list = []

    image_rect_list = [# 0 - 9
    (3, 230, 7, 7), (12, 230, 7, 7), (19, 230, 7, 7),
    (27, 230, 7, 7), (35, 230, 7, 7), (43, 230, 7, 7),
    (51, 230, 7, 7), (59, 230, 7, 7), (67, 230, 7, 7),
    (75, 230, 7, 7),
    # A - Z
    (83, 230, 7, 7), (91, 230, 7, 7), (99, 230, 7, 7),
    (107, 230, 7, 7), (115, 230, 7, 7), (123, 230, 7, 7),
    (3, 238, 7, 7), (11, 238, 7, 7), (20, 238, 7, 7),
    (27, 238, 7, 7), (35, 238, 7, 7), (44, 238, 7, 7),
    (51, 238, 7, 7), (59, 238, 7, 7), (67, 238, 7, 7),
    (75, 238, 7, 7), (83, 238, 7, 7), (91, 238, 7, 7),
    (99, 238, 7, 7), (108, 238, 7, 7), (115, 238, 7, 7),
    (123, 238, 7, 7), (3, 246, 7, 7), (11, 246, 7, 7),
    (20, 246, 7, 7), (27, 246, 7, 7), (48, 246, 7, 7),
    # -*
    (68, 249, 6, 2), (75, 247, 6, 6)]

    character_string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -*'

    for character, image_rect in zip(character_string, image_rect_list):
    self.image_dict[character] = get_image(GFX['text_images'],
    *image_rect, (92, 148, 252), 2.9)

    def create_info_labels(self):
    self.score_text = []
    self.coin_count_text = []
    self.mario_label = []
    self.world_label = []
    self.time_label = []
    self.stage_label = []

    self.create_label(self.score_text, '000000', 75, 55)
    self.create_label(self.coin_count_text, '*00', 300, 55)
    self.create_label(self.mario_label, 'MARIO', 75, 30)
    self.create_label(self.world_label, 'WORLD', 450, 30)
    self.create_label(self.time_label, 'TIME', 625, 30)
    self.create_label(self.stage_label, '1-1', 472, 55)

    self.info_labels = [self.score_text, self.coin_count_text, self.mario_label,
    self.world_label, self.time_label, self.stage_label]

    def create_state_labels(self):
    if self.state == c.MAIN_MENU:
    self.create_main_menu_labels()
    elif self.state == c.LOAD_SCREEN:
    self.create_player_image()
    self.create_load_screen_labels()
    elif self.state == c.LEVEL:
    self.create_level_labels()
    elif self.state == c.GAME_OVER:
    self.create_game_over_labels()
    elif self.state == c.TIME_OUT:
    self.create_time_out_labels()

    def create_player_image(self):
    self.life_times_image = get_image(GFX['text_images'],
    75, 247, 6, 6, (92, 148, 252), 2.9)
    self.life_times_rect = self.life_times_image.get_rect(center=(378, 295))
    self.life_total_label = []
    self.create_label(self.life_total_label, str(self.total_lives), 450, 285)

    if self.game_info[c.PLAYER_NAME] == c.PLAYER_MARIO:
    rect = (178, 32, 12, 16)
    else:
    rect = (178, 128, 12, 16)
    self.player_image = get_image(GFX['mario_bros'],
    *rect, (92, 148, 252), 2.9)
    self.player_rect = self.player_image.get_rect(center=(320, 290))

    def create_main_menu_labels(self):
    mario_game = []
    luigi_game = []
    top = []
    top_score = []

    self.create_label(mario_game, c.PLAYER1, 272, 360)
    self.create_label(luigi_game, c.PLAYER2, 272, 405)
    self.create_label(top, 'TOP - ', 290, 465)
    self.create_label(top_score, '000000', 400, 465)
    self.state_labels = [mario_game, luigi_game, top, top_score,
    *self.info_labels]

    def create_load_screen_labels(self):
    world_label = []
    self.stage_label2 = []

    self.create_label(world_label, 'WORLD', 280, 200)
    self.create_label(self.stage_label2, '1-1', 430, 200)
    self.state_labels = [world_label, self.stage_label2,
    *self.info_labels, self.life_total_label]

    def create_level_labels(self):
    self.time = c.GAME_TIME_OUT
    self.current_time = 0
    self.clock_time_label = []
    self.create_label(self.clock_time_label, str(self.time), 645, 55)
    self.state_labels = [*self.info_labels, self.clock_time_label]

    def create_game_over_labels(self):
    game_label = []
    over_label = []

    self.create_label(game_label, 'GAME', 280, 300)
    self.create_label(over_label, 'OVER', 400, 300)

    self.state_labels = [game_label, over_label, *self.info_labels]

    def create_time_out_labels(self):
    timeout_label = []
    self.create_label(timeout_label, 'TIME OUT', 290, 310)
    self.state_labels = [timeout_label, *self.info_labels]

    def create_label(self, label_list, string, x, y):
    for letter in string:
    label_list.append(Character(self.image_dict[letter]))
    self.set_label_rects(label_list, x, y)

    def set_label_rects(self, label_list, x, y):
    for i, letter in enumerate(label_list):
    letter.rect.x = x + ((letter.rect.width + 3) * i)
    letter.rect.y = y
    if letter.image == self.image_dict['-']:
    letter.rect.y += 7
    letter.rect.x += 2

    def update(self, level_info, level=None):
    self.level = level
    self.handle_level_state(level_info)

    def handle_level_state(self, level_info):
    self.score = level_info[c.SCORE]
    self.update_text(self.score_text, self.score)
    self.update_text(self.coin_count_text, level_info[c.COIN_TOTAL])
    self.update_text(self.stage_label, level_info[c.LEVEL_NUM])
    self.flashing_coin.update(level_info[c.CURRENT_TIME])
    if self.state == c.LOAD_SCREEN:
    self.update_text(self.stage_label2, level_info[c.LEVEL_NUM])
    if self.state == c.LEVEL:
    if (level_info[c.CURRENT_TIME] - self.current_time) > 1000:
    self.current_time = level_info[c.CURRENT_TIME]
    self.time -= 1
    self.update_text(self.clock_time_label, self.time, True)

    def update_text(self, text, score, reset=False):
    if reset and len(text) > len(str(score)):
    text.remove(text[0])
    index = len(text) - 1
    for digit in reversed(str(score)):
    rect = text[index].rect
    text[index] = Character(self.image_dict[digit])
    text[index].rect = rect
    index -= 1

    def draw(self, surface):
    self.draw_info(surface, self.state_labels)
    if self.state == c.LOAD_SCREEN:
    surface.blit(self.player_image, self.player_rect)
    surface.blit(self.life_times_image, self.life_times_rect)
    surface.blit(self.flashing_coin.image, self.flashing_coin.rect)

    def draw_info(self, surface, label_list):
    for label in label_list:
    for letter in label:
    surface.blit(letter.image, letter.rect)


    class FlashCoin(pg.sprite.Sprite):
    def __init__(self, x, y):
    pg.sprite.Sprite.__init__(self)
    self.frame_index = 0
    self.frames = []
    self.load_frames()
    self.image = self.frames[self.frame_index]
    self.rect = self.image.get_rect()
    self.rect.x = x
    self.rect.y = y
    self.animation_timer = 0

    def load_frames(self):
    sheet = GFX[c.ITEM_SHEET]
    frame_rect_list = [(1, 160, 5, 8), (9, 160, 5, 8),
    (17, 160, 5, 8), (9, 160, 5, 8)]
    for frame_rect in frame_rect_list:
    self.frames.append(get_image(sheet, *frame_rect,
    c.BLACK, c.BRICK_SIZE_MULTIPLIER))

    def update(self, current_time):
    time_list = [375, 125, 125, 125]
    if self.animation_timer == 0:
    self.animation_timer = current_time
    elif (current_time - self.animation_timer) > time_list[self.frame_index]:
    self.frame_index += 1
    if self.frame_index == 4:
    self.frame_index = 0
    self.animation_timer = current_time

    self.image = self.frames[self.frame_index]

    class Control():
    def __init__(self):
    self.screen = pg.display.get_surface()
    self.done = False
    self.clock = pg.time.Clock()
    self.fps = 60
    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.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)

    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()
    elif event.type == pg.KEYUP:
    self.keys = pg.key.get_pressed()

    def main(self):
    while not self.done:
    self.event_loop()
    self.update()
    pg.display.update()
    self.clock.tick(self.fps)

    def get_image(sheet, x, y, width, height, colorkey, scale):
    image = pg.Surface([width, height])
    rect = image.get_rect()

    image.blit(sheet, (0, 0), (x, y, width, height))
    image.set_colorkey(colorkey)
    image = pg.transform.scale(image,
    (int(rect.width*scale),
    int(rect.height*scale)))
    return image

    def load_all_gfx(directory, colorkey=(255,0,255), accept=('.png', '.jpg', '.bmp', '.gif')):
    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

    # pygame related initial code
    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()

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

    if __name__=='__main__':
    game = Control()
    state_dict = {c.MAIN_MENU: Menu(),
    c.LOAD_SCREEN: LoadScreen(),
    c.LEVEL: Level(),
    c.GAME_OVER: GameOver(),
    c.TIME_OUT: TimeOut()}
    game.setup_states(state_dict, c.MAIN_MENU)
    game.main()

  • 相关阅读:
    Python3安装turtle提示错误:Command "python setup.py egg_info" failed with error code 1
    慕学生鲜xadmin登录不成功解决办法
    mysql删除后ID不连续解决办法
    Mac 安装gevent
    ubuntu 下 docker的简单使用
    python 字典的一些简单操作
    列表推导式
    Serializer字段和选项
    添加包解决一些导包问题
    css 文本换行,文本空白符处理相关 属性:white-space word-wrap word-break
  • 原文地址:https://www.cnblogs.com/hyhy904/p/11535780.html
Copyright © 2011-2022 走看看