Implemented the logic of turns of the character when pressing the keys: , , , . But there is a problem, because attached to degrees, then when you are in the Up position and you need to rotate Left, you get an angle of 270 degrees, which is not natural for the user. Tell me how to solve this issue? Code below.

 document.onkeydown = function (event){ if (event.key == 'ArrowRight'){ Player.direction.transform = 0; }; if (event.key == 'ArrowLeft') { Player.direction.transform = 180; }; if (event.key == 'ArrowDown'){ Player.direction.transform = 90; }; if (event.key == 'ArrowUp'){ Player.direction.transform = -90; }; Player.renderPosition(htmlPlayer,Player); }; 

All code:

 <div id="dot" style=" position: fixed; border-radius: 50%; -webkit-background-size: cover; background-size: cover; background-repeat: no-repeat; transition: transform .3s; -webkit-transition: transform .3s; -moz-transition: transform .3s; -o-transition: transform .3s;"> </div> var htmlPlayer = $('#dot'); var GameMap = { width: $(window).width(), height: $(window).height() }; var Player = { sizes: { width: 36, height: 36 }, position: { top: 0, left: 0 }, direction: { transform: 0 }, speed: 1.5, backgroundImage: 'img/player.png', setPosition: function(pos){ switch(pos){ case 'top': this.position.top = 0; this.position.left = GameMap.width / 2 - (this.sizes.width/2); break case 'left': this.position.left = 0; this.position.top = GameMap.height / 2 - (this.sizes.height/2); break case 'center': this.position.top = GameMap.height / 2 - (this.sizes.height/2); this.position.left = GameMap.width / 2 - (this.sizes.width/2); break case 'bottom': this.position.top = GameMap.height - (this.sizes.height); this.position.left = GameMap.width / 2 - (this.sizes.width/2); break case 'right': this.position.top = GameMap.height / 2 - (this.sizes.height/2); this.position.left = GameMap.width - (this.sizes.width); break } }, renderPosition: function(elm,Player){ elm.css({ left: Player.position.left + 'px', top: Player.position.top + 'px', width: Player.sizes.width + 'px', height: Player.sizes.height + 'px', transform: 'rotate' + '('+ Player.direction.transform + 'deg)', 'background-image': 'url('+ Player.backgroundImage +')', }); } }; Player.setPosition('center'); Player.renderPosition(htmlPlayer,Player); document.onkeydown = function (event){ if (event.keyCode) { Player.backgroundImage = 'img/player.gif'; } if (event.keyCode == 37){ if(Player.position.left <= 0){ Player.position.left = 0; }else{ Player.position.left-=Player.speed; } } if (event.keyCode == 38){ if(Player.position.top <= 0){ Player.position.top = 0; }else{ Player.position.top-=Player.speed; } } if (event.keyCode == 39){ if(Player.position.left >= GameMap.width-Player.sizes.width){ Player.position.left = GameMap.width-Player.sizes.width; }else{ Player.position.left+=Player.speed; } } if (event.keyCode == 40){ if (Player.position.top >= GameMap.height-Player.sizes.height) { Player.position.top = GameMap.height-Player.sizes.height; }else{ Player.position.top+=Player.speed; } } if (event.keyCode == 37) { Player.direction.transform = 180; } if (event.keyCode == 38){ Player.direction.transform = -90; } if (event.keyCode == 39){ Player.direction.transform = 0; } if (event.keyCode == 40){ Player.direction.transform = 90; } Player.renderPosition(htmlPlayer,Player); console.log(Player.direction.transform); }; document.onkeyup = function(evt){ if (event.keyCode) { Player.backgroundImage = 'img/player.png'; } Player.renderPosition(htmlPlayer,Player); }; }); 

Interested in a moment with turns. With the logic that I (event.keyCode == 37) , from the position (event.keyCode == 37) to the position (event.keyCode == 38) will be a rotation of 270 degrees. Tell me the solutions?


 var htmlPlayer = $('#dot'); var GameMap = { width: $(window).width(), height: $(window).height() }; var Player = { sizes: { width: 36, height: 36 }, position: { top: 0, left: 0 }, direction: { transform: 0 }, speed: 1.5, backgroundImage: 'img/player.png', setPosition: function(pos) { switch (pos) { case 'top': this.position.top = 0; this.position.left = GameMap.width / 2 - (this.sizes.width / 2); break case 'left': this.position.left = 0; this.position.top = GameMap.height / 2 - (this.sizes.height / 2); break case 'center': this.position.top = GameMap.height / 2 - (this.sizes.height / 2); this.position.left = GameMap.width / 2 - (this.sizes.width / 2); break case 'bottom': this.position.top = GameMap.height - (this.sizes.height); this.position.left = GameMap.width / 2 - (this.sizes.width / 2); break case 'right': this.position.top = GameMap.height / 2 - (this.sizes.height / 2); this.position.left = GameMap.width - (this.sizes.width); break } }, renderPosition: function(elm, Player) { elm.css({ left: Player.position.left + 'px', top: Player.position.top + 'px', width: Player.sizes.width + 'px', height: Player.sizes.height + 'px', transform: 'rotate' + '(' + Player.direction.transform + 'deg)', 'background-image': 'url(' + Player.backgroundImage + ')', }); } }; Player.setPosition('center'); Player.renderPosition(htmlPlayer, Player); document.onkeydown = function(event) { if (event.keyCode) { Player.backgroundImage = 'img/player.gif'; } if (event.keyCode == 37) { if (Player.position.left <= 0) { Player.position.left = 0; } else { Player.position.left -= Player.speed; } } if (event.keyCode == 38) { if (Player.position.top <= 0) { Player.position.top = 0; } else { Player.position.top -= Player.speed; } } if (event.keyCode == 39) { if (Player.position.left >= GameMap.width - Player.sizes.width) { Player.position.left = GameMap.width - Player.sizes.width; } else { Player.position.left += Player.speed; } } if (event.keyCode == 40) { if (Player.position.top >= GameMap.height - Player.sizes.height) { Player.position.top = GameMap.height - Player.sizes.height; } else { Player.position.top += Player.speed; } } if (event.keyCode == 37) { Player.direction.transform = 180; } if (event.keyCode == 38) { Player.direction.transform = -90; } if (event.keyCode == 39) { Player.direction.transform = 0; } if (event.keyCode == 40) { Player.direction.transform = 90; } Player.renderPosition(htmlPlayer, Player); console.log(Player.direction.transform); }; document.onkeyup = function(evt) { if (event.keyCode) { Player.backgroundImage = 'img/player.png'; } Player.renderPosition(htmlPlayer, Player); }; }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="dot" style=" position: fixed; border-radius: 50%; -webkit-background-size: cover; background-size: cover; background-repeat: no-repeat; transition: transform .3s; -webkit-transition: transform .3s; -moz-transition: transform .3s; -o-transition: transform .3s;"> </div> 

(Full picture)

Interested in a moment with turns. With the logic that I specified, from the position (event.keyCode == 37) to the position (event.keyCode == 38) there will be a rotation of 270 degrees. Tell me the solutions?

  • Can you clarify in the question, what exactly does the angle of 270 degrees interfere with you? - Kromster
  • It is not natural that in a game that in life you will always do / expect 90 or 180 degrees. If I am in the Up position, then I want to turn 90 degrees to the left, not 270. - Yury Butsan
  • Naturalness is a relative and individual concept. I, for example, -90 is unusual)) In any case, please describe this clarification in the question and add a simple replacement if a == 270 then a = -90 will suit you, and if not, then why, what additional conditions? - Kromster
  • Up position (-90) press Right = 0 Position Right (0) press Down = 90 Position Down (90) press Left = 180 Position Left (180) press Up = -90 (Turns with a 270 angle) - Yuri Butsan

1 answer 1

Apparently the engine behind the scenes interpolates the angle. When moving between 0 ° and 90 °, everything works fine because the interpolation will be along the shortest path. But when moving through 360 °, this does not work because from 350 to 10 the shortest way will be through turn by + 20 °, and not by -340 °. As one of the solutions, you can find the nearest angle from the next turns (-90 °, -90 ° + 360 ° and -90 ° - 360 °). In this case, you must take into account the original direction.

 var directions = { ArrowRight: 0, ArrowDown: 90, ArrowLeft: 180, ArrowUp: -90 }; document.onkeydown = function (event) { if (event.key in angles) { var targetAngle = directions[event.key]; var delta = targetAngle - Player.direction; Player.direction.transform = Player.direction + delta; } } 

But here comes a nuance - now the position of the player can take values ​​greater than 180 ° and less than -90 °. To take this into account, you need to subtract the number of full turns when calculating delta :

 document.onkeydown = function (event) { if (event.key in angles) { // Вычитаем количество целых оборотов var normPlayerDirection = (Player.direction + 90) % 360 - 90; var targetAngle = directions[event.key]; // Считаем угол, на который нужно повернуть объект var delta = targetAngle - normPlayerDirection; Player.direction.transform = Player.direction + delta; Player.renderPosition(htmlPlayer, Player); } } 

But this solution is far from the best. If you rotate long enough, you can come to values ​​where the absolute angle will have very high values ​​and the error in calculating floating-point numbers will be noticeable. To avoid this, you need to look at how the rotation is implemented in the engine and choose more appropriate functions for changing the angle.

  • Thanks :) Look, please, below the whole engine. - Yuri Butsan