You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
8.0 KiB

import sys
import pygame
import pymunk
from common.game.billiards.baseBilliard import BaseBilliard
from common.game.billiards.colorBall import ColorBall
from common.game.billiards.cueBall import CueBall
from common.game.billiards.fakeCueball import FakeCueBall
from common.game.billiards.redBall import RedBall
from common.game.cue import Cue
from common.game.gameData import GameData
from common.game.ruleManager import RuleManager
from common.game.table import Table
from config.sys import *
from enums.color import *
from enums.category import *
class Game(object):
def __init__(self):
self.__game_data = GameData()
self.__table = Table(self.__game_data)
self.__cue_ball = CueBall((TABLE_WIDTH * 7 / 8, TABLE_HEIGHT / 4))
self.__game_data.balls.append(self.__cue_ball)
self.__cue = Cue(self.__cue_ball, self.__game_data)
self.__space = pymunk.Space()
self.__clock = pygame.time.Clock()
self.__space.gravity = (0, 0)
self.__rule = RuleManager(self.__game_data)
self.__hitting = False
self.__window = pygame.display.set_mode(SCREEN_SIZE)
self.__fake_ball = FakeCueBall((99999, 99999))
pass
def add_ball(self, ball: BaseBilliard):
self.__game_data.balls.append(ball)
self.__space.add(ball.rigid_body, ball.shape)
def init_table(self):
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS, TABLE_HEIGHT / 2)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 2, TABLE_HEIGHT / 2 - BALL_RADIUS / 2)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 2, TABLE_HEIGHT / 2 + BALL_RADIUS / 2)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 3, TABLE_HEIGHT / 2)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 3, TABLE_HEIGHT / 2 - BALL_RADIUS)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 3, TABLE_HEIGHT / 2 + BALL_RADIUS)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 4, TABLE_HEIGHT / 2 - BALL_RADIUS / 2)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 4, TABLE_HEIGHT / 2 + BALL_RADIUS / 2)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 4, TABLE_HEIGHT / 2 - BALL_RADIUS)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 4, TABLE_HEIGHT / 2 + BALL_RADIUS)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 5, TABLE_HEIGHT / 2)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 5, TABLE_HEIGHT / 2 - BALL_RADIUS)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 5, TABLE_HEIGHT / 2 + BALL_RADIUS)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 5, TABLE_HEIGHT / 2 - BALL_RADIUS * 2)))
self.add_ball(RedBall((TABLE_WIDTH / 4 - BALL_RADIUS * 5, TABLE_HEIGHT / 2 + BALL_RADIUS * 2)))
self.add_ball(ColorBall(2, YELLOW_BALL, YELLOW, (TABLE_WIDTH * 3 / 4, TABLE_HEIGHT / 3)))
self.add_ball(ColorBall(3, COFFEE_BALL, COFFEE, (TABLE_WIDTH * 3 / 4, TABLE_HEIGHT / 2)))
self.add_ball(ColorBall(4, CLAN_BALL, CLAN, (TABLE_WIDTH * 3 / 4, TABLE_HEIGHT * 2 / 3)))
self.add_ball(ColorBall(5, BLUE_BALL, BLUE, (TABLE_WIDTH / 2, TABLE_HEIGHT / 2)))
self.add_ball(ColorBall(6, PINK_BALL, PINK, (TABLE_WIDTH / 4 + BALL_RADIUS * 3, TABLE_HEIGHT / 2)))
self.add_ball(ColorBall(7, BLACK_BALL, BLACK, (TABLE_WIDTH / 8, TABLE_HEIGHT / 2)))
pass
def print_score(self, left_score, right_score):
font = pygame.font.Font("./src/fonts/PingFang.ttc", 24)
left_surface = font.render("left: " + str(left_score), True, BLACK, None)
right_surface = font.render("right: " + str(right_score), True, BLACK, None)
round_surface = font.render("round: " + ("left" if self.__rule.round == 1 else "right"), True, BLACK, None)
self.__window.blit(left_surface, (SCREEN_WIDTH / 8, SCREEN_HEIGHT * 7 / 8))
self.__window.blit(right_surface, (SCREEN_WIDTH * 7 / 8 - right_surface.get_width(), SCREEN_HEIGHT * 7 / 8))
self.__window.blit(round_surface, (SCREEN_WIDTH / 2 - round_surface.get_width() / 2, SCREEN_HEIGHT * 7 / 8))
def hit(self, x, y):
self.__hitting = True
self.__game_data.last_goal_balls = [_ for _ in self.__game_data.goal_balls]
self.__rule.get_should_hit()
self.__game_data.collide_log.clear()
self.__game_data.goal_balls.clear()
pos_x = x - (SCREEN_WIDTH - TABLE_WIDTH) / 2
pos_y = y - (SCREEN_HEIGHT - TABLE_HEIGHT) / 2
self.__cue_ball.rigid_body.velocity = pymunk.Vec2d(
pos_x - self.__game_data.balls[0].rigid_body.position.x,
pos_y - self.__game_data.balls[0].rigid_body.position.y).scale_to_length(512)
def start(self):
def new_ball(space, pos):
ball = RedBall(pos)
body = ball.rigid_body
shape = ball.shape
space.add(body, shape)
self.__game_data.balls.append(ball)
return shape
def post_collision_ball_ball(arbiter, space, data):
self.__game_data.collide_log.append(arbiter.shapes[0].collision_type)
pygame.init()
pygame.display.set_caption(TITLE)
self.init_table()
for _ in range(1, 9):
self.__space.add_collision_handler(_, CUE_BALL).post_solve = post_collision_ball_ball
for _ in range(6):
self.__space.add(self.__table.cushing_body[_], self.__table.cushing_shape[_])
self.__space.add(self.__game_data.balls[0].rigid_body, self.__game_data.balls[0].shape)
force = 5
add_force = False
while True:
if self.__rule.settlement:
self.__rule.judge()
if self.__game_data.is_stable() and self.__hitting:
self.__rule.settlement = True
self.__hitting = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if not self.__game_data.is_stable():
continue
if event.type == pygame.MOUSEMOTION:
self.__cue.mouse_pos = event.pos
if self.__rule.need_reset_cue_ball:
self.__fake_ball.pos = event.pos
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
add_force = True
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
if self.__rule.need_reset_cue_ball:
pos_x = - (SCREEN_WIDTH - TABLE_WIDTH) / 2 + event.pos[0]
pos_y = - (SCREEN_HEIGHT - TABLE_HEIGHT) / 2 + event.pos[1]
self.__cue_ball.pos = (pos_x + 1, pos_y + 1)
self.__fake_ball.pos = (99999, 99999)
self.__rule.need_reset_cue_ball = False
else:
self.hit(event.pos[0], event.pos[1])
add_force = False
force = 5
if event.button == 3:
pos_x = event.pos[0] - (SCREEN_WIDTH - TABLE_WIDTH) / 2
pos_y = event.pos[1] - (SCREEN_HEIGHT - TABLE_HEIGHT) / 2
new_ball(self.__space, (pos_x, pos_y))
if add_force:
force += 5
if force >= 512:
force = 512
self.__window.fill(WHITE)
self.__table.goal(self.__space, self.__game_data.balls)
self.__table.draw(self.__window)
self.__fake_ball.draw(self.__window)
if not self.__rule.need_reset_cue_ball:
self.__cue.draw(self.__window)
for _ in self.__game_data.balls:
_.resistance()
_.draw(self.__window)
self.print_score(self.__game_data.left_score, self.__game_data.right_score)
self.__space.step(1 / FPS)
pygame.display.update()
self.__clock.tick(FPS)
pass
pass