Module moog_demos.gui_frames
This file contains GUI frames for human_agent.py.
The classes in this file are interfaces for playing the demo with different action spaces. If you are using an action space that doesn't fall into one of these categories, you must create your own gui for it.
Note: on some computers, the keyboard interfaces don't work properly, and holding letter or arrow keys repeatedly takes actions. This is an issue with your computer's keyboard sending rapid press/release signals when you hold down a key. You can resolve this by (i) changing your computer's keyboard settings to not do this behavior when you hold down a key, or (ii) modify the class in this file that you're using to do whatever behavior you want when a key is held down (this will involve a bit of debugging for you).
Expand source code
"""This file contains GUI frames for human_agent.py.
The classes in this file are interfaces for playing the demo with different
action spaces. If you are using an action space that doesn't fall into one of
these categories, you must create your own gui for it.
Note: on some computers, the keyboard interfaces don't work properly, and
holding letter or arrow keys repeatedly takes actions. This is an issue with
your computer's keyboard sending rapid press/release signals when you hold down
a key. You can resolve this by (i) changing your computer's keyboard settings to
not do this behavior when you hold down a key, or (ii) modify the class in this
file that you're using to do whatever behavior you want when a key is held down
(this will involve a bit of debugging for you).
"""
import numpy as np
import tkinter as tk
class JoystickFrame(tk.Frame):
"""Joystick Tkinter frame.
This creates the frame for an interactive joystick. The joystick consists of
three objects:
(i) A large gray "motion zone" circle in the background. This is the
area in which the joystick can be moved.
(ii) A small black "center point" circle fixed in the middle ground.
This indicates the joystick position that give zero action.
(iii) A green "joystick" circle in the foreground that can be moved. The
center of this circle is the action readout.
If the mouse is not clicked, then position of the joystick centerpoint is 0
(in the center of the motion zone). If the mouse is currently pressed, then
the position of the joystick is the closest point in the motion zone to the
mouse position. Namely, if the mouse is in the motion zone then the joystick
is directly under the mouse, and if the mouse is not in the motion zone then
the joystick is at the edge of the motion zone closest to the mouse.
Thus the joystick can be moved by clicking the mouse anywhere (in which case
the joystick jumps to that position) and dragging the pressed mouse around
(in which case the joystick moves underneath the mouse).
"""
def __init__(self, root, canvas_half_width=100, motion_zone_radius=90,
joystick_radius=10, center_point_radius=3):
"""Constructor.
Args:
root: Instance of tk.Frame. Root frame in which the joystick lives.
canvas_half_width: Int. Half of the width of the canvas on which the
joystick is rendered.
motion_zone_radius: Int. Radius of the motion zone.
joystick_radius: Int. Radius of the joystick.
center_point_radius: Int. Radius of the center point.
"""
super(JoystickFrame, self).__init__(root)
self._joystick_radius = joystick_radius
self._canvas_half_width = canvas_half_width
self._motion_zone_radius = motion_zone_radius
self._center_point_radius = center_point_radius
# Create a canvas
self.canvas = tk.Canvas(
width=2 * canvas_half_width,
height=2 * canvas_half_width)
# Create motion zone, center point, and joystick
self._create_items()
# Add bindings for clicking, dragging and releasing the joystick
self.canvas.bind('<ButtonPress-1>', self._mouse_press)
self.canvas.bind('<ButtonRelease-1>', self._mouse_release)
self.canvas.bind('<B1-Motion>', self._mouse_move)
self._mouse_is_pressed = False
def _create_items(self):
# Create motion zone
self.canvas.create_oval(
self._canvas_half_width - self._motion_zone_radius,
self._canvas_half_width - self._motion_zone_radius,
self._canvas_half_width + self._motion_zone_radius,
self._canvas_half_width + self._motion_zone_radius,
fill='gray80',
)
# Create center point
self.canvas.create_oval(
self._canvas_half_width - self._center_point_radius,
self._canvas_half_width - self._center_point_radius,
self._canvas_half_width + self._center_point_radius,
self._canvas_half_width + self._center_point_radius,
fill='black',
)
# Create joystick
self.joystick = self.canvas.create_oval(
self._canvas_half_width - self._joystick_radius,
self._canvas_half_width - self._joystick_radius,
self._canvas_half_width + self._joystick_radius,
self._canvas_half_width + self._joystick_radius,
fill='green',
)
def _recenter_joystick(self):
"""Move the joystick to the center."""
new_coords = [
self._canvas_half_width - self._joystick_radius,
self._canvas_half_width - self._joystick_radius,
self._canvas_half_width + self._joystick_radius,
self._canvas_half_width + self._joystick_radius,
]
self.canvas.coords(self.joystick, new_coords)
def _place_joystick(self, event):
"""Place the joystick near the (x, y) coordinates of a mouse event.
If the event (x, y) is inside the motion zone, the joystick is placed
directly at that position. If it is outside the motion zone, the
joystick is placed on the edge of the motion zone nearest to that point.
"""
centered_event_coords = (
np.array([event.x, event.y], dtype=float) - self._canvas_half_width)
event_dist = np.linalg.norm(centered_event_coords)
rescale_factor = min(1, self._motion_zone_radius / event_dist)
centered_event_coords *= rescale_factor
event_coords = centered_event_coords + self._canvas_half_width
event_coords = event_coords.astype(int)
new_coords = [
event_coords[0] - self._joystick_radius,
event_coords[1] - self._joystick_radius,
event_coords[0] + self._joystick_radius,
event_coords[1] + self._joystick_radius,
]
self.canvas.coords(self.joystick, new_coords)
def _mouse_press(self, event):
self._place_joystick(event)
self._mouse_is_pressed = True
def _mouse_release(self, event):
self._mouse_is_pressed = False
self._recenter_joystick()
def _mouse_move(self, event):
if self._mouse_is_pressed:
self._place_joystick(event)
@property
def action(self):
"""Return the joystick's position as an action in [-1, 1] x [-1, 1]."""
joystick_coords = self.canvas.coords(self.joystick)
joystick_center = np.array([
joystick_coords[0] + self._joystick_radius,
joystick_coords[1] + self._joystick_radius
])
joystick_center -= self._canvas_half_width
action = joystick_center.astype(float) / self._motion_zone_radius
return np.array([action[0], -1 * action[1]])
class GridActions(tk.Frame):
"""Grid actions Tkinter frame.
This creates an empty Tkinter frame where the joystick would be. It also
registers bindings responding to arrow key presses and releases, and turns
them into discrete actions for a Grid action space.
"""
def __init__(self, root, canvas_half_width=100):
"""Constructor.
Args:
root: Instance of tk.Frame. Root frame in which the gui frame lives.
canvas_half_width: Int. Half of the width of the canvas to create.
"""
super(GridActions, self).__init__(root)
self._current_key = 4 # Do-nothing action
# Create a canvas
self.canvas = tk.Canvas(
width=2 * canvas_half_width,
height=2 * canvas_half_width)
# Add bindings for key presses and releases
root.bind('<KeyPress>', self._key_press)
root.bind('<KeyRelease>', self._key_release)
def _get_action_from_event(self, event):
if event.keysym == 'Left':
return 0
elif event.keysym == 'Right':
return 1
elif event.keysym == 'Down':
return 2
elif event.keysym == 'Up':
return 3
else:
return None
def _key_press(self, event):
self._current_key = self._get_action_from_event(event)
def _key_release(self, event):
if self._get_action_from_event(event) == self._current_key:
self._current_key = None
@property
def action(self):
if self._current_key is not None:
return self._current_key
else:
return 4 # Do-nothing action
class SetPositionFrame():
"""SetPosition Tkinter frame.
This creates position_setting functionality for a canvas. Typically this is
done to the HumanAgent._env_canvas.
"""
def __init__(self, canvas, canvas_half_width):
"""Constructor.
Args:
canvas: Canvas object to add position-setting functionality to.
canvas_half_width: Int. Half-width of the canvas.
"""
# Add bindings for clicking, dragging and releasing the joystick
canvas.bind('<ButtonPress-1>', self._mouse_press)
canvas.bind('<ButtonRelease-1>', self._mouse_release)
canvas.bind('<B1-Motion>', self._mouse_move)
self._canvas_half_width = canvas_half_width
self._mouse_is_pressed = False
self._mouse_coords = np.array([0.5, 0.5])
def _mouse_press(self, event):
self._place_mouse(event)
self._mouse_is_pressed = True
def _mouse_release(self, event):
self._mouse_is_pressed = False
def _mouse_move(self, event):
if self._mouse_is_pressed:
self._place_mouse(event)
def _place_mouse(self, event):
"""Place the self._mouse_coords (x, y) coordinates of a mouse event."""
centered_event_coords = (
np.array([event.x, event.y], dtype=float) - self._canvas_half_width)
centered_event_coords = np.clip(
centered_event_coords,
-self._canvas_half_width,
self._canvas_half_width,
)
self._mouse_coords = 0.5 * (
1 + centered_event_coords.astype(float) / self._canvas_half_width)
@property
def action(self):
"""Return the mouse's position as an action in [0, 1] x [0, 1]."""
return np.array([self._mouse_coords[0], 1. - self._mouse_coords[1]])
class TwoPlayerGridActions(tk.Frame):
"""2-player grid actions Tkinter frame.
This creates an empty Tkinter frame where the joystick would be. It also
registers bindings responding to arrow key presses and releases, and turns
them into discrete actions for a two-player Grid action space.
One player uses the [Left, Right, Down, Up] arrow keys and the other player
uses the [a, d, s, w] keys.
"""
def __init__(self, root, canvas_half_width=100, player_0='', player_1=''):
"""Constructor.
Args:
root: Instance of tk.Frame. Root frame in which the gui frame lives.
canvas_half_width: Int. Half of the width of the canvas to create.
player_0: String. Name of player_0. This will be the key in the
action dictionary for player_0's action.
player_1: String. Name of player_1. This will be the key in the
action dictionary for player_1's action.
"""
super(TwoPlayerGridActions, self).__init__(root)
self._player_0 = player_0
self._player_1 = player_1
self._current_keys = {player_0: 4, player_1: 4} # Do-nothing action
# Create a canvas
self.canvas = tk.Canvas(
width=2 * canvas_half_width,
height=2 * canvas_half_width)
# Add bindings for key presses and releases
root.bind('<KeyPress>', self._key_press)
root.bind('<KeyRelease>', self._key_release)
def _get_action_from_event(self, event):
if event.keysym == 'Left':
return 0
elif event.keysym == 'Right':
return 1
elif event.keysym == 'Down':
return 2
elif event.keysym == 'Up':
return 3
elif event.keysym == 'a':
return 4
elif event.keysym == 'd':
return 5
elif event.keysym == 's':
return 6
elif event.keysym == 'w':
return 7
else:
return None
def _key_press(self, event):
current_key = self._get_action_from_event(event)
if current_key is None:
pass
elif current_key < 4:
self._current_keys[self._player_0] = current_key
else:
self._current_keys[self._player_1] = current_key - 4
def _key_release(self, event):
if (self._get_action_from_event(event) ==
self._current_keys[self._player_0]):
self._current_keys[self._player_0] = 4
elif (self._get_action_from_event(event) ==
self._current_keys[self._player_1] + 4):
self._current_keys[self._player_1] = 4
@property
def action(self):
return self._current_keys
class TwoPlayerJoystick(tk.Frame):
"""2-player joystick actions Tkinter frame.
This creates an empty Tkinter frame where the joystick would be. It also
registers bindings responding to arrow key presses and releases, and turns
them into joystick actions for a two-player Joystick action space.
One player uses the [Left, Right, Down, Up] arrow keys and the other player
uses the [a, d, s, w] keys.
"""
def __init__(self, root, canvas_half_width=100, player_0='', player_1=''):
"""Constructor.
Args:
root: Instance of tk.Frame. Root frame in which the gui frame lives.
canvas_half_width: Int. Half of the width of the canvas to create.
player_0: String. Name of player_0. This will be the key in the
action dictionary for player_0's action.
player_1: String. Name of player_1. This will be the key in the
action dictionary for player_1's action.
"""
super(TwoPlayerJoystick, self).__init__(root)
self._player_0 = player_0
self._player_1 = player_1
self._current_action = {
player_0: np.array([0.,0.]),
player_1: np.array([0.,0.]),
}
self._current_keys = {
player_0: [0.,0.,0.,0.],
player_1: [0.,0.,0.,0.],
}
# Create a canvas
self.canvas = tk.Canvas(
width=2 * canvas_half_width,
height=2 * canvas_half_width)
# Add bindings for key presses and releases
root.bind('<KeyPress>', self._key_press)
root.bind('<KeyRelease>', self._key_release)
def _key_press(self, event):
if event.keysym == 'Left':
self._current_keys[self._player_0][0] = 1.
elif event.keysym == 'Right':
self._current_keys[self._player_0][1] = 1.
elif event.keysym == 'Down':
self._current_keys[self._player_0][2] = 1.
elif event.keysym == 'Up':
self._current_keys[self._player_0][3] = 1.
elif event.keysym == 'a' or event.keysym == 'Meta_L':
self._current_keys[self._player_1][0] = 1.
elif event.keysym == 'd' or event.keysym == 'Alt_L':
self._current_keys[self._player_1][1] = 1.
elif event.keysym == 's':
self._current_keys[self._player_1][2] = 1.
elif event.keysym == 'w':
self._current_keys[self._player_1][3] = 1.
for k, v in self._current_keys.items():
self._current_action[k] = np.array([v[1]-v[0],v[3]-v[2]])
def _key_release(self, event):
if event.keysym == 'Left':
self._current_keys[self._player_0][0] = 0.
elif event.keysym == 'Right':
self._current_keys[self._player_0][1] = 0.
elif event.keysym == 'Down':
self._current_keys[self._player_0][2] = 0.
elif event.keysym == 'Up':
self._current_keys[self._player_0][3] = 0.
elif event.keysym == 'a' or event.keysym == 'Meta_L':
self._current_keys[self._player_1][0] = 0.
elif event.keysym == 'd' or event.keysym == 'Alt_L':
self._current_keys[self._player_1][1] = 0.
elif event.keysym == 's':
self._current_keys[self._player_1][2] = 0.
elif event.keysym == 'w':
self._current_keys[self._player_1][3] = 0.
for k, v in self._current_keys.items():
self._current_action[k] = np.array([v[1]-v[0],v[3]-v[2]])
@property
def action(self):
return self._current_action
Classes
class GridActions (root, canvas_half_width=100)
-
Grid actions Tkinter frame.
This creates an empty Tkinter frame where the joystick would be. It also registers bindings responding to arrow key presses and releases, and turns them into discrete actions for a Grid action space.
Constructor.
Args
root
- Instance of tk.Frame. Root frame in which the gui frame lives.
canvas_half_width
- Int. Half of the width of the canvas to create.
Expand source code
class GridActions(tk.Frame): """Grid actions Tkinter frame. This creates an empty Tkinter frame where the joystick would be. It also registers bindings responding to arrow key presses and releases, and turns them into discrete actions for a Grid action space. """ def __init__(self, root, canvas_half_width=100): """Constructor. Args: root: Instance of tk.Frame. Root frame in which the gui frame lives. canvas_half_width: Int. Half of the width of the canvas to create. """ super(GridActions, self).__init__(root) self._current_key = 4 # Do-nothing action # Create a canvas self.canvas = tk.Canvas( width=2 * canvas_half_width, height=2 * canvas_half_width) # Add bindings for key presses and releases root.bind('<KeyPress>', self._key_press) root.bind('<KeyRelease>', self._key_release) def _get_action_from_event(self, event): if event.keysym == 'Left': return 0 elif event.keysym == 'Right': return 1 elif event.keysym == 'Down': return 2 elif event.keysym == 'Up': return 3 else: return None def _key_press(self, event): self._current_key = self._get_action_from_event(event) def _key_release(self, event): if self._get_action_from_event(event) == self._current_key: self._current_key = None @property def action(self): if self._current_key is not None: return self._current_key else: return 4 # Do-nothing action
Ancestors
- tkinter.Frame
- tkinter.Widget
- tkinter.BaseWidget
- tkinter.Misc
- tkinter.Pack
- tkinter.Place
- tkinter.Grid
Instance variables
var action
-
Expand source code
@property def action(self): if self._current_key is not None: return self._current_key else: return 4 # Do-nothing action
class JoystickFrame (root, canvas_half_width=100, motion_zone_radius=90, joystick_radius=10, center_point_radius=3)
-
Joystick Tkinter frame.
This creates the frame for an interactive joystick. The joystick consists of three objects: (i) A large gray "motion zone" circle in the background. This is the area in which the joystick can be moved. (ii) A small black "center point" circle fixed in the middle ground. This indicates the joystick position that give zero action. (iii) A green "joystick" circle in the foreground that can be moved. The center of this circle is the action readout.
If the mouse is not clicked, then position of the joystick centerpoint is 0 (in the center of the motion zone). If the mouse is currently pressed, then the position of the joystick is the closest point in the motion zone to the mouse position. Namely, if the mouse is in the motion zone then the joystick is directly under the mouse, and if the mouse is not in the motion zone then the joystick is at the edge of the motion zone closest to the mouse.
Thus the joystick can be moved by clicking the mouse anywhere (in which case the joystick jumps to that position) and dragging the pressed mouse around (in which case the joystick moves underneath the mouse).
Constructor.
Args
root
- Instance of tk.Frame. Root frame in which the joystick lives.
canvas_half_width
- Int. Half of the width of the canvas on which the joystick is rendered.
motion_zone_radius
- Int. Radius of the motion zone.
joystick_radius
- Int. Radius of the joystick.
center_point_radius
- Int. Radius of the center point.
Expand source code
class JoystickFrame(tk.Frame): """Joystick Tkinter frame. This creates the frame for an interactive joystick. The joystick consists of three objects: (i) A large gray "motion zone" circle in the background. This is the area in which the joystick can be moved. (ii) A small black "center point" circle fixed in the middle ground. This indicates the joystick position that give zero action. (iii) A green "joystick" circle in the foreground that can be moved. The center of this circle is the action readout. If the mouse is not clicked, then position of the joystick centerpoint is 0 (in the center of the motion zone). If the mouse is currently pressed, then the position of the joystick is the closest point in the motion zone to the mouse position. Namely, if the mouse is in the motion zone then the joystick is directly under the mouse, and if the mouse is not in the motion zone then the joystick is at the edge of the motion zone closest to the mouse. Thus the joystick can be moved by clicking the mouse anywhere (in which case the joystick jumps to that position) and dragging the pressed mouse around (in which case the joystick moves underneath the mouse). """ def __init__(self, root, canvas_half_width=100, motion_zone_radius=90, joystick_radius=10, center_point_radius=3): """Constructor. Args: root: Instance of tk.Frame. Root frame in which the joystick lives. canvas_half_width: Int. Half of the width of the canvas on which the joystick is rendered. motion_zone_radius: Int. Radius of the motion zone. joystick_radius: Int. Radius of the joystick. center_point_radius: Int. Radius of the center point. """ super(JoystickFrame, self).__init__(root) self._joystick_radius = joystick_radius self._canvas_half_width = canvas_half_width self._motion_zone_radius = motion_zone_radius self._center_point_radius = center_point_radius # Create a canvas self.canvas = tk.Canvas( width=2 * canvas_half_width, height=2 * canvas_half_width) # Create motion zone, center point, and joystick self._create_items() # Add bindings for clicking, dragging and releasing the joystick self.canvas.bind('<ButtonPress-1>', self._mouse_press) self.canvas.bind('<ButtonRelease-1>', self._mouse_release) self.canvas.bind('<B1-Motion>', self._mouse_move) self._mouse_is_pressed = False def _create_items(self): # Create motion zone self.canvas.create_oval( self._canvas_half_width - self._motion_zone_radius, self._canvas_half_width - self._motion_zone_radius, self._canvas_half_width + self._motion_zone_radius, self._canvas_half_width + self._motion_zone_radius, fill='gray80', ) # Create center point self.canvas.create_oval( self._canvas_half_width - self._center_point_radius, self._canvas_half_width - self._center_point_radius, self._canvas_half_width + self._center_point_radius, self._canvas_half_width + self._center_point_radius, fill='black', ) # Create joystick self.joystick = self.canvas.create_oval( self._canvas_half_width - self._joystick_radius, self._canvas_half_width - self._joystick_radius, self._canvas_half_width + self._joystick_radius, self._canvas_half_width + self._joystick_radius, fill='green', ) def _recenter_joystick(self): """Move the joystick to the center.""" new_coords = [ self._canvas_half_width - self._joystick_radius, self._canvas_half_width - self._joystick_radius, self._canvas_half_width + self._joystick_radius, self._canvas_half_width + self._joystick_radius, ] self.canvas.coords(self.joystick, new_coords) def _place_joystick(self, event): """Place the joystick near the (x, y) coordinates of a mouse event. If the event (x, y) is inside the motion zone, the joystick is placed directly at that position. If it is outside the motion zone, the joystick is placed on the edge of the motion zone nearest to that point. """ centered_event_coords = ( np.array([event.x, event.y], dtype=float) - self._canvas_half_width) event_dist = np.linalg.norm(centered_event_coords) rescale_factor = min(1, self._motion_zone_radius / event_dist) centered_event_coords *= rescale_factor event_coords = centered_event_coords + self._canvas_half_width event_coords = event_coords.astype(int) new_coords = [ event_coords[0] - self._joystick_radius, event_coords[1] - self._joystick_radius, event_coords[0] + self._joystick_radius, event_coords[1] + self._joystick_radius, ] self.canvas.coords(self.joystick, new_coords) def _mouse_press(self, event): self._place_joystick(event) self._mouse_is_pressed = True def _mouse_release(self, event): self._mouse_is_pressed = False self._recenter_joystick() def _mouse_move(self, event): if self._mouse_is_pressed: self._place_joystick(event) @property def action(self): """Return the joystick's position as an action in [-1, 1] x [-1, 1].""" joystick_coords = self.canvas.coords(self.joystick) joystick_center = np.array([ joystick_coords[0] + self._joystick_radius, joystick_coords[1] + self._joystick_radius ]) joystick_center -= self._canvas_half_width action = joystick_center.astype(float) / self._motion_zone_radius return np.array([action[0], -1 * action[1]])
Ancestors
- tkinter.Frame
- tkinter.Widget
- tkinter.BaseWidget
- tkinter.Misc
- tkinter.Pack
- tkinter.Place
- tkinter.Grid
Instance variables
var action
-
Return the joystick's position as an action in [-1, 1] x [-1, 1].
Expand source code
@property def action(self): """Return the joystick's position as an action in [-1, 1] x [-1, 1].""" joystick_coords = self.canvas.coords(self.joystick) joystick_center = np.array([ joystick_coords[0] + self._joystick_radius, joystick_coords[1] + self._joystick_radius ]) joystick_center -= self._canvas_half_width action = joystick_center.astype(float) / self._motion_zone_radius return np.array([action[0], -1 * action[1]])
class SetPositionFrame (canvas, canvas_half_width)
-
SetPosition Tkinter frame.
This creates position_setting functionality for a canvas. Typically this is done to the HumanAgent._env_canvas.
Constructor.
Args
canvas
- Canvas object to add position-setting functionality to.
canvas_half_width
- Int. Half-width of the canvas.
Expand source code
class SetPositionFrame(): """SetPosition Tkinter frame. This creates position_setting functionality for a canvas. Typically this is done to the HumanAgent._env_canvas. """ def __init__(self, canvas, canvas_half_width): """Constructor. Args: canvas: Canvas object to add position-setting functionality to. canvas_half_width: Int. Half-width of the canvas. """ # Add bindings for clicking, dragging and releasing the joystick canvas.bind('<ButtonPress-1>', self._mouse_press) canvas.bind('<ButtonRelease-1>', self._mouse_release) canvas.bind('<B1-Motion>', self._mouse_move) self._canvas_half_width = canvas_half_width self._mouse_is_pressed = False self._mouse_coords = np.array([0.5, 0.5]) def _mouse_press(self, event): self._place_mouse(event) self._mouse_is_pressed = True def _mouse_release(self, event): self._mouse_is_pressed = False def _mouse_move(self, event): if self._mouse_is_pressed: self._place_mouse(event) def _place_mouse(self, event): """Place the self._mouse_coords (x, y) coordinates of a mouse event.""" centered_event_coords = ( np.array([event.x, event.y], dtype=float) - self._canvas_half_width) centered_event_coords = np.clip( centered_event_coords, -self._canvas_half_width, self._canvas_half_width, ) self._mouse_coords = 0.5 * ( 1 + centered_event_coords.astype(float) / self._canvas_half_width) @property def action(self): """Return the mouse's position as an action in [0, 1] x [0, 1].""" return np.array([self._mouse_coords[0], 1. - self._mouse_coords[1]])
Instance variables
var action
-
Return the mouse's position as an action in [0, 1] x [0, 1].
Expand source code
@property def action(self): """Return the mouse's position as an action in [0, 1] x [0, 1].""" return np.array([self._mouse_coords[0], 1. - self._mouse_coords[1]])
class TwoPlayerGridActions (root, canvas_half_width=100, player_0='', player_1='')
-
2-player grid actions Tkinter frame.
This creates an empty Tkinter frame where the joystick would be. It also registers bindings responding to arrow key presses and releases, and turns them into discrete actions for a two-player Grid action space.
One player uses the [Left, Right, Down, Up] arrow keys and the other player uses the [a, d, s, w] keys.
Constructor.
Args
root
- Instance of tk.Frame. Root frame in which the gui frame lives.
canvas_half_width
- Int. Half of the width of the canvas to create.
player_0
- String. Name of player_0. This will be the key in the action dictionary for player_0's action.
player_1
- String. Name of player_1. This will be the key in the action dictionary for player_1's action.
Expand source code
class TwoPlayerGridActions(tk.Frame): """2-player grid actions Tkinter frame. This creates an empty Tkinter frame where the joystick would be. It also registers bindings responding to arrow key presses and releases, and turns them into discrete actions for a two-player Grid action space. One player uses the [Left, Right, Down, Up] arrow keys and the other player uses the [a, d, s, w] keys. """ def __init__(self, root, canvas_half_width=100, player_0='', player_1=''): """Constructor. Args: root: Instance of tk.Frame. Root frame in which the gui frame lives. canvas_half_width: Int. Half of the width of the canvas to create. player_0: String. Name of player_0. This will be the key in the action dictionary for player_0's action. player_1: String. Name of player_1. This will be the key in the action dictionary for player_1's action. """ super(TwoPlayerGridActions, self).__init__(root) self._player_0 = player_0 self._player_1 = player_1 self._current_keys = {player_0: 4, player_1: 4} # Do-nothing action # Create a canvas self.canvas = tk.Canvas( width=2 * canvas_half_width, height=2 * canvas_half_width) # Add bindings for key presses and releases root.bind('<KeyPress>', self._key_press) root.bind('<KeyRelease>', self._key_release) def _get_action_from_event(self, event): if event.keysym == 'Left': return 0 elif event.keysym == 'Right': return 1 elif event.keysym == 'Down': return 2 elif event.keysym == 'Up': return 3 elif event.keysym == 'a': return 4 elif event.keysym == 'd': return 5 elif event.keysym == 's': return 6 elif event.keysym == 'w': return 7 else: return None def _key_press(self, event): current_key = self._get_action_from_event(event) if current_key is None: pass elif current_key < 4: self._current_keys[self._player_0] = current_key else: self._current_keys[self._player_1] = current_key - 4 def _key_release(self, event): if (self._get_action_from_event(event) == self._current_keys[self._player_0]): self._current_keys[self._player_0] = 4 elif (self._get_action_from_event(event) == self._current_keys[self._player_1] + 4): self._current_keys[self._player_1] = 4 @property def action(self): return self._current_keys
Ancestors
- tkinter.Frame
- tkinter.Widget
- tkinter.BaseWidget
- tkinter.Misc
- tkinter.Pack
- tkinter.Place
- tkinter.Grid
Instance variables
var action
-
Expand source code
@property def action(self): return self._current_keys
class TwoPlayerJoystick (root, canvas_half_width=100, player_0='', player_1='')
-
2-player joystick actions Tkinter frame.
This creates an empty Tkinter frame where the joystick would be. It also registers bindings responding to arrow key presses and releases, and turns them into joystick actions for a two-player Joystick action space.
One player uses the [Left, Right, Down, Up] arrow keys and the other player uses the [a, d, s, w] keys.
Constructor.
Args
root
- Instance of tk.Frame. Root frame in which the gui frame lives.
canvas_half_width
- Int. Half of the width of the canvas to create.
player_0
- String. Name of player_0. This will be the key in the action dictionary for player_0's action.
player_1
- String. Name of player_1. This will be the key in the action dictionary for player_1's action.
Expand source code
class TwoPlayerJoystick(tk.Frame): """2-player joystick actions Tkinter frame. This creates an empty Tkinter frame where the joystick would be. It also registers bindings responding to arrow key presses and releases, and turns them into joystick actions for a two-player Joystick action space. One player uses the [Left, Right, Down, Up] arrow keys and the other player uses the [a, d, s, w] keys. """ def __init__(self, root, canvas_half_width=100, player_0='', player_1=''): """Constructor. Args: root: Instance of tk.Frame. Root frame in which the gui frame lives. canvas_half_width: Int. Half of the width of the canvas to create. player_0: String. Name of player_0. This will be the key in the action dictionary for player_0's action. player_1: String. Name of player_1. This will be the key in the action dictionary for player_1's action. """ super(TwoPlayerJoystick, self).__init__(root) self._player_0 = player_0 self._player_1 = player_1 self._current_action = { player_0: np.array([0.,0.]), player_1: np.array([0.,0.]), } self._current_keys = { player_0: [0.,0.,0.,0.], player_1: [0.,0.,0.,0.], } # Create a canvas self.canvas = tk.Canvas( width=2 * canvas_half_width, height=2 * canvas_half_width) # Add bindings for key presses and releases root.bind('<KeyPress>', self._key_press) root.bind('<KeyRelease>', self._key_release) def _key_press(self, event): if event.keysym == 'Left': self._current_keys[self._player_0][0] = 1. elif event.keysym == 'Right': self._current_keys[self._player_0][1] = 1. elif event.keysym == 'Down': self._current_keys[self._player_0][2] = 1. elif event.keysym == 'Up': self._current_keys[self._player_0][3] = 1. elif event.keysym == 'a' or event.keysym == 'Meta_L': self._current_keys[self._player_1][0] = 1. elif event.keysym == 'd' or event.keysym == 'Alt_L': self._current_keys[self._player_1][1] = 1. elif event.keysym == 's': self._current_keys[self._player_1][2] = 1. elif event.keysym == 'w': self._current_keys[self._player_1][3] = 1. for k, v in self._current_keys.items(): self._current_action[k] = np.array([v[1]-v[0],v[3]-v[2]]) def _key_release(self, event): if event.keysym == 'Left': self._current_keys[self._player_0][0] = 0. elif event.keysym == 'Right': self._current_keys[self._player_0][1] = 0. elif event.keysym == 'Down': self._current_keys[self._player_0][2] = 0. elif event.keysym == 'Up': self._current_keys[self._player_0][3] = 0. elif event.keysym == 'a' or event.keysym == 'Meta_L': self._current_keys[self._player_1][0] = 0. elif event.keysym == 'd' or event.keysym == 'Alt_L': self._current_keys[self._player_1][1] = 0. elif event.keysym == 's': self._current_keys[self._player_1][2] = 0. elif event.keysym == 'w': self._current_keys[self._player_1][3] = 0. for k, v in self._current_keys.items(): self._current_action[k] = np.array([v[1]-v[0],v[3]-v[2]]) @property def action(self): return self._current_action
Ancestors
- tkinter.Frame
- tkinter.Widget
- tkinter.BaseWidget
- tkinter.Misc
- tkinter.Pack
- tkinter.Place
- tkinter.Grid
Instance variables
var action
-
Expand source code
@property def action(self): return self._current_action