gui improvement and blueprint
This commit is contained in:
parent
53ccf4439c
commit
f0096d2c74
219
game_plat.py
219
game_plat.py
|
@ -5,6 +5,7 @@ import random
|
||||||
from utils.cv_marker import cap_and_mark
|
from utils.cv_marker import cap_and_mark
|
||||||
# from utils.stack_exe import Stackbot
|
# from utils.stack_exe import Stackbot
|
||||||
import cv2
|
import cv2
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
pygame.init()
|
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_WIDTH, 1920)
|
||||||
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
|
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
|
||||||
|
|
||||||
|
# 定义屏幕尺寸
|
||||||
|
SCREEN_WIDTH = 800
|
||||||
|
SCREEN_HEIGHT = 600
|
||||||
|
|
||||||
|
# 定义按钮尺寸
|
||||||
|
BUTTON_WIDTH = 200
|
||||||
|
BUTTON_HEIGHT = 200
|
||||||
|
|
||||||
class Block:
|
class Block:
|
||||||
def __init__(self, x, y, width, height, angle, layer):
|
def __init__(self, x, y, width, height, angle, layer):
|
||||||
self.x = x
|
self.x = x
|
||||||
|
@ -62,30 +71,34 @@ class Block:
|
||||||
|
|
||||||
|
|
||||||
class Tower:
|
class Tower:
|
||||||
def __init__(self):
|
def __init__(self, blueprint, tower_image=None):
|
||||||
self.blocks = []
|
self.blocks = []
|
||||||
self.current_layer = 0
|
self.current_layer = 0
|
||||||
self.layer_centroids = [] # 存储每层的重心
|
self.layer_centroids = []
|
||||||
self.stability_threshold = 10 # 稳定性阈值(像素)
|
self.stability_threshold = 10
|
||||||
self.rotation_angle = 15 # 预设每层旋转角度
|
self.rotation_angle = 15
|
||||||
self.angle_tolerance = 5 # 允许的角度偏移
|
self.angle_tolerance = 5
|
||||||
self.position_tolerance = 10 # 允许的位置偏移
|
self.position_tolerance = 10
|
||||||
|
|
||||||
self.sim_to_robot_matrix = np.array([
|
self.sim_to_robot_matrix = np.array([
|
||||||
[1, 0, 0, -300], # 假设的转换矩阵,需要根据实际情况调整
|
[1, 0, 0, -300],
|
||||||
[0, -1, 0, -200],
|
[0, -1, 0, -200],
|
||||||
[0, 0, 1, 0],
|
[0, 0, 1, 0],
|
||||||
[0, 0, 0, 1]
|
[0, 0, 0, 1]
|
||||||
])
|
])
|
||||||
self.robot_to_sim_matrix = np.linalg.inv(self.sim_to_robot_matrix)
|
self.robot_to_sim_matrix = np.linalg.inv(self.sim_to_robot_matrix)
|
||||||
|
|
||||||
# self.stack_bot = Stackbot()
|
|
||||||
|
|
||||||
self.is_upper = False
|
self.is_upper = False
|
||||||
|
|
||||||
|
self.blueprint = blueprint
|
||||||
|
self.center_x, self.center_y = 300, 300 # 定义塔的中心点
|
||||||
self.ideal_positions = self.get_ideal_positions()
|
self.ideal_positions = self.get_ideal_positions()
|
||||||
self.position_tolerance = 20 # 允许的位置偏差(像素)
|
self.position_tolerance = 20
|
||||||
self.angle_tolerance = 15 # 允许的角度偏差(度)
|
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):
|
def sim_to_robot_coords(self, x, y, angle):
|
||||||
sim_coords = np.array([x, y, 0, 1])
|
sim_coords = np.array([x, y, 0, 1])
|
||||||
|
@ -262,29 +275,15 @@ class Tower:
|
||||||
self.current_layer += 1
|
self.current_layer += 1
|
||||||
|
|
||||||
def get_ideal_positions(self):
|
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 = []
|
absolute_positions = []
|
||||||
for layer in relative_positions:
|
for layer in self.blueprint:
|
||||||
layer_positions = []
|
layer_positions = []
|
||||||
for rel_x, rel_y, angle in layer:
|
for rel_x, rel_y, angle in layer:
|
||||||
abs_x = center_x + rel_x
|
abs_x = self.center_x + rel_x
|
||||||
abs_y = center_y + rel_y
|
abs_y = self.center_y + rel_y
|
||||||
layer_positions.append((abs_x, abs_y, angle))
|
layer_positions.append((abs_x, abs_y, angle))
|
||||||
absolute_positions.append(layer_positions)
|
absolute_positions.append(layer_positions)
|
||||||
|
|
||||||
return absolute_positions
|
return absolute_positions
|
||||||
|
|
||||||
def auto_place_block(self):
|
def auto_place_block(self):
|
||||||
|
@ -297,7 +296,7 @@ class Tower:
|
||||||
|
|
||||||
if best_position:
|
if best_position:
|
||||||
x, y, angle = 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)
|
return Block(x, y, 100, 20, angle, self.current_layer)
|
||||||
else:
|
else:
|
||||||
print("无法找到合适的放置位置")
|
print("无法找到合适的放置位置")
|
||||||
|
@ -322,16 +321,28 @@ class Tower:
|
||||||
def find_best_position(self, possible_positions):
|
def find_best_position(self, possible_positions):
|
||||||
best_position = None
|
best_position = None
|
||||||
min_distance = float('inf')
|
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:
|
for x, y, angle in possible_positions:
|
||||||
new_block = Block(x, y, 100, 20, angle, self.current_layer)
|
new_block = Block(x, y, 100, 20, angle, self.current_layer)
|
||||||
|
|
||||||
if self.has_support(new_block) and not self.check_interference(new_block):
|
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.blocks = self.blocks.copy()
|
||||||
temp_tower.add_block(new_block)
|
temp_tower.add_block(new_block)
|
||||||
if temp_tower.check_stability():
|
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)
|
distance = np.sqrt((x - ideal_x)**2 + (y - ideal_y)**2) + abs(angle - ideal_angle)
|
||||||
|
|
||||||
if distance < min_distance:
|
if distance < min_distance:
|
||||||
|
@ -398,8 +409,146 @@ class Tower:
|
||||||
self.add_block_from_robot(block[0][0], block[0][1], block[1])
|
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():
|
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()
|
clock = pygame.time.Clock()
|
||||||
current_block = None
|
current_block = None
|
||||||
|
|
||||||
|
@ -469,10 +618,12 @@ def main():
|
||||||
layer_text = font.render(f"Current layer: {tower.current_layer + 1}", True, BLACK)
|
layer_text = font.render(f"Current layer: {tower.current_layer + 1}", True, BLACK)
|
||||||
screen.blit(layer_text, (10, 10))
|
screen.blit(layer_text, (10, 10))
|
||||||
|
|
||||||
|
tower.draw_tower_image(screen)
|
||||||
|
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
clock.tick(60)
|
clock.tick(60)
|
||||||
|
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
After Width: | Height: | Size: 141 KiB |
Loading…
Reference in New Issue