简体   繁体   中英

How to add dash function with vectors

In my 2D (top-down) game, I am attempting to add a dash function.

Using an if (keyWentDown("e")) {} condition inside a function named dash . I have a thing set up to face the player's direction, being: plrvector.rotation = 90 , and I want my character to move about 50px smoothly when E is pressed.

Problem is, I have no clue how to use vectors. Any tips or directions? I have attempted to use various techniques; however, I could not find any tutorials or anything that could help me.

I am not sure you want to move the player exactly 50px. You would just temporarily increase the velocity by a factor. In the example below, if the E key is pressed, a "turbo" mode is activate increasing the speed by a factor of 3.

You would have to do something along the lines of:

function update(progress) {
  const { player } = state;
  const turbo = state.pressedKeys.turbo ? 3 : 1; // x3 speed (E)

  if (state.pressedKeys.left) {
    if (player.speed.x > 0) player.speed.x *= -1;
    player.position.x += progress * player.speed.x * turbo;
  }
}

Note: This can be modified to only allow turbo for a short duration. For instance, the player may have a turbo meter that they need to fill in order to use this mode.

The following example is adapted from: "Quick Tip: How to Make a Game Loop in JavaScript" . I did not utilize vectors pre se , but I store the position and velocity (speed) in a vector-like object. If you want to convert this to vectors, you can check out victor.js . It can easily add/multiply/normalize vectors for you.

 // Canvas context reference const ctx = document.querySelector('#game').getContext('2d'); const hud = document.querySelector('#hud'); // Set the canvas size Object.assign(ctx.canvas, { width: 600, height: 160 }); // Game state const state = { player: { dimensions: { depth: 10, height: 10, width: 10 }, position: { x: Math.floor(ctx.canvas.width / 2), y: Math.floor(ctx.canvas.height / 2) }, speed: { x: 0.25, y: 0.25 } }, pressedKeys: { left: false, right: false, turbo: false, up: false, down: false } }; // Track keys const keyMap = new Map(Object.entries({ ArrowDown: 'down', ArrowLeft: 'left', ArrowRight: 'right', ArrowUp: 'up', a: 'left', d: 'right', e: 'turbo', s: 'down', w: 'up', })); // Game Loop ~ Update function update(progress) { const { player } = state; hud.innerText = Object.entries(state.pressedKeys).filter(([k, v]) => v).map(([k]) => `<${k}>`).sort().join(' '); const turbo = state.pressedKeys.turbo? 3: 1; // x3 speed (E) // Check pressed keys to update position if (state.pressedKeys.left) { if (player.speed.x > 0) player.speed.x *= -1; player.position.x += progress * player.speed.x * turbo; } if (state.pressedKeys.right) { if (player.speed.x < 0) player.speed.x *= -1; player.position.x += progress * player.speed.x * turbo; } if (state.pressedKeys.up) { if (player.speed.y > 0) player.speed.y *= -1; player.position.y += progress * player.speed.y * turbo; } if (state.pressedKeys.down) { if (player.speed.y < 0) player.speed.y *= -1; player.position.y += progress * player.speed.y * turbo; } // Check bounds const threshold = player.dimensions.width; if (player.position.x > ctx.canvas.width - threshold) { player.position.x = ctx.canvas.width - threshold; } else if (player.position.x < threshold) { player.position.x = threshold; } if (player.position.y > ctx.canvas.height - threshold) { player.position.y = ctx.canvas.height - threshold; } else if (player.position.y < threshold) { player.position.y = threshold; } } // Game Loop ~ Draw function draw() { const { player, pressedKeys } = state; ctx.fillStyle = 'black'; ctx.beginPath(); ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); ctx.closePath(); ctx.fillStyle = 'red'; ctx.beginPath(); ctx.arc(player.position.x, player.position.y, player.dimensions.width, 0, 2 * Math.PI); ctx.fill(); ctx.closePath(); } // Game Loop ~ Main function loop(timestamp) { const progress = timestamp - lastRender; update(progress); draw(); lastRender = timestamp; window.requestAnimationFrame(loop); } // Begin game let lastRender = 0; window.requestAnimationFrame(loop); // Register keyboard events window.addEventListener('keydown', onKeyDown, false); window.addEventListener('keyup', onKeyUp, false); // Event handlers function onKeyDown({ key }) { toggleKey(key, true); } function onKeyUp({ key }) { toggleKey(key, false); } // Convenience function toggleKey(key, value) { const index = keyMap.get(key); if (index) { const currentValue = state.pressedKeys[index]; state.pressedKeys[index] = value?? ;currentValue; } }
 *, *::before,*::after { box-sizing: border-box; } html, body { width: 100%; height: 100%; margin: 0; padding: 0; } body { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 0.25em; padding: 0.25em; } #hud { white-space: pre; text-transform: uppercase; }
 <:-- See: https.//www.sitepoint.com/quick-tip-game-loop-in-javascript/ --> <canvas id="game"></canvas> <div id="hud"></div>


Vector math

Here is an example of adding/multiplying vectors:

  1. Add t and u to get { x: 4, y: 7 }
  2. Multiply the result above by t to get { x: 4, y: 14 }

 const vectorAdd = (a, b) => ({ x: ax + bx, y: ay + by }); const vectorMultiply = (a, b) => ({ x: ax * bx, y: ay * by }); let t = { x: 1, y: 2 }, u = { x: 3, y: 5 }, v = vectorMultiply(vectorAdd(t, u), t); console.log(v); // { x: 4, y: 14 }

If you want to chain these calls, you can try creating a wrapper:

 const vectorAdd = (a, b) => ({ x: ax + bx, y: ay + by }); const vectorMultiply = (a, b) => ({ x: ax * bx, y: ay * by }); const vector = function({ x, y }) { [this.x, this.y] = [x, y]; this.add = (other) => { const { x, y } = vectorAdd(this, other); [this.x, this.y] = [x, y]; return this; }; this.multiply = (other) => { const { x, y } = vectorMultiply(this, other); [this.x, this.y] = [x, y]; return this; }; this.value = () => ({ x: this.x, y: this.y }); return this; } let t = { x: 1, y: 2 }, u = { x: 3, y: 5 }, v = vector(t).add(u).multiply(t).value(); console.log(v); // { x: 4, y: 14 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM