/
pentomas
/
volley
Обзор
Документация
Войти
/
pentomas
/
volley
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
player.py
236 строк
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
Код
Авторство
О чём код?
from math import cos, radians, sin from constants import ( ATTACK_DURATION, ATTACK_HEIGHT, ATTACK_WIDTH, COURT_LEFT, COURT_RIGHT, FLOOR_Y, PLAYER_GRAVITY, PLAYER_JUMP_SPEED, RECEIVE_HEIGHT, RECEIVE_WIDTH, WIDTH, ) class Player: role = "player" color = (255, 255, 255) speed = 5 jump_speed = PLAYER_JUMP_SPEED def __init__(self, team, x): self.team = team self.control = "human" self.x = x self.y = FLOOR_Y - 60 self.w = 30 self.h = 60 self.vy = 0 self.facing = 1 if team == "left" else -1 self.attack_timer = 0 self.attack_used = False self.is_receiving = False @property def ground_y(self): return FLOOR_Y - self.h @property def is_on_ground(self): return self.y == self.ground_y @property def is_attacking(self): return self.attack_timer > 0 @property def attack_progress(self): if not self.is_attacking: return 0 return 1 - self.attack_timer / ATTACK_DURATION @property def attack_angle(self): if not self.is_attacking: return 0 start_angle = -100 end_angle = 35 angle = start_angle + (end_angle - start_angle) * self.attack_progress if self.team == "right": angle = 180 - angle return angle def update(self, move_left, move_right, action, receive=False, bounds=None): self.is_receiving = receive if move_left: self.x -= self.speed self.facing = -1 if move_right: self.x += self.speed self.facing = 1 if action: if self.is_on_ground: self.vy = self.jump_speed else: self.start_attack() self._keep_on_side(bounds) self._update_jump() self._update_attack() def start_attack(self): if self.attack_used or self.is_attacking: return self.attack_timer = ATTACK_DURATION self.attack_used = True def reset_vertical_position(self): self.y = self.ground_y self.vy = 0 self.attack_timer = 0 self.attack_used = False def get_attack_hitbox(self): if not self.is_attacking: return None progress = self.attack_progress hitbox_y = self.y + 8 + progress * 22 attack_direction = 1 if self.team == "left" else -1 if attack_direction == 1: hitbox_x = self.x + self.w else: hitbox_x = self.x - ATTACK_WIDTH return (hitbox_x, hitbox_y, ATTACK_WIDTH, ATTACK_HEIGHT) def get_receive_hitbox(self): if not self.is_receiving: return None receive_direction = 1 if self.team == "left" else -1 hitbox_y = self.y + self.h * 0.48 if receive_direction == 1: hitbox_x = self.x + self.w else: hitbox_x = self.x - RECEIVE_WIDTH return (hitbox_x, hitbox_y, RECEIVE_WIDTH, RECEIVE_HEIGHT) def get_attack_velocity(self, ball_y): angle = radians(self.attack_angle) timing_quality = self.attack_timing_quality power = self.attack_vx * (0.75 + timing_quality * 0.35) vx = cos(angle) * power vy = sin(angle) * power if ball_y > self.y + self.h * 0.55: vy += 2.0 return vx, vy @property def attack_timing_quality(self): if not self.is_attacking: return 0 ideal_progress = 0.58 timing_error = abs(self.attack_progress - ideal_progress) return max(0.35, 1 - timing_error * 1.6) @property def attack_timing_label(self): if self.attack_progress < 0.4: return "EARLY" if self.attack_progress > 0.75: return "LATE" return "GOOD" def _update_jump(self): self.vy += PLAYER_GRAVITY self.y += self.vy if self.y >= self.ground_y: self.reset_vertical_position() def _update_attack(self): if self.attack_timer > 0: self.attack_timer -= 1 def _keep_on_side(self, bounds=None): if bounds is not None: min_x, max_x = bounds if self.x < min_x: self.x = min_x if self.x + self.w > max_x: self.x = max_x - self.w return if self.team == "left": if self.x < COURT_LEFT: self.x = COURT_LEFT if self.x + self.w > WIDTH // 2: self.x = WIDTH // 2 - self.w else: if self.x < WIDTH // 2: self.x = WIDTH // 2 if self.x + self.w > COURT_RIGHT: self.x = COURT_RIGHT - self.w def get_attack_line(self): if not self.is_attacking: return None length = 62 angle = radians(self.attack_angle) shoulder_x = self.x + self.w if self.team == "left" else self.x shoulder_y = self.y + 18 hand_x = shoulder_x + cos(angle) * length hand_y = shoulder_y + sin(angle) * length return (shoulder_x, shoulder_y), (hand_x, hand_y) def get_attack_contact_segment(self): line = self.get_attack_line() if line is None: return None shoulder, hand = line shoulder_x, shoulder_y = shoulder hand_x, hand_y = hand elbow_x = (shoulder_x + hand_x) / 2 elbow_y = (shoulder_y + hand_y) / 2 return (elbow_x, elbow_y), hand class OutsideHitter(Player): role = "outside" color = (80, 170, 255) attack_vx = 10.5 speed = 5 jump_speed = -12.8 class Setter(Player): role = "setter" color = (255, 80, 80) attack_vx = 6.5 speed = 5.6 jump_speed = -11.4