コード例 #1
0
class AirhockeyScreen:
    dir = os.path.dirname(__file__)
    FPS = 60.0

    player1_keys = ['d', 'q', 'z', 's']
    player2_keys = ['Right', 'Left', 'Up', 'Down']

    score = {'player_1': 0, 'player_2': 0}

    def __init__(self):
        self.pub_player1 = rospy.Publisher('airhockey/simulator/player1', Twist, queue_size=60)
        self.pub_player2 = rospy.Publisher('airhockey/simulator/player2', Twist, queue_size=60)
        self.vel_player1 = 0, 0
        self.vel_player2 = 0, 0
        self.pub_image = rospy.Publisher('/airhockey/simulator/image', ImageMsg, queue_size=60)
        self.bridge = CvBridge()

        self.space = pymunk.Space()
        self.space.gravity = (0.0, 0.0)

        self.root = tk.Tk()
        self.root.title('Airhockey')
        self.root.resizable(width=False, height=False)
        self.root.geometry("{}x{}+{}+{}".format(1595, 1000, 0, 0))
        self.root.bind("<Escape>", lambda e: self.root.quit())
        #self.root.bind('<Motion>', self.mouse_position)

        self.field_image = Image.open(os.path.join(self.dir, '../res', 'field.png'))

        self.static_body = pymunk.Body(body_type=pymunk.Body.STATIC)
        self.static_line = pymunk.Segment(self.static_body, (0, 40), (1595, 40), 0.0)
        self.static_line.elasticity = 1
        self.space.add(self.static_body, self.static_line)

        self.static_body = pymunk.Body(body_type=pymunk.Body.STATIC)
        self.static_line = pymunk.Segment(self.static_body, (0, 960), (1595, 960), 0.0)
        self.static_line.elasticity = 1
        self.space.add(self.static_body, self.static_line)

        self.static_body = pymunk.Body(body_type=pymunk.Body.STATIC)
        self.static_line = pymunk.Segment(self.static_body, (40, 0), (40, 1000), 0.0)
        self.static_line.elasticity = 1
        self.space.add(self.static_body, self.static_line)

        self.static_body = pymunk.Body(body_type=pymunk.Body.STATIC)
        self.static_line = pymunk.Segment(self.static_body, (1550, 0), (1550, 1000), 0.0)
        self.static_line.elasticity = 1
        self.space.add(self.static_body, self.static_line)

        self.player1_object = Pod(200, 500, 100, 3, 'player1', 'airhockey/simulator/player1')
        self.player2_object = Pod(1390, 500, 100, 3, 'player2', 'airhockey/simulator/player2')
        self.puck = Puck(795, 500, 60, 1)

        self.space.add(self.player1_object.body, self.player1_object.shape)
        self.space.add(self.player2_object.body, self.player2_object.shape)
        self.space.add(self.puck.body, self.puck.shape)

        self.field = ImageTk.PhotoImage(self.get_field_image(self.player1_object, self.player2_object, self.puck))

        self.canvas = tk.Canvas(self.root, width=1590, height=1000)
        self.canvas.pack()

        self.root.bind_all('<KeyPress>', self.key_pressed)
        self.root.bind_all('<KeyRelease>', self.key_released)

        self.root.after(int(round(1000 / self.FPS, 0)), func=self.tick)

    def tick(self):
        self.player1_object.move()
        self.player2_object.move()
        self.space.step(1 / self.FPS)
        self.render()
        self.puck.check_goal(self.score)
        self.root.after(int(round(1000 / self.FPS, 0)), func=self.tick)

    def render(self):
        self.canvas.delete('all')
        image = self.get_field_image(self.player1_object, self.player2_object, self.puck)
        field = ImageTk.PhotoImage(image)
        self.canvas.create_image((795, 500), image=field)
        self.canvas.image = field
        self.canvas.create_text(799, 75, fill='darkblue', font='Times 80 bold',
                                text='{}:{}'.format(self.score['player_1'], self.score['player_2']))
        """
        Subscribe to this topic to analyze the board in ROS with OpenCV
        To move the player publish a message of geometry_msgs.msg.Twist to /airhockey/player1 or /airhockey/player2.
        """
        self.pub_image.publish(self.bridge.cv2_to_imgmsg(cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR), 'bgr8'))

    def get_field_image(self, *args):
        img_to_show = Image.new('RGB', (1590, 1000), color=(255, 255, 255, 1))
        img_to_show.paste(self.field_image, (0, 0), self.field_image)
        for game_object in args:
            img_to_show.paste(game_object.image, (game_object.get_position()), game_object.image)
        return img_to_show

    def mouse_position(self, event):
        pos_x, pos_y = event.x, event.y
        self.player1_object.set_position(pos_x, pos_y)

    def key_pressed(self, event):
        motion_command = Twist()
        if event.keysym in self.player1_keys:
            velocity = self.get_velocity(event, self.vel_player1)
            self.vel_player1 = velocity
            motion_command.linear.x = velocity[0]
            motion_command.linear.y = velocity[1]
            self.pub_player1.publish(motion_command)
        elif event.keysym in self.player2_keys:
            velocity = self.get_velocity(event, self.vel_player2)
            self.vel_player2 = velocity
            motion_command.linear.x = velocity[0]
            motion_command.linear.y = velocity[1]
            self.pub_player2.publish(motion_command)

    def key_released(self, event):
        motion_command = Twist()
        if event.keysym in self.player1_keys:
            velocity = self.reset_velocity(event, self.vel_player1)
            self.vel_player1 = velocity
            motion_command.linear.x = velocity[0]
            motion_command.linear.y = velocity[1]
            self.pub_player1.publish(motion_command)
        elif event.keysym in self.player2_keys:
            velocity = self.reset_velocity(event, self.vel_player2)
            self.vel_player2 = velocity
            motion_command.linear.x = velocity[0]
            motion_command.linear.y = velocity[1]
            self.pub_player2.publish(motion_command)

    def get_velocity(self, event, velocity):
        _vel_x, _vel_y = velocity
        if 'Right' == event.keysym or event.keysym  == 'd':
            _vel_x = 15
        elif 'Left' == event.keysym or event.keysym == 'q':
            _vel_x = -15
        elif 'Up' == event.keysym or event.keysym == 'z':
            _vel_y = -15
        elif 'Down' == event.keysym or event.keysym == 's':
            _vel_y = 15
        return _vel_x, _vel_y

    def reset_velocity(self, event, velocity):
        _vel_x, _vel_y = velocity
        if 'Right' == event.keysym or event.keysym == 'd' or 'Left' == event.keysym or event.keysym == 'q':
            _vel_x = 0
        elif 'Up' == event.keysym or event.keysym == 'z' or 'Down' == event.keysym or event.keysym == 's':
            _vel_y = 0
        return _vel_x, _vel_y