process input (v2)

Revision 2 of this benchmark created on


Setup

function moveForward(distance) {
 
}

class Vector3 {
	x = 0
	y = 0
	z = 0
	
	constructor(x,y,z) {
		this.x = x
		this.y = y
		this.z = z
	}
}

class KeyState {
  eventCount= 0;

  constructor(
    rawValue,
    value,
    isPressed = false,
    isConsumed = false
  ) {}
}

class InputAxisMap {
  constructor(
    name,
    key,
    scale
  ) {}
}

class InputBinding {
  consumeInput = false;
  executeWhenPaused = false;
}

class InputAxisBinding extends InputBinding {
  constructor(
    name,
    handle,
    value = 0
  ) {
    super();
  }
}

const keyStates = new Map();
const axisKeyMap = new Map();
const axisMappings = [];
const axisBindings = [];
const axisKeyBindings = [];

axisMappings.push(new InputAxisMap("MoveForward", "KeyS", -1));
axisMappings.push(new InputAxisMap("MoveForward", "KeyW", 1));

axisBindings.push(new InputAxisBinding("MoveForward", moveForward));

function processInput1() {
  const axisBindingsToExec = [];
  const keysWithEvents = new Set();

  for (const [key, keyState] of keyStates) {
    if (keyState.eventCount > 0) {
      keysWithEvents.add(key);
    }

    // Create axis key map
    const keyMappings = [];

    // Create axis key map
    for (const axisMap of axisMappings) {
      if (axisMap.key === key) {
        keyMappings.push(axisMap);
      }
    }

    axisKeyMap.set(key, keyMappings);
  }

  // Axis Bindings
  for (const key of keysWithEvents) {
    const mappings = axisKeyMap.get(key);
    const keyState = keyStates.get(key);

	if (keyState.eventCount === 0) continue

    if (keyState?.isPressed) {
    //if (keyState?.isPressed && keyState.eventCount > 0) {
      if (mappings) {
        for (const axisMapping of mappings) {
          for (const axisBinding of axisBindings) {
            if (axisBinding.name !== axisMapping.name) continue;

            axisBinding.value = keyState.value.x * axisMapping.scale;
            axisBindingsToExec.push(axisBinding);
          }
        }
      }
      
      keyState.eventCount = 0;
    }
  }

  for (const axisBinding of axisBindingsToExec) {
    axisBinding.handle(axisBinding.value);
    axisBinding.value = 0;
  }
}

function processInput2() {
  const axisBindingsToExec = [];
  const keysWithEvents = new Set();

  for (const [key, keyState] of keyStates) {
    if (keyState.eventCount > 0) {
      keysWithEvents.add(key);
    }

    axisKeyMap.set(key, []);

    // Create axis key map
    for (const axisMap of axisMappings) {
      const keyMappings = axisKeyMap.get(axisMap.key);

      if (axisMap.key === key) {
        keyMappings.push(axisMap);
      }
    }
  }
  
  for (const [key, keyState] of keyStates) {
    if (keyState.eventCount === 0) continue;

    for (const axisMap of axisMappings) {
      for (const axisBinding of axisBindings) {
        if (
          keyState.isPressed &&
          axisMap.key === key &&
          axisMap.name === axisBinding.name
        ) {
          axisBinding.value = keyState.value.x * axisMap.scale;
          axisBindingsToExec.push(axisBinding);
        }
      }
    }

    keyState.eventCount = 0;
  }

  for (const axisBinding of axisBindingsToExec) {
    axisBinding.handle(axisBinding.value);
    axisBinding.value = 0;
  }
}

Test runner

Ready to run.

Testing in
TestOps/sec
processInput1
(() => {
	let keyState = keyStates.get("KeyW");
  	const val = new Vector3(1, 0, 0);

  if (!keyState) {
    keyState = new KeyState(val, val);
    keyStates.set("KeyW", keyState);
  }

  keyState.isPressed = true;
  keyState.eventCount++;

  processInput1();
})()
ready
processInput2
(() => {
	let keyState = keyStates.get("KeyW");
  	const val = new Vector3(1, 0, 0);

  if (!keyState) {
    keyState = new KeyState(val, val);
    keyStates.set("KeyW", keyState);
  }

  keyState.isPressed = true;
  keyState.eventCount++;

  processInput2();
})()
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.