首页 > 解决方案 > javascript游戏 - 操纵杆问题

问题描述

注意:我再次问了这个问题,因为我无法编辑我的旧问题。(不知道这是一个 SO 错误还是我的 beta Safari 的一个错误。)

所以我想生成一个游戏杆,因为它在许多游戏中都有使用。操纵杆从背景和可移动的钢坯中脱颖而出。方坯只能在后台移动。

在这里你可以找到这两个图像

背景

戳

let background = new Image()
let stick = new Image()
let enableMaxDistance = false

background.onload = function() {
  $(this).css({
    position: "absolute",
    left: "2%",
    bottom: "2%",
    width: "30%"
  }).appendTo(document.body)
}
stick.onload = function() {
  $(this).css({
    position: "absolute",
    left: "2%",
    bottom: "2%",
    width: "30%"
  }).appendTo(document.body)
  let zeroPosition = $(this).offset()
  $(this).draggable({
    drag: function(e, ui) {
      let distance = Math.sqrt(Math.pow(zeroPosition.top - $(this).offset().top, 2) + Math.pow(zeroPosition.left - $(this).offset().left, 2));
      if (distance > 60 && enableMaxDistance) {
        e.preventDefault();
      }
    },
    scroll: false

  })
}
background.src = "https://i.stack.imgur.com/5My6q.png"
stick.src = "https://i.stack.imgur.com/YEoJ4.png"
html, body {
  overflow: hidden;
  height: 100%;
}
input {
  margin-top: 10%;
  margin-left: 50%;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>


<input onclick="enableMaxDistance = !enableMaxDistance " value="toggle maximum distance" type="button"/>

但是在实现这个操纵杆时出现了一些问题:

我的想法是通过使用 jqueryUI 使操纵杆可操纵,并通过每个拖动事件计算其到原点的距离。如果距离太大,事件将使用 停止(不执行)e.preventDefault();。-->如果在框架中的距离,则棒是可穿戴的。 问题是...

  1. 移出最大距离后,摇杆不再可拖动。

  2. 棒应该可以在边界内移动而不会取消事件,这样如果我触及边界(超出最大距离),我必须一次又一次地抓住棒。

如何使用jQuery+实现工作操纵杆jQueryUI

标签: javascriptjqueryhtmlcss

解决方案


您的逻辑问题是,一旦drag事件被阻止,由于 JS 处理时间的固有延迟,该distance值就会结束。60因此,下一次拖动中的逻辑立即被取消,因为distance > 60检查被立即命中。虽然可以解决此问题,但更好的解决方案是不允许该值大于您设置的限制。

为了实现这一点,我不建议使用 jQueryUI。您可以使用本机方法很容易地做到这一点,这些方法可以让您更直接地控制定位,而无需与任何内置逻辑作斗争。

它的性能也略高一些,这在处理游戏机制时至关重要;特别是在处理需要尽可能响应的直接用户输入时。

话虽如此,您可以使用修改 Twisty 对此问题的评论中所述的基本逻辑。然后它就变成了改变相关元素大小的问题,这是一项微不足道的任务。试试这个:

var $canvas = $('#background');
var $pointer = $('#stick');
var $window = $(window);

var settings = {
  width: $canvas.prop('offsetWidth'),
  height: $canvas.prop('offsetHeight'),
  top: $canvas.prop('offsetTop'),
  left: $canvas.prop('offsetLeft')
};
settings.center = [settings.left + settings.width / 2, settings.top + settings.height / 2];
settings.radius = settings.width / 2;

let mousedown = false;
$window.on('mouseup', function() { mousedown = false; });
$pointer.on('mousedown', function() { mousedown = true; });
$pointer.on('mouseup', function() { mousedown = false; });
$pointer.on('dragstart', function(e) { e.preventDefault(); });

$window.on('mousemove', function(e) {
  if (!mousedown)
    return;

  var result = limit(e.clientX, e.clientY);
  $pointer.css('left', result.x + 'px');
  $pointer.css('top', result.y + 'px');
});

function limit(x, y) {
  var dist = distance([x, y], settings.center);
  if (dist <= settings.radius) {
    return {
      x: x,
      y: y
    };
  } else {
    x = x - settings.center[0];
    y = y - settings.center[1];
    var radians = Math.atan2(y, x)
    return {
      x: Math.cos(radians) * settings.radius + settings.center[0],
      y: Math.sin(radians) * settings.radius + settings.center[1]
    }
  }
}

function distance(dot1, dot2) {
  var x1 = dot1[0],
    y1 = dot1[1],
    x2 = dot2[0],
    y2 = dot2[1];
  return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
html,
body {
  height: 100%;
}

#background {
  background-image: url('https://i.stack.imgur.com/5My6q.png');
  position: absolute;
  height: 200px;
  width: 200px;
  top: 50%;
  left: 50%;
  margin: -100px 0 0 -100px;
  border-radius: 200px;
  border: dashed #ccc 1px;
}

#stick {
  background: transparent url('https://i.stack.imgur.com/YEoJ4.png') 50% 50%;
  position: absolute;
  width: 100px;
  height: 100px;
  border-radius: 100px;
  margin: -50px 0 0 -50px;
  top: 50%;
  left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="background"></div>
<div id="stick"></div>


推荐阅读