Загрузка данных


import pgzrun
import random
import pygame
from pgzhelper import load_sound, play_music, audio_status

WIDTH = 450
HEIGHT = 800
TITLE = "Мой огород"


music_started = False

# Каждый эффект — отдельная переменная.
# Пути строит pgzhelper относительно СВОЕГО файла, который лежит в папке проекта.
plant_sound = load_sound("plant.wav", 1.0)
water_sound = load_sound("water.wav", 1.0)
harvest_sound = load_sound("harvest.wav", 1.0)


def start_music():
    # OGG надёжнее MP3 для pygame/pygame-zero.
    play_music("background.ogg", volume=1.0, loops=-1)

# ---------------------------------------------------------
# ОСНОВНЫЕ ПАНЕЛИ
# ---------------------------------------------------------

background = Actor("background")
background.topleft = (0, 0)

top_panel = Actor("top_panel")
top_panel.center = (218, 40)

settings_button = Actor("settings_new")
settings_button.center = (426, 37)

bottom_panel = Actor("bottom_panel")
bottom_panel.center = (225, 743)


# ---------------------------------------------------------
# РЕСУРСЫ
# ---------------------------------------------------------

resource_x = [72, 225, 378]
resource_panels = []

for x in resource_x:
    panel = Actor("resource_panel_new")
    panel.center = (x, 96)
    resource_panels.append(panel)

coin_icon = Actor("coin_new")
coin_icon.center = (resource_x[0] - 49, 96)

water_icon = Actor("water_new")
water_icon.center = (resource_x[1] - 49, 96)

sun_icon = Actor("sun_new")
sun_icon.center = (resource_x[2] - 49, 96)

level_panel = Actor("level_panel_new")
level_panel.center = (225, 132)


# ---------------------------------------------------------
# ЗАДАНИЯ
# ---------------------------------------------------------

tasks_title = Actor("tasks_title_new")
tasks_title.center = (82, 157)

tasks_panel = Actor("tasks_panel_new")
tasks_panel.center = (82, 248)

task_plant_icon = Actor("task_plant")
task_plant_icon.center = (48, 201)

task_harvest_icon = Actor("task_basket")
task_harvest_icon.center = (48, 276)

plant_progress_bg = Actor("progress_bg_new")
plant_progress_bg.center = (82, 228)

harvest_progress_bg = Actor("progress_bg_new")
harvest_progress_bg.center = (82, 303)

plant_progress_fill = Actor("progress_fill_25")
harvest_progress_fill = Actor("progress_fill_25")

progress_width = {
    25: 27,
    50: 54,
    75: 81,
    100: 108
}


# ---------------------------------------------------------
# ШЕСТЬ ГРЯДОК
# ---------------------------------------------------------

bed_positions = [
    (82, 392),
    (225, 392),
    (368, 392),
    (82, 512),
    (225, 512),
    (368, 512)
]

beds = []
plants = []
ready_effects = []
empty_marks = []

for position in bed_positions:
    bed = Actor("bed_empty")
    bed.center = position
    beds.append(bed)

    plants.append(None)

    effect = Actor("ready_effect_new")
    effect.center = (position[0] + 38, position[1] - 42)
    ready_effects.append(effect)

    mark = Actor("plus_bed_new")
    mark.center = (position[0], position[1] - 5)
    empty_marks.append(mark)

plant_name = ["", "", "", "", "", ""]
plant_stage = [0, 0, 0, 0, 0, 0]
plant_time = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
plant_watered = [False, False, False, False, False, False]
plant_ready = [False, False, False, False, False, False]


# ---------------------------------------------------------
# СООБЩЕНИЕ И БОЛЬШАЯ КНОПКА СБОРА
# ---------------------------------------------------------

message_panel = Actor("message_panel_new")
message_panel.center = (145, 660)

harvest_big = Actor("harvest_big_new")
harvest_big.center = (365, 660)

message_line1 = ""
message_line2 = ""
message_time = 0.0


# ---------------------------------------------------------
# НИЖНЕЕ МЕНЮ
# ---------------------------------------------------------

button_x = [45, 135, 225, 315, 405]
button_y = 758

button_water = Actor("button_water")
button_water.center = (button_x[0], button_y)

button_seeds = Actor("button_seeds")
button_seeds.center = (button_x[1], button_y)

button_shovel = Actor("button_shovel")
button_shovel.center = (button_x[2], button_y)

button_harvest = Actor("button_harvest")
button_harvest.center = (button_x[3], button_y)

button_shop = Actor("button_shop")
button_shop.center = (button_x[4], button_y)

menu_buttons = [
    button_water,
    button_seeds,
    button_shovel,
    button_harvest,
    button_shop
]

selected_marker = Actor("selected_new")
selected_check = Actor("check_new")
selected_check.center = (0, 0)


# ---------------------------------------------------------
# МАГАЗИН И ОКНА
# ---------------------------------------------------------

overlay_panel = Actor("overlay_panel")
overlay_panel.center = (225, 400)

close_button = Actor("check_new")
close_button.center = (385, 154)

shop_y = [220, 292, 364, 436, 508, 580]
shop_rows = []

for y in shop_y:
    row = Actor("shop_item")
    row.center = (225, y)
    shop_rows.append(row)

shop_icons = [
    Actor("shop_carrot"),
    Actor("shop_potato"),
    Actor("shop_tomato"),
    Actor("shop_cucumber"),
    Actor("shop_water_icon"),
    Actor("shop_sun_icon")
]

for icon, y in zip(shop_icons, shop_y):
    icon.center = (105, y)

pause_continue = Actor("shop_item")
pause_continue.center = (225, 360)

pause_restart = Actor("shop_item")
pause_restart.center = (225, 450)

win_restart = Actor("shop_item")
win_restart.center = (225, 500)


# ---------------------------------------------------------
# ИГРОВЫЕ ДАННЫЕ
# ---------------------------------------------------------

mode = "game"
tool = "seeds"

coins = 250
water = 25
sun = 12

level = 1
plant_progress = 0
harvest_progress = 0

level_plant_goal = [3, 4, 5, 6, 8]
level_harvest_goal = [3, 4, 5, 6, 8]

crop_order = ["carrot", "potato", "tomato", "cucumber"]
selected_crop = "carrot"
unlocked_crops = ["carrot"]

seed_count = {
    "carrot": 8,
    "potato": 0,
    "tomato": 0,
    "cucumber": 0
}

crop_title = {
    "carrot": "МОРКОВЬ",
    "potato": "КАРТОФЕЛЬ",
    "tomato": "ПОМИДОР",
    "cucumber": "ОГУРЕЦ"
}

crop_reward = {
    "carrot": 10,
    "potato": 15,
    "tomato": 20,
    "cucumber": 25
}

shop_price = {
    "carrot": 15,
    "potato": 25,
    "tomato": 35,
    "cucumber": 45,
    "water": 20,
    "sun": 25
}

shop_names = [
    "Семена моркови +5",
    "Семена картофеля +5",
    "Семена помидоров +5",
    "Семена огурцов +5",
    "Вода +10",
    "Солнце +5"
]

shop_items = ["carrot", "potato", "tomato", "cucumber", "water", "sun"]

pressed_button = ""
pressed_time = 0.0
coin_effects = []


# ---------------------------------------------------------
# СООБЩЕНИЯ
# ---------------------------------------------------------

def split_message(text):
    words = str(text).split()
    line1 = ""
    line2 = ""

    for word in words:
        test = word if line1 == "" else line1 + " " + word

        if len(test) <= 28 or line1 == "":
            line1 = test
        else:
            line2 = word if line2 == "" else line2 + " " + word

    return line1, line2


def set_message(line1, line2=""):
    global message_line1
    global message_line2
    global message_time

    if line2 == "":
        message_line1, message_line2 = split_message(line1)
    else:
        message_line1 = str(line1)
        message_line2 = str(line2)

    message_time = 3.5


def press_button(name):
    global pressed_button
    global pressed_time

    pressed_button = name
    pressed_time = 0.15


def add_coin_effect(index, amount):
    x = bed_positions[index][0] + random.randint(-8, 8)
    y = bed_positions[index][1] - 45
    coin_effects.append([x, y, "+" + str(amount), 1.2])


# ---------------------------------------------------------
# РАСТЕНИЯ
# ---------------------------------------------------------

def create_plant(index):
    image_name = plant_name[index] + "_" + str(plant_stage[index])

    if plants[index] is None:
        plants[index] = Actor(image_name)
    else:
        plants[index].image = image_name

    plants[index].center = (
        bed_positions[index][0],
        bed_positions[index][1] - 14
    )


def reset_bed(index):
    plant_name[index] = ""
    plant_stage[index] = 0
    plant_time[index] = 0.0
    plant_watered[index] = False
    plant_ready[index] = False
    plants[index] = None
    beds[index].image = "bed_empty"


def plant_seed(index):
    global sun
    global plant_progress

    if index < 0 or index >= len(beds):
        return False

    if plant_stage[index] != 0:
        set_message("Эта грядка уже занята")
        return False

    if selected_crop not in unlocked_crops:
        set_message("Эта культура ещё закрыта")
        return False

    if seed_count[selected_crop] <= 0:
        set_message("Семена закончились", "Откройте магазин")
        return False

    if sun <= 0:
        set_message("Недостаточно солнца")
        return False

    seed_count[selected_crop] -= 1
    sun -= 1

    plant_name[index] = selected_crop
    plant_stage[index] = 1
    plant_time[index] = 0.0
    plant_watered[index] = False
    plant_ready[index] = False
    beds[index].image = "bed_empty"
    create_plant(index)

    plant_progress += 1
    set_message("Посажено: " + crop_title[selected_crop])
    check_level()
    return True


def water_bed(index):
    global water

    if index < 0 or index >= len(beds):
        return False

    if plant_stage[index] == 0:
        set_message("Сначала посадите растение")
        return False

    if plant_ready[index]:
        set_message("Урожай уже созрел")
        return False

    if plant_watered[index]:
        set_message("Эта грядка уже полита")
        return False

    if water <= 0:
        set_message("Вода закончилась")
        return False

    water -= 1
    plant_watered[index] = True
    beds[index].image = "bed_watered"
    set_message("Грядка полита", "Рост ускорен")
    return True


def clear_bed(index):
    if index < 0 or index >= len(beds):
        return False

    if plant_stage[index] == 0:
        set_message("Грядка уже пустая")
        return False

    reset_bed(index)
    set_message("Грядка очищена")
    return True


def harvest_bed(index):
    global coins
    global harvest_progress

    if index < 0 or index >= len(beds):
        return False

    if not plant_ready[index]:
        set_message("Урожай ещё не созрел")
        return False

    crop = plant_name[index]
    reward = crop_reward[crop]
    coins += reward
    harvest_progress += 1
    add_coin_effect(index, reward)
    reset_bed(index)
    set_message("Урожай собран", "+" + str(reward) + " монет")
    check_level()
    return True


def harvest_all():
    count = 0

    for index in range(len(beds)):
        if plant_ready[index]:
            if harvest_bed(index):
                count += 1

    if count == 0:
        set_message("Готового урожая пока нет")
    else:
        set_message("Собрано грядок: " + str(count))

    return count


# ---------------------------------------------------------
# УРОВНИ И КУЛЬТУРЫ
# ---------------------------------------------------------

def current_plant_goal():
    return level_plant_goal[level - 1]


def current_harvest_goal():
    return level_harvest_goal[level - 1]


def unlock_crop(name):
    global selected_crop

    if name not in unlocked_crops:
        unlocked_crops.append(name)
        seed_count[name] += 4
        selected_crop = name


def check_level():
    global level
    global plant_progress
    global harvest_progress
    global water
    global sun
    global mode

    if plant_progress < current_plant_goal():
        return False

    if harvest_progress < current_harvest_goal():
        return False

    if level == 5:
        mode = "win"
        set_message("Все уровни пройдены!")
        return True

    level += 1
    plant_progress = 0
    harvest_progress = 0
    water += 5
    sun += 3

    if level == 2:
        unlock_crop("potato")
    elif level == 3:
        unlock_crop("tomato")
    elif level == 4:
        unlock_crop("cucumber")

    set_message("Открыт уровень " + str(level), "Новая культура доступна")
    return True


def cycle_crop():
    global selected_crop

    available = []

    for name in crop_order:
        if name in unlocked_crops:
            available.append(name)

    if selected_crop not in available:
        selected_crop = available[0]
    else:
        index = available.index(selected_crop)
        index = (index + 1) % len(available)
        selected_crop = available[index]

    set_message("Выбрано: " + crop_title[selected_crop],
                "Семян: " + str(seed_count[selected_crop]))


# ---------------------------------------------------------
# МАГАЗИН
# ---------------------------------------------------------

def buy_item(item):
    global coins
    global water
    global sun

    if item not in shop_price:
        return False

    if item in crop_order and item not in unlocked_crops:
        set_message("Культура откроется позже")
        return False

    price = shop_price[item]

    if coins < price:
        set_message("Недостаточно монет")
        return False

    coins -= price

    if item == "water":
        water += 10
        set_message("Куплено воды: +10")
    elif item == "sun":
        sun += 5
        set_message("Куплено солнца: +5")
    else:
        seed_count[item] += 5
        set_message("Куплено 5 семян", crop_title[item])

    return True


# ---------------------------------------------------------
# НОВАЯ ИГРА
# ---------------------------------------------------------

def new_game():
    global mode
    global tool
    global coins
    global water
    global sun
    global level
    global plant_progress
    global harvest_progress
    global selected_crop
    global unlocked_crops
    global message_line1
    global message_line2
    global message_time
    global coin_effects

    mode = "game"
    tool = "seeds"

    coins = 250
    water = 25
    sun = 12

    level = 1
    plant_progress = 0
    harvest_progress = 0

    selected_crop = "carrot"
    unlocked_crops = ["carrot"]

    seed_count["carrot"] = 8
    seed_count["potato"] = 0
    seed_count["tomato"] = 0
    seed_count["cucumber"] = 0

    for index in range(len(beds)):
        reset_bed(index)

    coin_effects = []
    message_line1 = "Выберите СЕМЕНА"
    message_line2 = "и нажмите на грядку"
    message_time = 5.0


# ---------------------------------------------------------
# ОТРИСОВКА ПРОГРЕССА
# ---------------------------------------------------------

def progress_percent(value, goal):
    if goal <= 0 or value <= 0:
        return 0

    percent = value * 100 / goal

    if percent <= 25:
        return 25
    if percent <= 50:
        return 50
    if percent <= 75:
        return 75
    return 100


def draw_progress(fill_actor, center_x, center_y, value, goal):
    percent = progress_percent(value, goal)

    if percent == 0:
        return

    fill_actor.image = "progress_fill_" + str(percent)
    width = progress_width[percent]
    left = center_x - 54
    fill_actor.center = (left + width / 2, center_y)
    fill_actor.draw()


# ---------------------------------------------------------
# ОТРИСОВКА ЭКРАНА ИГРЫ
# ---------------------------------------------------------

def draw_resources():
    for panel in resource_panels:
        panel.draw()

    coin_icon.draw()
    water_icon.draw()
    sun_icon.draw()

    screen.draw.text(str(coins), center=(resource_x[0] + 8, 96),
                     fontsize=19, color="#6b3b14", shadow=(1, 1),
                     scolor="#fff4ce")
    screen.draw.text(str(water), center=(resource_x[1] + 8, 96),
                     fontsize=19, color="#16548d", shadow=(1, 1),
                     scolor="#ffffff")
    screen.draw.text(str(sun), center=(resource_x[2] + 8, 96),
                     fontsize=19, color="#9a5a00", shadow=(1, 1),
                     scolor="#fff9c2")


def draw_tasks():
    tasks_panel.draw()
    tasks_title.draw()
    task_plant_icon.draw()
    task_harvest_icon.draw()

    screen.draw.text("Посадить", center=(100, 196), fontsize=14,
                     color="#5b3518")
    screen.draw.text("Собрать", center=(100, 271), fontsize=14,
                     color="#5b3518")

    plant_progress_bg.draw()
    harvest_progress_bg.draw()

    draw_progress(plant_progress_fill, 82, 228,
                  plant_progress, current_plant_goal())
    draw_progress(harvest_progress_fill, 82, 303,
                  harvest_progress, current_harvest_goal())

    screen.draw.text(str(plant_progress) + "/" + str(current_plant_goal()),
                     center=(82, 228), fontsize=12, color="white",
                     shadow=(1, 1), scolor="#356020")
    screen.draw.text(str(harvest_progress) + "/" + str(current_harvest_goal()),
                     center=(82, 303), fontsize=12, color="white",
                     shadow=(1, 1), scolor="#356020")


def draw_beds():
    for index in range(len(beds)):
        beds[index].draw()

        if plants[index] is not None:
            plants[index].draw()
        else:
            empty_marks[index].draw()

        if plant_ready[index]:
            ready_effects[index].draw()


def draw_message():
    message_panel.draw()

    screen.draw.text(message_line1, center=(145, 653), fontsize=15,
                     color="#5b3518")

    if message_line2 != "":
        screen.draw.text(message_line2, center=(145, 672), fontsize=14,
                         color="#5b3518")


def selected_button_index():
    if tool == "water":
        return 0
    if tool == "seeds":
        return 1
    if tool == "shovel":
        return 2
    if tool == "harvest":
        return 3
    return -1


def draw_bottom_menu():
    bottom_panel.draw()

    index = selected_button_index()

    if index >= 0:
        selected_marker.center = (button_x[index], button_y + 2)
        selected_marker.draw()

    for button in menu_buttons:
        button.draw()

    if index >= 0:
        selected_check.center = (button_x[index] + 27, button_y - 23)
        selected_check.draw()


def draw_coin_effects():
    for effect in coin_effects:
        screen.draw.text(effect[2], center=(effect[0], effect[1]),
                         fontsize=20, color="#ffe34f", shadow=(1, 1),
                         scolor="#8a4b00")


def draw_game():
    background.draw()
    top_panel.draw()
    settings_button.draw()
    draw_resources()

    level_panel.draw()
    screen.draw.text("УРОВЕНЬ " + str(level), center=(225, 132),
                     fontsize=16, color="white", shadow=(1, 1),
                     scolor="#6b3512")

    draw_tasks()
    draw_beds()
    draw_message()
    harvest_big.draw()
    draw_bottom_menu()
    draw_coin_effects()


# ---------------------------------------------------------
# МАГАЗИН, ПАУЗА, ПОБЕДА
# ---------------------------------------------------------

def draw_shop():
    draw_game()
    overlay_panel.draw()
    close_button.draw()

    screen.draw.text("МАГАЗИН", center=(225, 164), fontsize=30,
                     color="#6b3512")

    for index in range(len(shop_rows)):
        shop_rows[index].draw()
        shop_icons[index].draw()

        item = shop_items[index]
        locked = item in crop_order and item not in unlocked_crops
        title = shop_names[index]

        if locked:
            title = "ЗАКРЫТО ДО УРОВНЯ " + str(crop_order.index(item) + 1)

        screen.draw.text(title, midleft=(138, shop_y[index] - 10),
                         fontsize=15, color="#5b3518")

        if not locked:
            screen.draw.text(str(shop_price[item]) + " монет",
                             midleft=(138, shop_y[index] + 13),
                             fontsize=14, color="#a05a00")


def draw_pause():
    draw_game()
    overlay_panel.draw()
    close_button.draw()
    screen.draw.text("ПАУЗА", center=(225, 225), fontsize=42,
                     color="#6b3512")

    pause_continue.draw()
    pause_restart.draw()

    screen.draw.text("ПРОДОЛЖИТЬ", center=pause_continue.center,
                     fontsize=24, color="#5b3518")
    screen.draw.text("НОВАЯ ИГРА", center=pause_restart.center,
                     fontsize=24, color="#5b3518")


def draw_win():
    background.draw()
    overlay_panel.draw()
    screen.draw.text("ПОБЕДА!", center=(225, 250), fontsize=48,
                     color="#4f9b22", shadow=(2, 2), scolor="#ffffff")
    screen.draw.text("Все 5 уровней пройдены", center=(225, 320),
                     fontsize=22, color="#5b3518")
    screen.draw.text("Монеты: " + str(coins), center=(225, 360),
                     fontsize=22, color="#9a5a00")

    win_restart.draw()
    screen.draw.text("ИГРАТЬ СНОВА", center=win_restart.center,
                     fontsize=23, color="#5b3518")


def draw():
    if mode == "game":
        draw_game()
    elif mode == "shop":
        draw_shop()
    elif mode == "pause":
        draw_pause()
    elif mode == "win":
        draw_win()


# ---------------------------------------------------------
# ОБНОВЛЕНИЕ
# ---------------------------------------------------------

def update(dt):
    global message_time
    global pressed_time
    global music_started

    # update() вызывается уже после запуска pgzrun.go(),
    # поэтому здесь аудиосистема Pygame Zero уже готова.
    if not music_started:
        start_music()
        music_started = True

    if mode == "game":
        for index in range(len(beds)):
            if plant_stage[index] > 0 and not plant_ready[index]:
                speed = 2.0 if plant_watered[index] else 1.0
                plant_time[index] += dt * speed

                if plant_time[index] >= 8.0:
                    plant_stage[index] = 3
                    plant_ready[index] = True
                    beds[index].image = "bed_ready"
                    create_plant(index)

                elif plant_time[index] >= 4.0 and plant_stage[index] == 1:
                    plant_stage[index] = 2
                    create_plant(index)

    if message_time > 0:
        message_time -= dt

    if pressed_time > 0:
        pressed_time -= dt

    for effect in coin_effects[:]:
        effect[1] -= 22 * dt
        effect[3] -= dt

        if effect[3] <= 0:
            coin_effects.remove(effect)


# ---------------------------------------------------------
# МЫШЬ
# ---------------------------------------------------------

def choose_tool(name):
    global tool

    tool = name
    press_button(name)

    if name == "water":
        set_message("Выбрана лейка", "Нажмите на растение")
    elif name == "seeds":
        set_message("Выбрано: " + crop_title[selected_crop],
                    "Семян: " + str(seed_count[selected_crop]))
    elif name == "shovel":
        set_message("Выбрана лопата", "Нажмите на грядку")
    elif name == "harvest":
        set_message("Выбран урожай", "Нажмите на готовую грядку")


def on_mouse_down(pos):
    global mode

    if mode == "game":
        if settings_button.collidepoint(pos):
            mode = "pause"
            return

        if button_water.collidepoint(pos):
            choose_tool("water")
            return

        if button_seeds.collidepoint(pos):
            if tool == "seeds":
                cycle_crop()
            else:
                choose_tool("seeds")
            return

        if button_shovel.collidepoint(pos):
            choose_tool("shovel")
            return

        if button_harvest.collidepoint(pos):
            choose_tool("harvest")
            harvest_sound.play()
            return

        if button_shop.collidepoint(pos):
            mode = "shop"
            return

        if harvest_big.collidepoint(pos):
            count = harvest_all()
            if count > 0:
                harvest_sound.play()
            press_button("harvest_all")
            return

        for panel in resource_panels:
            if panel.collidepoint(pos):
                mode = "shop"
                return

        for index in range(len(beds)):
            if beds[index].collidepoint(pos):
                if tool == "seeds":
                    if plant_seed(index):
                        plant_sound.play()
                elif tool == "water":
                    if water_bed(index):
                    
                        sounds.water.play()
                elif tool == "shovel":
                    clear_bed(index)
                elif tool == "harvest":
                    if harvest_bed(index):
                        harvest_sound.play()
                return

    elif mode == "shop":
        if close_button.collidepoint(pos):
            mode = "game"
            return

        for index in range(len(shop_rows)):
            if shop_rows[index].collidepoint(pos):
                buy_item(shop_items[index])
                return

    elif mode == "pause":
        if close_button.collidepoint(pos) or pause_continue.collidepoint(pos):
            mode = "game"
            return

        if pause_restart.collidepoint(pos):
            new_game()
            return

    elif mode == "win":
        if win_restart.collidepoint(pos):
            new_game()

new_game()
pgzrun.go()