Made a function that moves the character in different directions, here is an example:

function handleInput() { window.addEventListener("keydown", function(event) { if (event.keyCode == 65) ractive.set({'playerX': ractive.get( 'playerX' ) - 1}); if (event.keyCode == 68) ractive.set({'playerX': ractive.get( 'playerX' ) + 1}); if (event.keyCode == 87) ractive.set({'playerY': ractive.get( 'playerY' ) - 1}); if (event.keyCode == 83) ractive.set({'playerY': ractive.get( 'playerY' ) + 1}); }); 

I will not go into details, the example shows that the movement takes place at the keyDown event - so when you press and hold the key, the player first moves by 1 pixel, and only then - after a split second - continues to move on, I don’t know if you can decide problem, but this implementation seems to me not quite true. How to properly implement the movement of the sprite? Can someone have links to useful articles on this?

  • I recommend not reinventing bicycles right away, but switching to one of the frameworks for developing games on js .... for example, on the phaser .... and here’s the popular html5gameengine.com - Alexey Shimansky
  • eight
    I recommend reinventing bicycles in order to understand how games are made, and in order for someone (I) to tell you, for example about habrahabr.ru/post/131931 , so that you don’t invent mathematical bicycles from scratch - strangeqargo
  • one
    @strangeqargo and not yet write in an existing programming language, but make your own, to begin with, to understand how programming languages ​​work and are done. And then on it to make games ....... nonsense - Alexei Shimansky
  • one
    In any case, the movement must be done through vectors, and bypassing the obstacles through the libu can either simply rewrite algorithm A * or Dijkstra from Wikipedia. And for turning into js, ​​it is convenient to use atan2 - Serge Esmanovich
  • one
    jsfiddle.net/181g794f Here is an example, from this question ru.stackoverflow.com/questions/446817/… But it needs to be slightly corrected, there the normal vector needs to be added, otherwise the diagonal speed is greater - Serge Esmanovich

3 answers 3

Asked to write the answer here. In general, there are a lot of jambs too lazy to edit everything, he hastily wrote mainly paste-paste from the example he wrote in the comments, so there are many duplicate methods and variables, but I’m kind of at work so excuse me =)

This is the link http://codepen.io/korolariya/pen/WxbPJo

 (function($) { $(document).ready(function() { function keydown(event) { if (player.pressed.indexOf(event.which) === -1) { switch (event.which) { case 37: // left player.vec_add(player.velocity, { x: -1, y: 0 }); break; case 38: // top player.vec_add(player.velocity, { x: 0, y: -1 }); break; case 39: // right player.vec_add(player.velocity, { x: 1, y: 0 }); break; case 40: // bottom player.vec_add(player.velocity, { x: 0, y: 1 }); break; } player.pressed.push(event.which); } } function keyup(event) { var index; if ((index = player.pressed.indexOf(event.which)) >= 0) { player.pressed.splice(index, 1); switch (event.which) { case 37: // left player.vec_sub(player.velocity, { x: -1, y: 0 }); break; case 38: // top player.vec_sub(player.velocity, { x: 0, y: -1 }); break; case 39: // right player.vec_sub(player.velocity, { x: 1, y: 0 }); break; case 40: // bottom player.vec_sub(player.velocity, { x: 0, y: 1 }); break; } } } window.addEventListener("keydown", keydown, false); window.addEventListener("keyup", keyup, false); var player = { selector: $('#player'), position: { x: 110, y: 110 }, target: { x: 0, y: 0 }, click: { x: 0, y: 0 }, normal: { x: 0, y: 0 }, way: { x: 0, y: 0 }, speed: 3, collapse: 5, pressed: [], velocity: { x: 0, y: 0 }, vec_add: function(a, b) { ax += bx; ay += by; }, vec_sub: function(a, b) { ax -= bx; ay -= by; } }; player.move = function(pos) { if (pos != undefined) { this.position.x = pos.x; this.position.y = pos.y; } this.selector.css("left", (this.position.x - 5) + 'px'); this.selector.css("top", (this.position.y - 5) + 'px'); }; player.normalMove = function() { this.countWay(); this.position.x = this.position.x + (this.normal.x * this.speed); this.position.y = this.position.y + (this.normal.y * this.speed); this.move(); }; player.keyMove = function() { if(this.velocity.x || this.velocity.y != 0){ var normal = {x:0,y:0}; normal.x = this.speed * this.velocity.x / Math.sqrt(Math.pow(this.velocity.x, 2) + Math.pow(this.velocity.y, 2)); normal.y = this.speed * this.velocity.y / Math.sqrt(Math.pow(this.velocity.x, 2) + Math.pow(this.velocity.y, 2)); this.vec_add(this.position, normal); this.move(); } }; player.setNormal = function(e) { this.click.x = e.clientX; this.click.y = e.clientY; this.target.x = this.click.x - this.position.x; this.target.y = this.click.y - this.position.y; this.normal.x = this.target.x / Math.sqrt(Math.pow(this.target.x, 2) + Math.pow(this.target.y, 2)); this.normal.y = this.target.y / Math.sqrt(Math.pow(this.target.x, 2) + Math.pow(this.target.y, 2)); this.countWay(); }; player.untilgo = function() { return this.way.x > this.collapse || this.way.y > this.collapse; }; player.countWay = function() { //тут можно вычислять расстояние // Math.sqrt(Math.pow(this.position.x - this.click.x)+Math.pow(this.position.y - this.click.y)); this.way.x = Math.abs(this.position.x - this.click.x); this.way.y = Math.abs(this.position.y - this.click.y); }; player.move(); var timer; var fps = 60; function step() { setTimeout(function() { requestAnimationFrame(step); if (player.untilgo()) { player.normalMove(); } player.keyMove(); }, 1000 / fps); } step(); $(document).click(function(e) { player.setNormal(e); }); }); }) (jQuery); 
  • 1. vec_add and vec_sub - only the first would suffice. 2. If after clicking the mouse to press the move button on the keyboard, it will move forever. - Qwertiy
  • Yes, there are a lot of jambs written there =) In addition to this, but as if the essence can be caught. So that is solved by adding the parameter run = true / false to the player - Serge Esmanovich
  • Here's another useful dock if anyone is interested in docs.unity3d.com/ru/current/Manual/… - Serge Esmanovich

Subscribe to keydown and keyup . In the first place the flag of movement in this direction, in the second - to shoot. The movement itself is carried out on a timer, checking whether the corresponding button is pressed.

https://jsfiddle.net/fwg53xc8/6/ in chrome or FF (because of ES6):

 ~function() { var LEFT = 37, UP = 38, RIGHT = 39, DOWN = 40; var dirs = {[LEFT]: 0, [UP]: 0, [RIGHT]: 0, [DOWN]: 0}; var SPEED = 10; var x = 0, y = 0; $(document).keydown(function(e) { dirs[e.keyCode] = 1; }).keyup(function(e) { dirs[e.keyCode] = 0; }); setInterval(function() { var $div = $("div"); x -= dirs[LEFT] * SPEED; x += dirs[RIGHT] * SPEED; y -= dirs[UP] * SPEED; y += dirs[DOWN] * SPEED; $div.css('transform', `translate(${x}px, ${y}px)`); }, 100); }(); 
 div { position: absolute; left: 50%; top: 50%; margin: -.5em -.5em 0 0; background: red; width: 1em; height: 1em; border-radius: 50%; transform: translate(0, 0); transition: transform 100ms linear; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div></div> 

requestAnimationFrame

Why did everyone give up requestAnimationFrame instead of a timer?

on the contrary, the vector movement is carried out on a plane, with acceleration or deceleration at will, as well as in space. You have now done at the most primitive level.

Again. I have done for a very specific case. There is a certain checkered field, in the cells of which all sorts of objects are located. During one movement, the player either stays in the current cell, or moves to one of 8 neighbors. In this embodiment, I am not interested in the constancy of speed when moving diagonally, I am interested in ensuring the transition from cell to cell.

  • timer movement? O_o - Alexey Shimansky
  • 2
    Yep This is certainly good, but at intervals there are some problems, and for such purposes, it seems like there is a requestAnimationFrame ..... anyway, bicycles are somehow not worth inventing, IMHO)) - Alexey Shimansky
  • @NicolasChabanovsky, why spoil the formatting? In addition, jQuery was lost when copying: ( - Qwertiy
  • @ Alexey Shimansky, in this case I do not see the benefits of requestAnimationFrame . - Qwertiy
  • @Qwertiy This is an automatic format (tidy button). You can update the code snippet, if necessary. - Nicolas Chabanovsky

You need to deliberately stop the sprite before each movement to prevent movement after releasing any of the keys.

for example, you can implement this:

 var cnv = document.querySelector("#cnv"); var ctx = cnv.getContext("2d"); var frameID = 0; var dt = 0; var currentFrame = 0; var lastFrame = currentFrame; var keys = {}; var Vec2 = function(x, y) { this.x = x; this.y = y; this.add = function(other) { this.x += other.x; this.y += other.y; return this; }; this.multScalar = function(scalar) { this.x *= scalar; this.y *= scalar; return this; }; }; var rect = { fillColor: "#f12", position: new Vec2(0, 0), velocity: new Vec2(0, 0), w: 10, h: 10, move: function(dt) { this.position.add(this.velocity.multScalar(dt)); }, stop: function() { this.velocity.x = 0; this.velocity.y = 0; }, render: function() { ctx.clearRect(0, 0, cnv.width, cnv.height); ctx.fillStyle = this.fillColor; ctx.fillRect(this.position.x, this.position.y, this.w, this.h); } }; function renderScene() { currentFrame = new Date(); dt = currentFrame - lastFrame; // miliseconds lastFrame = currentFrame; rect.stop(); if (keys[37]) { rect.velocity.x = -0.2; } if (keys[39]) { rect.velocity.x = 0.2; } if (keys[38]) { rect.velocity.y = -0.2; } if (keys[40]) { rect.velocity.y = 0.2; } rect.move(dt); rect.render(); frameID = requestAnimationFrame(renderScene); } window.onkeydown = function(event) { keys[event.keyCode] = true; }; window.onkeyup = function(event) { keys[event.keyCode] = false; }; frameID = requestAnimationFrame(renderScene); 
 #cnv { border: 1px solid black; } 
 <canvas width="300" height = "150" id="cnv"></canvas>