6
$\begingroup$

I'm trying to make moving object using controls. I'm trying to do this using Buttons. The code is

diskPosition = {50, 50}; left = False; right = False; up = False; down = False;

Manipulate[
 Graphics[Dynamic[
   If[left, diskPosition[[1]] += -.01]; 
   If[right, diskPosition[[1]] += .01];
   If[up, diskPosition[[2]] += .01]; 
   If[down, diskPosition[[2]] += -.01];
   {Yellow, Disk[diskPosition, 3]}],
  PlotRange -> {{0, 100}, {0, 140}}, Background -> Black
  ],
 Row[{Button["\[LongLeftArrow]", left = True; 
    right = up = down = False], 
   Column[{Button["\[UpArrow]", up = True; 
      right = left = down = False],
     Button["\[DownArrow]", down = True; right = up = left = False]}],
    Button["\[LongRightArrow]", right = True; 
    left = up = down = False]}]
 ]

I wonder if I can use random keys on the keyboard? I know how to get "Shift", "Ctrl" and "Alt" with CurrentValue[] but not how to get random keys from keyboard. Some suggestions?

$\endgroup$

1 Answer 1

7
$\begingroup$

I'm not sure what you mean by "random keys." If you mean how to process any user keydown, then EventHandler and CurrentValue["EventKey"] might be what you're looking for. They can handle keydown events. Note that all rules that match the event are processed. Below for instance, if a "?" is pressed, diskPosition is set to a new random position and label is set to an empty string.

DynamicModule[{diskPosition = {50, 50}, diskRadius = 3, label = ""},
 EventHandler[
  Graphics[Dynamic[
    {Yellow, Disk[diskPosition, diskRadius], Darker@Red, 
     Text[label, diskPosition]}],
   PlotRange -> {{0, 100}, {0, 140}}, Background -> Black],
  {"LeftArrowKeyDown"  :> (diskPosition[[1]] += -.1),
   "RightArrowKeyDown" :> (diskPosition[[1]] += .1),
   "UpArrowKeyDown"    :> (diskPosition[[2]] += .1),
   "DownArrowKeyDown"  :> (diskPosition[[2]] += -.1),
   {"KeyDown", "?"}    :> (diskPosition = {RandomReal[{3, 100 - 3}], RandomReal[{3, 140 - 3}]}),
   "KeyDown"           :> With[{char = CurrentValue["EventKey"]},
                            If[LetterQ[char], label = char, 
                             If[DigitQ[char], diskRadius = FromDigits[char],
                                              label = ""]]]}
  ]]

(* optional *)
(SelectionMove[EvaluationNotebook[], Previous, Cell]; 
 SelectionMove[EvaluationNotebook[], Before, CellContents];
 SelectionMove[EvaluationNotebook[], Next, Character])

Note: The graphics needs to be focused on. The SelectionMove code accomplishes this programmatically, perhaps ungracefully. If the user clicks away from the graphics, then keys won't be processed (that is, the user won't be locked into playing with the yellow disk, but can go back to programming). Clicking on the graphics doesn't get it to listen to keydowns. Instead, click next to the graphics to the right of it and press the left arrow key. Perhaps there is a more graceful way to do this!?

Output after pressing "X"

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.