diff --git a/game_plat.py b/game_plat.py index f05ed00..45b7a20 100644 --- a/game_plat.py +++ b/game_plat.py @@ -5,6 +5,7 @@ import random from utils.cv_marker import cap_and_mark # from utils.stack_exe import Stackbot import cv2 +import sys pygame.init() @@ -28,6 +29,14 @@ cap.set(6,cv2.VideoWriter.fourcc('M','J','P','G')) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) +# 定义屏幕尺寸 +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 + +# 定义按钮尺寸 +BUTTON_WIDTH = 200 +BUTTON_HEIGHT = 200 + class Block: def __init__(self, x, y, width, height, angle, layer): self.x = x @@ -62,30 +71,34 @@ class Block: class Tower: - def __init__(self): + def __init__(self, blueprint, tower_image=None): self.blocks = [] self.current_layer = 0 - self.layer_centroids = [] # 存储每层的重心 - self.stability_threshold = 10 # 稳定性阈值(像素) - self.rotation_angle = 15 # 预设每层旋转角度 - self.angle_tolerance = 5 # 允许的角度偏移 - self.position_tolerance = 10 # 允许的位置偏移 + self.layer_centroids = [] + self.stability_threshold = 10 + self.rotation_angle = 15 + self.angle_tolerance = 5 + self.position_tolerance = 10 self.sim_to_robot_matrix = np.array([ - [1, 0, 0, -300], # 假设的转换矩阵,需要根据实际情况调整 + [1, 0, 0, -300], [0, -1, 0, -200], [0, 0, 1, 0], [0, 0, 0, 1] ]) self.robot_to_sim_matrix = np.linalg.inv(self.sim_to_robot_matrix) - # self.stack_bot = Stackbot() - self.is_upper = False + self.blueprint = blueprint + self.center_x, self.center_y = 300, 300 # 定义塔的中心点 self.ideal_positions = self.get_ideal_positions() - self.position_tolerance = 20 # 允许的位置偏差(像素) - self.angle_tolerance = 15 # 允许的角度偏差(度) + self.position_tolerance = 20 + self.angle_tolerance = 15 + + self.tower_image = None + if tower_image: + self.tower_image = pygame.transform.scale(tower_image, (150, 150)) # 调整图片大小 def sim_to_robot_coords(self, x, y, angle): sim_coords = np.array([x, y, 0, 1]) @@ -262,29 +275,15 @@ class Tower: self.current_layer += 1 def get_ideal_positions(self): - # 定义中心原点 - center_x, center_y = 400, 450 - - # 定义相对坐标和角度 - relative_positions = [ - [(0, 40, 0), (0, -40, 0)], # 第一层 - [(-40, 0, 90), (40, 0, 90)], # 第二层 - [(0, 40, 0), (0, -40, 0)], # 第三层 - [(-40, 0, 90), (40, 0, 90)], # 第四层 - [(0, 40, 0), (0, -40, 0)], # 第五层 - # ... 可以继续添加更多层 ... - ] - - # 转换为绝对坐标 + # 将相对坐标转换为绝对坐标 absolute_positions = [] - for layer in relative_positions: + for layer in self.blueprint: layer_positions = [] for rel_x, rel_y, angle in layer: - abs_x = center_x + rel_x - abs_y = center_y + rel_y + abs_x = self.center_x + rel_x + abs_y = self.center_y + rel_y layer_positions.append((abs_x, abs_y, angle)) absolute_positions.append(layer_positions) - return absolute_positions def auto_place_block(self): @@ -297,7 +296,7 @@ class Tower: if best_position: x, y, angle = best_position - print(f"选择的最佳位置: ({x}, {y}) 角度为 {angle}") # 添加这行来调试 + print(f"选择的最佳位置: ({x}, {y}) 角度为 {angle}") return Block(x, y, 100, 20, angle, self.current_layer) else: print("无法找到合适的放置位置") @@ -322,16 +321,28 @@ class Tower: def find_best_position(self, possible_positions): best_position = None min_distance = float('inf') + + # 获取当前层已放置的木块数量 + blocks_in_current_layer = sum(1 for block in self.blocks if block.layer == self.current_layer) + + # 获取当前层的理想位置 + ideal_positions = self.ideal_positions[self.current_layer] + + # 确保我们选择正确的理想位置 + if blocks_in_current_layer < len(ideal_positions): + ideal_x, ideal_y, ideal_angle = ideal_positions[blocks_in_current_layer] + else: + print("警告:当前层的所有位置都已被填满") + return None for x, y, angle in possible_positions: new_block = Block(x, y, 100, 20, angle, self.current_layer) if self.has_support(new_block) and not self.check_interference(new_block): - temp_tower = Tower() + temp_tower = Tower(self.blueprint) temp_tower.blocks = self.blocks.copy() temp_tower.add_block(new_block) if temp_tower.check_stability(): - ideal_x, ideal_y, ideal_angle = self.ideal_positions[self.current_layer][len(self.blocks) % 2] distance = np.sqrt((x - ideal_x)**2 + (y - ideal_y)**2) + abs(angle - ideal_angle) if distance < min_distance: @@ -398,8 +409,146 @@ class Tower: self.add_block_from_robot(block[0][0], block[0][1], block[1]) + def draw_tower_image(self, screen): + if self.tower_image: + image_rect = self.tower_image.get_rect() + image_rect.topright = (SCREEN_WIDTH - 10, 10) # 放置在右上角,留出10像素的边距 + screen.blit(self.tower_image, image_rect) + +def show_tower_selection(screen): + # 加载塔型图片 + tower_images = [ + pygame.image.load("tower1.png"), + pygame.image.load("tower2.png"), + pygame.image.load("tower3.png") + ] + + # 调整图片大小 + tower_images = [pygame.transform.scale(img, (BUTTON_WIDTH, BUTTON_HEIGHT)) for img in tower_images] + + # 计算按钮位置 + button_y = (SCREEN_HEIGHT - BUTTON_HEIGHT) // 2 + button_x_start = (SCREEN_WIDTH - (BUTTON_WIDTH * 3 + 40)) // 2 + + # 创建按钮矩形 + buttons = [ + pygame.Rect(button_x_start + i * (BUTTON_WIDTH + 20), button_y, BUTTON_WIDTH, BUTTON_HEIGHT) + for i in range(3) + ] + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + if event.type == pygame.MOUSEBUTTONDOWN: + mouse_pos = pygame.mouse.get_pos() + for i, button in enumerate(buttons): + if button.collidepoint(mouse_pos): + return i # 返回选择的塔型索引 + + screen.fill(WHITE) + + # 绘制按钮和图片 + for i, (button, image) in enumerate(zip(buttons, tower_images)): + screen.blit(image, button.topleft) + pygame.draw.rect(screen, BLACK, button, 2) + + # 添加标题 + font = pygame.font.Font(None, 36) + title = font.render("选择塔型", True, BLACK) + title_rect = title.get_rect(center=(SCREEN_WIDTH // 2, 50)) + screen.blit(title, title_rect) + + pygame.display.flip() + +def get_tower_blueprint_1(): + # 第一种塔型的蓝图(相对坐标) + return [ + [(-40, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-35, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-30, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-25, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-20, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-15, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-10, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-5, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(0, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-5, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-10, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-15, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-20, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-25, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-30, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-35, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + [(-40, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + ] + +def get_tower_blueprint_2(): + # 第二种塔型的蓝图(相对坐标) + return [ + [(-20, 0, 90), (20, 0, 90)], + [(0, 20, 0), (0, -20, 0)], + ] + +def get_tower_blueprint_3(): + # 第三种塔型的蓝图(相对坐标) + return [ + [(-60, -60, 45), (60, -60, 135), (-60, 60, 135), (60, 60, 45)], + [(0, -80, 0), (80, 0, 90), (0, 80, 0), (-80, 0, 90)], + [(-55, -55, 45), (55, -55, 135), (-55, 55, 135), (55, 55, 45)], + [(0, -75, 0), (75, 0, 90), (0, 75, 0), (-75, 0, 90)], + [(-50, -50, 45), (50, -50, 135), (-50, 50, 135), (50, 50, 45)], + [(0, -70, 0), (70, 0, 90), (0, 70, 0), (-70, 0, 90)], + [(-45, -45, 45), (45, -45, 135), (-45, 45, 135), (45, 45, 45)], + [(0, -65, 0), (65, 0, 90), (0, 65, 0), (-65, 0, 90)], + [(-40, -40, 45), (40, -40, 135), (-40, 40, 135), (40, 40, 45)], + [(0, -60, 0), (60, 0, 90), (0, 60, 0), (-60, 0, 90)], + [(-40, 0, 90), (40, 0, 90)], + [(0, 40, 0), (0, -40, 0)], + ] + def main(): - tower = Tower() + pygame.init() + screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) + pygame.display.set_caption("积木塔仿真") + + # 加载塔型图片 + tower_images = [ + pygame.image.load("tower1.png"), + pygame.image.load("tower2.png"), + pygame.image.load("tower3.png") + ] + + # 显示塔型选择界面 + selected_tower = show_tower_selection(screen) + + # 根据选择的塔型设置相应的蓝图和图片 + if selected_tower == 0: + tower_blueprint = get_tower_blueprint_1() + elif selected_tower == 1: + tower_blueprint = get_tower_blueprint_2() + else: + tower_blueprint = get_tower_blueprint_3() + + tower = Tower(tower_blueprint, tower_images[selected_tower]) clock = pygame.time.Clock() current_block = None @@ -469,10 +618,12 @@ def main(): layer_text = font.render(f"Current layer: {tower.current_layer + 1}", True, BLACK) screen.blit(layer_text, (10, 10)) + tower.draw_tower_image(screen) + pygame.display.flip() clock.tick(60) pygame.quit() if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/tower1.png b/tower1.png new file mode 100644 index 0000000..5ea376c Binary files /dev/null and b/tower1.png differ diff --git a/tower2.png b/tower2.png new file mode 100644 index 0000000..288d1a4 Binary files /dev/null and b/tower2.png differ diff --git a/tower3.png b/tower3.png new file mode 100644 index 0000000..65881d6 Binary files /dev/null and b/tower3.png differ