Python. Фунтик ловит бабочек

Со школьниками сейчас проходим в рамках изучения python библиотеку pygame. В качестве завершающего задания необходимо сделать игру. Как образец была предложен код, генерирующий карту, перемещающий персонаж и т.д.

На основе этого сделал небольшую игру «Фунтик ловит бабочек». Скриншот приведен ниже.

Сюжет прост. В случайном месте появляется бабочка, сидит 4 секунды. За это время Фунтик должен подбежать и поймать ее. Как будут пойманы 4 бабочки, игра уходит на заставку. Главным тестером была моя семилетняя дочь, минут 20 она играла 🙂

Что сделано мной:

  • картинки,
  • сделана заставка,
  • создан объект Бабочка, реализовано его появление на 4 секунды,
  • реализован счетчик и проверка достижимости предельного значения.

Что не сделал:

  • выбор карты на заставке,
  • «мультик» в случае победы,
  • генерация части цветочков в случайном месте,
  • таблица рекордов,
  • тикающее время жизни бабочки на одном месте.

Код можно скачать по ссылке funtik.

Полный код приведен под спойлером ниже.

Код программы на Питон, 226 строк

import pygame
import os
import sys
import random
import threading

class ScreenFrame(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__()
        self.rect = (0, 0, 500, 500)


class SpriteGroup(pygame.sprite.Group):

    def __init__(self):
        super().__init__()

    def get_event(self, event):
        for sprite in self:
            sprite.get_event(event)


class Sprite(pygame.sprite.Sprite):

    def __init__(self, group):
        super().__init__(group)
        self.rect = None

    def get_event(self, event):
        pass


class Tile(Sprite):
    def __init__(self, tile_type, pos_x, pos_y):
        super().__init__(sprite_group)
        self.image = tile_images[tile_type]
        self.rect = self.image.get_rect().move(
            tile_width * pos_x, tile_height * pos_y)

class Batterfly(Sprite):
    def __init__(self):
        super().__init__(batterfly_group)
        self.image = batterfly_image
        self.pos = -1, -1
        self.kill_and_born()

    def kill_and_born(self):
        global level_map
        # Принцип рождения - через определенное количество секунд или
        # в случае столкновения у бабочки появляются новые координаты
        Ok = False
        while not Ok:
            pos_x_new, pos_y_new = random.randint(0, max_x), random.randint(0, max_y)
            if level_map[pos_y_new][pos_x_new] == '.' \
               and (pos_x_new, pos_y_new) != self.pos:
                    Ok = True
        pos_x, pos_y = pos_x_new, pos_y_new
        self.rect = self.image.get_rect().move(
            tile_width * pos_x, tile_height * pos_y)
        self.pos = (pos_x, pos_y)
        self.timer = threading.Timer(3.0, self.kill_and_born)
        self.timer.start()
        
class Player(Sprite):
    def __init__(self, pos_x, pos_y):
        super().__init__(hero_group)
        self.image = player_image
        self.rect = self.image.get_rect().move(
            tile_width * pos_x + 15, tile_height * pos_y + 5)
        self.pos = (pos_x, pos_y)

    def move(self, x, y):
        self.pos = (x, y)
        self.rect = self.image.get_rect().move(
            tile_width * self.pos[0] + 15, tile_height * self.pos[1] + 5)


def load_image(name, color_key=None):
#модуль на все случаи, но неприятности бывают
    fullname = os.path.join('data', name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error as message:
        print('Не удаётся загрузить:', name)
        raise SystemExit(message)
    image = image.convert_alpha()
    if color_key is not None:
        if color_key == -1:
            color_key = image.get_at((1, 1))            
        image.set_colorkey(color_key)
    return image


def terminate():
    pygame.quit()
    sys.exit


def start_screen():
    intro_text = ["Фунтик в лесу", 
                  "ловит бабочек,",
                  "бабочки хитры - ",
                  "долго на месте не сидят"]

    fon = pygame.transform.scale(load_image('fon.jpg'), screen_size)
    screen.blit(fon, (0, 0))
    font = pygame.font.Font(None, 30)
    text_coord = 50
    for line in intro_text:
        string_rendered = font.render(line, 1, pygame.Color('yellow'))
        intro_rect = string_rendered.get_rect()
        text_coord += 10
        intro_rect.top = text_coord
        intro_rect.x = 10
        text_coord += intro_rect.height
        screen.blit(string_rendered, intro_rect)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                terminate()
            elif event.type == pygame.KEYDOWN or \
                    event.type == pygame.MOUSEBUTTONDOWN:
                return
        pygame.display.flip()
        clock.tick(FPS)

def load_level(filename):
    filename = "data/" + filename
    with open(filename, 'r') as mapFile:
        level_map = [line.strip() for line in mapFile]
    max_width = max(map(len, level_map))
    return list(map(lambda x: list(x.ljust(max_width, '.')), level_map))


def generate_level(level):
    new_player, x, y = None, None, None
    for y in range(len(level)):
        for x in range(len(level[y])):
            if level[y][x] == '.':
                Tile('empty', x, y)
            elif level[y][x] == '#':
                Tile('wall', x, y)
            elif level[y][x] == '@':
                Tile('empty', x, y)
                new_player = Player(x, y)
                level[y][x] = "."
    return new_player, x, y


def move(hero, movement):
    x, y = hero.pos
    if movement == "up":
        if y > 0 and level_map[y - 1][x] == ".":
            hero.move(x, y - 1)
    elif movement == "down":
        if y < max_y and level_map[y + 1][x] == ".":
            #Здесь было -1, поэтому на последнюю строку не попадали
            hero.move(x, y + 1)
    elif movement == "left":
        if x > 0 and level_map[y][x - 1] == ".":
            hero.move(x - 1, y)
    elif movement == "right":
        if x < max_x and level_map[y][x + 1] == ".":
            #Здесь было -1, поэтому на последнюю строку не попадали
            hero.move(x + 1, y)


pygame.init()
screen_size = (500, 525)
screen = pygame.display.set_mode(screen_size)
FPS = 50
k = 0 # Поймано бабочек
k_max = 4 # Нужное количество бабочек

tile_images = {
    'wall': load_image('box.png'),
    'empty': load_image('grass.png'),
}
player_image = load_image('funtik1.png')
batterfly_image = load_image('butterfly.png')
tile_width = tile_height = 50
player = None
running = True
clock = pygame.time.Clock()
sprite_group = SpriteGroup()
hero_group = SpriteGroup()
batterfly_group = SpriteGroup()
start_screen()
level_map = load_level("map.map")
hero, max_x, max_y = generate_level(level_map)
batterfly = Batterfly()
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                move(hero, "up")
            elif event.key == pygame.K_DOWN:
                move(hero, "down")
            elif event.key == pygame.K_LEFT:
                move(hero, "left")
            elif event.key == pygame.K_RIGHT:
                move(hero, "right")
    screen.fill(pygame.Color("black"))
#Количество пойманных бабочек
    if hero.pos == batterfly.pos:
        k = k + 1
        batterfly.timer.cancel()
        batterfly.kill_and_born()
    if k == k_max:
        k = 0
        start_screen()
    font = pygame.font.Font(None, 40)
    text = font.render("Поймано бабочек: " + str(k), 1, (100, 255, 100))
    text_x = 250 - text.get_width() // 2
    text_y = 500
    text_w = text.get_width()
    text_h = text.get_height()
    screen.blit(text, (text_x, text_y))
#Конец вывода пойманных бабочек        
    sprite_group.draw(screen)
    hero_group.draw(screen)
    batterfly_group.draw(screen)
    clock.tick(FPS)
    pygame.display.flip()
pygame.quit()

[свернуть]

 

 

Поделиться:
  • Добавить ВКонтакте заметку об этой странице
  • Мой Мир
  • Facebook
  • Twitter
  • LiveJournal
  • FriendFeed
  • В закладки Google
  • Google Buzz
  • Яндекс.Закладки
  • StumbleUpon
  • Technorati
  • БобрДобр
  • Memori.ru
  • МоёМесто.ru

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.