Skip to content

Instantly share code, notes, and snippets.

@osteele
Last active November 24, 2021 05:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save osteele/986252244a0e7973ca3ffe92f85fef18 to your computer and use it in GitHub Desktop.
Save osteele/986252244a0e7973ca3ffe92f85fef18 to your computer and use it in GitHub Desktop.
Demonstrate how to keep track of currently held keyboard keys in Processing
/*
* This sketch demonstrates how to keep track of which keyboard keys are held
* down (pressed, and not released). Multiple keys can be held at the same time
* (if a second key is pressed before the first key is released).
*
* The list of currently-held keys is printed to the console each time a key is
* pressed or released.
*
* Instructions:
* 1. Run the sketch.
* 2. Click on the sketch window to select it.
* 3. Press and release keyboard keys.
* 4. Watch the console.
* 5. Try pressing and releasing multiple keys.
*
* Things to try:
* - Draw different things on the canvas depending on what keys are currently
* held.
* - Change the properties of an object (shape, color, stroke width) or the
* canvas (scale, translation, rotation) depending on what keys are currently
* held.
* - Can you design a two-player game where one player holds down one or more of
* QWERASDFZXCV and the other player uses UIOPJKL:NM<> ?
*
* The code can be modified to store values of `keyCode` instead of (or as well
* as) values of `key`.
*
* An alternative implementation, that uses `char[]` instead of `IntArray`, is
* available at https://gist.githubusercontent.com/osteele/54566a328c78cf12c000cbcea2e12a75
*
* Author: Oliver Steele
* Date: 2021-11-23
*/
/** A list of all the keyboard keys that are currently held (have been pressed
* but not released).
*
* We use an IntList instead of an Array of integers `int[]` or characters
* `char[]`, because we don't know how many keys might be pressed at once so we
* don't know how large to make the array.
*
* `key` is a `char`, not an `int`, but it can be stored in a list or array of
* ints.
*
* Some alternatives to using IntList:
* - Use an array that is large enough to hold all the keys in the keyboard,
* and keep track of how much of the array is used.
* - Use an array, and use append() and shorten() to add and remove values.
* This implementation is at https://gist.githubusercontent.com/osteele/54566a328c78cf12c000cbcea2e12a75
* - Use an array of `boolean`s to indicate whether a key is pressed or not.
*/
IntList heldKeys = new IntList();
void setup() {
size(100, 100);
}
// This sketch doesn't draw anything. However, if this function is not defined,
// Processing never calls keyPressed() or keyReleased().
void draw() {
}
void keyPressed() {
// Because keyPressed() is called repeatedly while a key is held down, in
// addition to when it is first pressed, heldKeys may already contain the key.
// In this case, don't add it a second time, and don't print to the console
// again.
if (!heldKeys.hasValue(key)) {
heldKeys.append(key);
heldKeys.sort(); // this is optional, but it makes the output easier to read
printHeldKeys();
}
}
void keyReleased() {
// It should always be the case that heldKeys contains key, but the
// conditional guard makes the code more robust in case this turns out not be
// true. (For example, what happens if the user is holding down some keys when
// the sketch starts running?)
if (heldKeys.hasValue(key)) {
intArrayListRemove(heldKeys, key);
printHeldKeys();
}
}
/** Print the currently pressed keys to the console. */
void printHeldKeys() {
print("Currently pressed keys: ");
var sep = "";
for (var c: heldKeys) {
print(sep);
print(char(c));
sep = " ";
}
if (heldKeys.size() == 0) {
print("none");
}
println();
}
/** Remove all occurrences of `value` from `arrayList`. If `arrayList` does not
* contain `value`, has no effect. */
void intArrayListRemove(IntList arrayList, int value) {
for (int i = 0; i < arrayList.size(); i++) {
if (arrayList.get(i) == value) {
arrayList.remove(i);
// Decrement the loop counter so that the next iteration looks at the
// value that follows the one that was removed. This following value is
// now in arrayList.get(i) (the same index that the removed item
// previously occupied).
//
// Without this special case, this function would only remove the first
// value from a list that contained two values in a row. In this
// particular program, this will never happen; however, a function with a
// generic name such as this one might get used in other program where
// this matters; or, someone might modify the code that uses this
// function, without noticing the issue.
i--;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment