最终文件

master
could_dream111 2 years ago
parent ccfe1604ea
commit 052b5fbcb8

@ -0,0 +1,13 @@
from common.game.billiards.baseBilliard import BaseBilliard
from enums.color import WHITE
from enums.category import CUE_BALL
class ColorBall(BaseBilliard):
def __init__(self, score: int, category: int, color: tuple[int, int, int], pos=(0, 0)):
super().__init__(score, category, color, pos)
self.__start_pos = pos
def reset(self):
self.pos = self.__start_pos
self.activity = True

@ -0,0 +1,8 @@
from common.game.billiards.baseBilliard import BaseBilliard
from enums.color import WHITE
from enums.category import CUE_BALL
class CueBall(BaseBilliard):
def __init__(self, pos=(0, 0)):
super().__init__(-1, CUE_BALL, WHITE, pos)

@ -0,0 +1,15 @@
import pygame
from common.drawableItem import DrawableItem
from config.sys import BALL_RADIUS
from enums.color import WHITE, BLACK
class FakeCueBall(DrawableItem):
def __init__(self, pos):
self.pos = pos
def draw(self, window: pygame.Surface):
pygame.draw.circle(window, WHITE, self.pos, BALL_RADIUS)
pygame.draw.circle(window, BLACK, self.pos, BALL_RADIUS, 1)
pass

@ -0,0 +1,11 @@
from common.game.billiards.baseBilliard import BaseBilliard
from enums.color import RED
from enums.category import RED_BALL
class RedBall(BaseBilliard):
def __init__(self, pos):
super().__init__(1, RED_BALL, RED, pos)
def reset(self):
pass

@ -0,0 +1,167 @@
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

@ -0,0 +1,24 @@
from common.game.billiards.colorBall import ColorBall
from common.game.billiards.redBall import RedBall
from common.game.billiards.cueBall import CueBall
class GameData(object):
def __init__(self):
self.left_score = 0
self.right_score = 0
self.balls: list[ColorBall | RedBall | CueBall] = []
self.last_balls: list[ColorBall | RedBall | CueBall] = []
self.goal_balls: list[int] = []
self.last_goal_balls: list[int] = []
self.collide_log: list[int] = []
pass
def collide_ball(self, ball):
self.collide_log.append(ball)
def is_stable(self) -> bool:
for _ in self.balls:
if not _.is_stable():
return False
return True

@ -0,0 +1,124 @@
from common.game.gameData import GameData
from enums.category import *
class RuleManager(object):
def __init__(self, game_data: GameData):
self.__game_data = game_data
self.__should_hit = []
self.need_reset_cue_ball = False
self.settlement = False
self.round = 1
def judge(self):
self.print_log()
self.do_reset()
self.cal_score()
self.try_turn_round()
self.settlement = False
def print_log(self):
print('round:' + str(self.round))
print('collide: ' + str(self.__game_data.collide_log))
print('collision_flag: ' + str(self.collision_legal()))
print('goal: ' + str(self.__game_data.goal_balls))
print('goal_flag: ' + str(self.goal_legal()))
def check_legality(self):
return self.collision_legal() and self.goal_legal() and self.cue_legal()
def do_reset(self):
if not self.goal_legal():
for _ in self.__game_data.balls:
if _.category in COLORED_BALLS and _.category in self.__game_data.goal_balls:
_.reset()
if not self.cue_legal():
self.need_reset_cue_ball = True
for _ in self.__game_data.balls:
if _.category == RED_BALL and _.activity:
for __ in self.__game_data.balls:
if __.category in COLORED_BALLS and __.category in self.__game_data.goal_balls:
__.reset()
break
def get_legality(self):
legality = []
if not self.collision_legal():
legality.append(legality)
if not self.goal_legal():
legality.append(legality)
if not self.cue_legal():
legality.append(legality)
return legality
def try_turn_round(self):
if len(self.__game_data.goal_balls) != 0 and self.check_legality():
return
self.__game_data.goal_balls.clear()
self.__game_data.last_goal_balls.clear()
self.round *= -1
def get_should_hit(self):
self.__should_hit.clear()
have_red_ball = False
for _ in self.__game_data.balls:
if _.category == RED_BALL and _.activity:
have_red_ball = True
break
if have_red_ball:
if len(self.__game_data.last_goal_balls) == 0:
return self.__should_hit.append(RED_BALL)
if self.__game_data.last_goal_balls[0] in COLORED_BALLS:
return self.__should_hit.append(RED_BALL)
self.__should_hit = [_ for _ in COLORED_BALLS]
return
should_hit = 7
for _ in self.__game_data.balls:
if _.category < should_hit and _.activity:
should_hit = _.category
return self.__should_hit.append(should_hit)
def collision_legal(self):
if len(self.__game_data.collide_log) == 0:
return False
if self.__game_data.collide_log[0] in self.__should_hit:
return True
return False
def goal_legal(self):
without_cue_list = [_ for _ in self.__game_data.goal_balls]
if CUE_BALL in without_cue_list:
without_cue_list.remove(CUE_BALL)
if len(without_cue_list) == 0:
return True
if len(list(set(without_cue_list) & set(self.__should_hit))) == 0:
return False
if RED_BALL not in self.__should_hit and len(list(set(without_cue_list) & set(self.__should_hit))) != 1:
return True
return True
def cue_legal(self):
return CUE_BALL not in self.__game_data.goal_balls
def cal_score(self):
if self.round == 1:
if self.check_legality():
for _ in self.__game_data.goal_balls:
self.__game_data.left_score += _
return
if len(self.__game_data.collide_log) == 0:
self.__game_data.right_score += 4
return
first_collide = self.__game_data.collide_log[0]
self.__game_data.right_score += first_collide if first_collide > 4 else 4
else:
if self.check_legality():
for _ in self.__game_data.goal_balls:
self.__game_data.right_score += _
return
if len(self.__game_data.collide_log) == 0:
self.__game_data.left_score += 4
return
first_collide = self.__game_data.collide_log[0]
self.__game_data.left_score += first_collide if first_collide > 4 else 4
pass

@ -0,0 +1,2 @@
ILLEGAL_COLLISION = 1
ILLEGAL_GOAL = 2

Binary file not shown.
Loading…
Cancel
Save