Исправления:

1. Игровой процесс
+ сохраняетсяв базу данных
+ после успешного прохождения уровня всплывает окно победы, после нажатия на кнопку "следующий уровень" появляется обратный отсчёт и начинается следующий уровень, карта обновляется.
This commit is contained in:
Xatiko 2024-12-03 19:44:29 +03:00
parent 5d34162267
commit 57f7c09541
6 changed files with 2762 additions and 54 deletions

Binary file not shown.

View file

@ -325,3 +325,17 @@ def update_question(question_id, text, helpful_info):
return False, f"Ошибка при обновлении: {e}" return False, f"Ошибка при обновлении: {e}"
finally: finally:
session.close() session.close()
def update_user_level(user_id, new_level):
"""Обновляет уровень пользователя в базе данных."""
session = get_session()
try:
user = session.query(Users).filter_by(user_id=user_id).first()
if user and user.level < new_level:
user.level = new_level
session.commit()
except Exception as e:
session.rollback()
logging.error(f"Ошибка при обновлении уровня пользователя: {e}")
finally:
session.close()

View file

@ -1,31 +1,44 @@
import logging import logging
from sqlalchemy import func
from database.db_events import get_user_progress from database.db_events import get_user_progress
from database.db_session import get_session from database.db_session import get_session
from sqlalchemy.exc import SQLAlchemyError
from database.models import GameSession from database.models import GameSession
def save_game_session(user_id, level, score, steps, duration=0, health=100, hunger=0, sleepiness=0): def save_game_session(user_id, level, score, duration, steps, health, hunger, sleepiness):
"""Сохранение игрового прогресса.""" """Сохранение игрового прогресса с обновлением существующей записи."""
session = get_session() session = get_session() # Получаем сессию для работы с базой данных
try: try:
session.add(GameSession( # Проверяем, существует ли уже запись для данного пользователя и уровня
existing_session = session.query(GameSession).filter_by(user_id=user_id, level=level).first()
if existing_session:
logging.info(f"Обновление прогресса для user_id={user_id}, level={level}.")
existing_session.score = score
existing_session.duration = duration
existing_session.steps = steps
existing_session.health = health
existing_session.hunger = hunger
existing_session.sleepiness = sleepiness
else:
# Если записи нет, создаем новую
new_session = GameSession(
user_id=user_id, user_id=user_id,
level=level, level=level,
score=score, score=score,
steps=steps,
duration=duration, duration=duration,
steps=steps,
health=health, health=health,
hunger=hunger, hunger=hunger,
sleepiness=sleepiness sleepiness=sleepiness
)) )
session.commit() session.add(new_session) # Добавляем в сессию
logging.info(f"Сессия сохранена: user_id={user_id}, level={level}, score={score}") session.commit() # Сохраняем изменения в базе данных
logging.info(f"Прогресс успешно сохранён: user_id={user_id}, level={level}, score={score}")
except Exception as e: except Exception as e:
session.rollback() session.rollback() # Откатываем изменения в случае ошибки
logging.error(f"Ошибка при сохранении игровой сессии: {e}") logging.error(f"Ошибка при сохранении прогресса: {e}")
raise finally:
session.close() # Закрываем сессию
def print_user_progress(user_id): def print_user_progress(user_id):

View file

@ -68,6 +68,7 @@ class GameSession(Base):
level = Column(Integer, nullable=False) level = Column(Integer, nullable=False)
score = Column(Integer, default=0) score = Column(Integer, default=0)
duration = Column(Integer) # Время игры в секундах duration = Column(Integer) # Время игры в секундах
steps = Column(Integer, default=0) # Количество шагов
start_time = Column(DateTime, default=func.now()) start_time = Column(DateTime, default=func.now())
end_time = Column(DateTime, nullable=True) end_time = Column(DateTime, nullable=True)
health = Column(Integer, default=100) # Здоровье health = Column(Integer, default=100) # Здоровье

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@ from tkinter import messagebox
from PIL import Image, ImageTk from PIL import Image, ImageTk
import random import random
import logging import logging
from database.db_events import get_user_by_id, get_user_progress, save_progress from database.db_events import get_user_by_id, get_user_progress, save_progress, update_user_level
from database.info.GameSessions_table import save_game_session from database.info.GameSessions_table import save_game_session
from src.user_functions.game_logs import setup_logging from src.user_functions.game_logs import setup_logging
from config import DOG_CHARACTERS, DONE, BONE, BACKGROUND_GAME from config import DOG_CHARACTERS, DONE, BONE, BACKGROUND_GAME
@ -150,6 +150,7 @@ class GameUI:
level_frame = tk.Frame(self.root, bg="#E5E5E5") level_frame = tk.Frame(self.root, bg="#E5E5E5")
level_frame.place(relx=0.5, rely=0.5, anchor=tk.CENTER) level_frame.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
# Получаем обновлённый прогресс пользователя
progress = get_user_progress(self.user_id) progress = get_user_progress(self.user_id)
completed_levels = {session.level for session in progress if session.score > 0} completed_levels = {session.level for session in progress if session.score > 0}
self.max_unlocked_level = max(completed_levels) if completed_levels else 1 self.max_unlocked_level = max(completed_levels) if completed_levels else 1
@ -183,14 +184,18 @@ class GameUI:
def handle_level_selection(self, level): def handle_level_selection(self, level):
"""Обработка выбора уровня.""" """Обработка выбора уровня."""
if level in self.completed_levels: if level in self.completed_levels:
# Если уровень завершён, предложить пройти заново
if messagebox.askyesno("Повторить уровень", f"Вы уже прошли уровень {level}. Хотите пройти его заново?"): if messagebox.askyesno("Повторить уровень", f"Вы уже прошли уровень {level}. Хотите пройти его заново?"):
self.current_level = level self.current_level = level
self.total_bones = 0 self.total_bones = 0 # Сбрасываем косточки
self.steps_taken = 0 self.steps_taken = 0 # Сбрасываем количество шагов
self.start_game() self.dog_position = [1, 1] # Сбрасываем позицию собаки
self.bones_positions = self.generate_bones() # Генерация новых косточек
self.start_game() # Запуск уровня заново
elif level <= self.max_unlocked_level: elif level <= self.max_unlocked_level:
# Запуск уровня, если он доступен
self.current_level = level self.current_level = level
self.countdown() self.countdown() # Обратный отсчёт перед началом уровня
else: else:
messagebox.showinfo("Недоступно", "Пройдите предыдущие уровни, чтобы разблокировать этот.") messagebox.showinfo("Недоступно", "Пройдите предыдущие уровни, чтобы разблокировать этот.")
@ -276,18 +281,28 @@ class GameUI:
self.bones_positions.remove(bone) self.bones_positions.remove(bone)
self.total_bones += 1 self.total_bones += 1
# Сохранение прогресса # Сохраняем прогресс
save_progress(self.user_id, self.current_level, self.total_bones, self.steps_taken, 100, 0, 0) save_game_session(
user_id=self.user_id,
level=self.current_level,
score=self.total_bones,
duration=self.steps_taken, # Количество шагов как продолжительность
steps=self.steps_taken, # Сохраняем количество шагов
health=100,
hunger=0,
sleepiness=0
)
self.bones_label.config(text=f"{self.total_bones}") self.bones_label.config(text=f"{self.total_bones}")
# Условие для победы # Проверка на завершение уровня
target_bones = 10 * (2 ** (self.current_level - 1)) # Модифицируем целевое количество косточек target_bones = 10 * (2 ** (self.current_level - 1))
if self.total_bones >= target_bones and not self.is_victory_screen_open: if self.total_bones >= target_bones and not self.is_victory_screen_open:
self.show_victory_screen() # Показываем экран победы self.show_victory_screen()
# Генерация дополнительных косточек, если нужно
if self.steps_taken % 10 == 0 and len(self.bones_positions) < self.max_bones_per_level: if self.steps_taken % 10 == 0 and len(self.bones_positions) < self.max_bones_per_level:
self.bones_positions.extend(self.generate_bones()) # Генерация новых косточек, если нужно self.bones_positions.extend(self.generate_bones())
def move_up(self, event): def move_up(self, event):
"""Движение вверх.""" """Движение вверх."""
@ -422,12 +437,37 @@ class GameUI:
self.is_victory_screen_open = True self.is_victory_screen_open = True
self.is_game_active = False self.is_game_active = False
# Сохраняем прогресс текущего уровня
save_game_session(
user_id=self.user_id,
level=self.current_level,
score=self.total_bones,
duration=self.steps_taken,
steps=self.steps_taken,
health=100,
hunger=0,
sleepiness=0
)
# Обновляем данные о разблокированном уровне
next_level = self.current_level + 1
update_user_level(self.user_id, next_level)
self.max_unlocked_level = max(self.max_unlocked_level, next_level)
# Открываем окно победы
victory_window = tk.Toplevel(self.root) victory_window = tk.Toplevel(self.root)
victory_window.title("Ура, победа!") victory_window.title("Уровень завершён!")
victory_window.geometry("800x600") victory_window.geometry("800x600")
victory_window.configure(bg="#E5E5E5") victory_window.configure(bg="#E5E5E5")
victory_window.grab_set() victory_window.grab_set()
tk.Label(
victory_window,
text=f"Поздравляем! Уровень {self.current_level} завершён!",
font=("Comic Sans MS", 24),
bg="#E5E5E5"
).pack(pady=20)
# Изображение собаки # Изображение собаки
dog_image = Image.open(DOG_CHARACTERS[self.selected_dog]["image"]).resize((200, 200), Image.Resampling.LANCZOS) dog_image = Image.open(DOG_CHARACTERS[self.selected_dog]["image"]).resize((200, 200), Image.Resampling.LANCZOS)
dog_photo = ImageTk.PhotoImage(dog_image) dog_photo = ImageTk.PhotoImage(dog_image)
@ -464,7 +504,7 @@ class GameUI:
bg="#4CAF50", bg="#4CAF50",
command=lambda: [victory_window.destroy(), self.start_next_level()] command=lambda: [victory_window.destroy(), self.start_next_level()]
) )
next_level_button.place(relx=0.5, rely=0.65, anchor=tk.CENTER) next_level_button.place(relx=0.5, rely=0.7, anchor=tk.CENTER)
# Кнопка выхода в главное меню # Кнопка выхода в главное меню
exit_button = tk.Button( exit_button = tk.Button(
@ -492,28 +532,27 @@ class GameUI:
self.show_main_menu() # Переходим в главное меню self.show_main_menu() # Переходим в главное меню
def start_next_level(self): def start_next_level(self):
"""Переход на следующий уровень.""" """Запуск следующего уровня."""
try: self.current_level += 1 # Переход на следующий уровень
# Сохранение текущего прогресса self.total_bones = 0 # Сброс собранных косточек
self.save_progress() self.steps_taken = 0 # Сброс количества шагов
self.dog_position = [1, 1] # Возвращаем собаку в начальную позицию
self.bones_positions = [] # Очищаем косточки
self.is_victory_screen_open = False # Закрываем экран победы, если он был открыт
# Переход на следующий уровень # Сохраняем новый прогресс в базу данных
self.current_level += 1 save_game_session(
self.max_unlocked_level = max(self.max_unlocked_level, self.current_level) user_id=self.user_id,
level=self.current_level,
# Сброс состояния игры: собака возвращается в начальную позицию score=0,
self.total_bones = 0 duration=0,
self.steps_taken = 0 steps=0,
self.dog_position = [1, 1] # Начальная позиция собаки health=100,
self.bones_positions = [] # Очищаем текущие косточки hunger=0,
sleepiness=0
# Генерация новых косточек с увеличением их количества по геометрической прогрессии )
self.bones_positions = self.generate_bones() logging.info(f"Запуск уровня {self.current_level}.")
self.countdown() # Запускаем обратный отсчёт перед началом уровня
# Начинаем новый уровень с обратным отсчётом
self.countdown() # Запуск обратного отсчёта
except Exception as e:
logging.error(f"Ошибка при переходе на следующий уровень: {e}")
def save_progress(self): def save_progress(self):
"""Сохранение игрового процесса в таблицу GameSessions.""" """Сохранение игрового процесса в таблицу GameSessions."""