简而言之,请参考JSFiddle
从四个玩家到六个玩家,您需要了解支持四个玩家的数学知识并将其应用于六个玩家的情况。
四个玩家的情况
您可以将每个玩家的位置视为一个以桌子中心为原点的圆周上给定的角度(或弧度)。在四个玩家的情况下,第一个玩家(索引0)的角度为0度,第二个玩家为90度,等等。
要确定一个玩家的移动如何影响不处于同一角度的另一个人屏幕上的卡片的移动,您需要将卡片的运动分解为其基础。在这种情况下,基础由两个正交向量组成,它们定义了当前玩家的运动空间。第一个向量是使用角度生成的向量。第二个向量可以通过取当前角度并添加90度(Pi / 2弧度)来找到。对于四个玩家的情况,第一个玩家将具有0度的主基向量,即(1,0)。第一个玩家的次要基向量将是0 + 90 = 90度,即(0,1)。
要将鼠标移动(delta screen x和y)转换为使用任意基础的运动,您需要取delta screen x和y与基础中每个向量的x和y的点积。在四个玩家的情况下,当第一个玩家移动卡片时,主要和次要基础的点积分别得到x delta和y delta。
计算出当前玩家的这个值后,您可以按照其基础术语移动其他玩家屏幕上的卡片。为此,请将已转换为沿两个基础的运动应用于每个其他玩家的基础。在四个玩家的情况下,第二个玩家的主基础为90度=(1,0),次要基础为90 + 90度=(-1,0)。因此,要在第二个玩家的位置上镜像移动,原始x运动被转换为y运动,原始y运动被转换为-x运动。
六(或任意数量)个玩家
要将此更改为具有任意数量的玩家并且第一个玩家可能偏离0度的游戏,您需要遵循相同的数学方法。首先,为每个玩家计算基础。其次,使用点积计算以其基础术语中移动的卡片的delta。第三,将此运动应用于其他玩家的基础。
下面的示例允许您更改玩家数量和起始偏移角度。卡片是div,覆盖在div上的是画布,用于显示每个基础的主轴(红色)和次要轴(蓝色)。
<div>
<div class="table-div">
</div>
<div>
This example shows how the current players card (blue) can be shown moving on other players' (red "ghost" cards).
Below you
can change the number of players and the angle offset of the starting player.
</div>
<div>
<p>Players</p>
<input type="text" onchange="playerChange()" id="playerText" value="6">
</div>
<div>
<p>Angle (Degrees)</p>
<input type="text" onchange="angleChange()" id="angleText" value="45">
</div>
<canvas id="canv"></canvas>
body {
margin: 0;
}
canvas {
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.table-div {
background-color: lightgreen;
width: 400px;
height: 400px;
}
.card {
position: absolute;
width: 50px;
height: 70px;
}
.current {
background-color: blue;
}
.ghost {
background-color: red;
}
class Vector2 {
constructor(x, y) { [this.x, this.y] = [x, y] }
}
let playerCount = 6;
let offsetAngle = 45;
let width = 400;
let height = width;
let radius = width / 2;
let cardWidth = 50;
let cardHeight = 50 * 1.4;
let cards;
let lastMouse = null;
let currentMouse = null;
let mouseDown = false;
let angleDelta;
let tableElement = document.querySelector(".table-div");
let canvas = document.querySelector("canvas")
let ctx = canvas.getContext("2d");
canvas.style.width = width + "px";
canvas.style.height = height + "px"
canvas.width = width;
canvas.height = height;
function update() {
ctx.clearRect(0, 0, width, height);
for (let i = 0; i < playerCount; i++) {
ctx.strokeStyle = "red";
ctx.beginPath();
ctx.moveTo(radius, radius);
ctx.lineTo(radius + Math.cos(angleDelta * i + offsetAngle) * radius, radius + Math.sin(angleDelta * i + offsetAngle) * radius)
ctx.stroke();
let secondAxisAngle = angleDelta * i + Math.PI / 2;
let startX = radius + Math.cos(angleDelta * i + offsetAngle) * radius / 2;
let startY = radius + Math.sin(angleDelta * i + offsetAngle) * radius / 2;
let endX = Math.cos(secondAxisAngle + offsetAngle) * radius / 4;
let endY = Math.sin(secondAxisAngle + offsetAngle) * radius / 4;
ctx.strokeStyle = "green";
ctx.beginPath();
ctx.moveTo(startX, startY)
ctx.lineTo(startX + endX, startY + endY)
ctx.stroke();
}
}
document.body.addEventListener("mousemove", e => {
lastMouse = currentMouse;
currentMouse = new Vector2(e.clientX, e.clientY);
if (lastMouse && mouseDown) {
let mouseDelta = new Vector2(currentMouse.x - lastMouse.x, currentMouse.y - lastMouse.y);
if (mouseDown) {
let primaryAxisCurrent = new Vector2(Math.cos(angleDelta * 0 + offsetAngle), Math.sin(angleDelta * 0 + offsetAngle))
let secondAxisCurrent = new Vector2(Math.cos(angleDelta * 0 + Math.PI / 2 + offsetAngle), Math.sin(angleDelta * 0 + Math.PI / 2 + offsetAngle))
let primary = (primaryAxisCurrent.x * mouseDelta.x + primaryAxisCurrent.y * mouseDelta.y)
let second = (secondAxisCurrent.x * mouseDelta.x + secondAxisCurrent.y * mouseDelta.y)
for (let i = 0; i < playerCount; i++) {
let primaryAxis = new Vector2(Math.cos(angleDelta * i + offsetAngle), Math.sin(angleDelta * i + offsetAngle))
let secondAxis = new Vector2(Math.cos(angleDelta * i + Math.PI / 2 + offsetAngle), Math.sin(angleDelta * i + Math.PI / 2 + offsetAngle))
let primaryAxisMovement = new Vector2(primaryAxis.x * primary, primaryAxis.y * primary)
let secondAxisMovement = new Vector2(secondAxis.x * second, secondAxis.y * second)
let div = cards[i];
let location = new Vector2(parseFloat(div.style.left) + primaryAxisMovement.x + secondAxisMovement.x, parseFloat(div.style.top) + primaryAxisMovement.y + secondAxisMovement.y)
div.style.left = location.x + "px"
div.style.top = location.y + "px"
}
}
}
})
document.body.addEventListener("mousedown", () => mouseDown = true)
document.body.addEventListener("mouseup", () => mouseDown = false)
function initDivs() {
cards = [];
tableElement.innerHTML = "";
for (let i = 0; i < playerCount; i++) {
let div = document.createElement("div");
tableElement.appendChild(div);
div.classList.add("card")
if (i == 0) div.classList.add("current")
else div.classList.add("ghost")
let radians = angleDelta * i;
div.style.left = (radius - cardWidth / 2 + Math.cos(radians + offsetAngle) * (radius - cardWidth / 2)) + "px";
div.style.top = (radius - cardHeight / 2 + Math.sin(radians + offsetAngle) * (radius - cardHeight / 2)) + "px"
cards.push(div);
}
}
function playerChange() {
playerCount = +document.querySelector("#playerText").value;
angleDelta = Math.PI * 2 / playerCount;
initDivs();
angleChange();
}
function angleChange() {
offsetAngle = parseFloat(document.querySelector("#angleText").value) * Math.PI / 180;
initDivs();
update();
}
playerChange();
offsetAngle = (parseFloat(document.querySelector("#angleText").value) * Math.PI) / 180;
其值如下:offsetAngles = { // key: tableRotation, value: value used inside the code above 0: 0, 60: 0, 120: 180, 180: 0, 240: 180, 300: 0, };
- Hayder Ameenangles = { // key: tableRotation, value: value used inside the code 0: 180, 60: 60, 120: 120, 180: 180, 240: 240, 300: 300, }; offsetAngle = (angles[tableRotation] * Math.PI) / 180;
使用1的值似乎不起作用。我确定我在这里缺少一些数学知识。 - Hayder Ameen