/
pentomas
/
volley
Обзор
Документация
Войти
/
pentomas
/
volley
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
view.py
154 строки
6 KB
pentomas
create: IMG_1551.PNG, мяч.png, controller.py, main.py, model.py, player.py, view.py
08 май 2026, 06:57
Верифицирован
08 май 2026, 06:57
9c0e4d3
Код
Авторство
О чём код?
import os import pygame from constants import BALL_RADIUS, COURT_LEFT, COURT_RIGHT, FLOOR_Y, HEIGHT, NET_HEIGHT, NET_WIDTH, NET_X, WIDTH class VolleyballView: def __init__(self, screen): self.screen = screen self.font = pygame.font.SysFont(None, 48) self.small_font = pygame.font.SysFont(None, 28) self.background_image = self._load_image( ("background.png", "background.jpg", "background.jpeg", "background.webp", "IMG_1551.PNG") ) self.ball_image = self._load_image(("ball.png", "ball.jpg", "ball.jpeg", "ball.webp", "мяч.png")) if self.background_image is not None: self.background_image = pygame.transform.smoothscale(self.background_image, (WIDTH, HEIGHT)) if self.ball_image is not None: ball_size = BALL_RADIUS * 2 self.ball_image = pygame.transform.smoothscale(self.ball_image, (ball_size, ball_size)) def render(self, model): if self.background_image is None: self.screen.fill((30, 80, 40)) else: self.screen.blit(self.background_image, (0, 0)) pygame.draw.line(self.screen, (255, 255, 255), (COURT_LEFT, FLOOR_Y), (COURT_RIGHT, FLOOR_Y), 3) pygame.draw.line(self.screen, (255, 255, 255), (COURT_LEFT, FLOOR_Y - 8), (COURT_LEFT, FLOOR_Y + 8), 3) pygame.draw.line(self.screen, (255, 255, 255), (COURT_RIGHT, FLOOR_Y - 8), (COURT_RIGHT, FLOOR_Y + 8), 3) pygame.draw.rect( self.screen, (200, 200, 200), (NET_X - NET_WIDTH / 2, FLOOR_Y - NET_HEIGHT, NET_WIDTH, NET_HEIGHT), ) self._draw_score(model) self._draw_state_message(model) self._draw_touch_counter(model) self._draw_ball(model) self._draw_players(model) self._draw_attack_feedback(model) self._draw_receive_hitboxes(model) self._draw_attack_hitboxes(model) pygame.display.flip() def _draw_score(self, model): score_text = f"{model.left_score} : {model.right_score}" score_surface = self.font.render(score_text, True, (255, 255, 255)) score_x = WIDTH // 2 - score_surface.get_width() // 2 self.screen.blit(score_surface, (score_x, 10)) if model.game_over: win_surface = self.font.render(model.winner_text, True, (255, 220, 120)) win_x = WIDTH // 2 - win_surface.get_width() // 2 self.screen.blit(win_surface, (win_x, 60)) def _draw_state_message(self, model): if model.game_over: message = "Press R to restart match" elif model.is_round_over: message = f"{model.round_message}. Press R for next serve" elif model.state.value == "serve": if model.serving_team == "right": message = "Right serve. AI will serve" else: message = "Left serve. Stand behind line and press Space" else: return surface = self.small_font.render(message, True, (245, 245, 245)) x = WIDTH // 2 - surface.get_width() // 2 self.screen.blit(surface, (x, 92)) def _draw_touch_counter(self, model): if model.state.value != "playing" or model.last_touch_team is None: return message = f"{model.last_touch_team.title()} touches: {model.team_touches}/3" surface = self.small_font.render(message, True, (235, 235, 235)) x = WIDTH // 2 - surface.get_width() // 2 self.screen.blit(surface, (x, 62)) def _draw_ball(self, model): if self.ball_image is not None: ball_rect = self.ball_image.get_rect(center=(int(model.ball_x), int(model.ball_y))) self.screen.blit(self.ball_image, ball_rect) return pygame.draw.circle( self.screen, (240, 220, 80), (int(model.ball_x), int(model.ball_y)), BALL_RADIUS, ) def _load_image(self, filenames): assets_dir = os.path.join(os.path.dirname(__file__), "assets") for filename in filenames: path = os.path.join(assets_dir, filename) if os.path.exists(path): return pygame.image.load(path).convert_alpha() return None def _draw_players(self, model): for player in model.players: pygame.draw.rect( self.screen, player.color, (player.x, player.y, player.w, player.h), ) def _draw_attack_feedback(self, model): if model.attack_feedback_timer <= 0 or not model.attack_feedback_text: return colors = { "EARLY": (150, 210, 255), "GOOD": (120, 255, 160), "LATE": (255, 170, 100), } color = colors.get(model.attack_feedback_text, (255, 255, 255)) surface = self.small_font.render(model.attack_feedback_text, True, color) x = model.attack_feedback_x - surface.get_width() / 2 y = model.attack_feedback_y - (30 - model.attack_feedback_timer) * 0.4 self.screen.blit(surface, (x, y)) def _draw_attack_hitboxes(self, model): for player in model.players: hitbox = player.get_attack_hitbox() if hitbox is not None: pygame.draw.rect(self.screen, (255, 230, 80), hitbox, 2) line = player.get_attack_line() if line is not None: start, end = line pygame.draw.circle(self.screen, (80, 180, 255), (int(start[0]), int(start[1])), 6) pygame.draw.line(self.screen, (255, 120, 60), start, end, 4) pygame.draw.circle(self.screen, (255, 80, 80), (int(end[0]), int(end[1])), 6) contact_segment = player.get_attack_contact_segment() if contact_segment is not None: contact_start, contact_end = contact_segment pygame.draw.line(self.screen, (255, 230, 80), contact_start, contact_end, 10) def _draw_receive_hitboxes(self, model): for player in model.players: hitbox = player.get_receive_hitbox() if hitbox is not None: pygame.draw.rect(self.screen, (170, 230, 255), hitbox, 2)