我正在参加掘金注意:随机点的数目越多,距离可能很小,图中看出的效果可能不明显。社区游戏创意投稿大赛个人赛,详情请看:游戏创意投稿大赛
游戏地址:不会搞(所以没放)git地址:gitee.com/fwjzzz/Conn…
前言
初中阶段我们经常遇到求“最短距离”的数学问题,很多同学对此类问题毫无头绪,遇到此类问题总是一头雾水、无从下手。其实这类题难度并不大,如果我们能掌握解决这类题的本质及方法,“最短距离”问题将迎刃而解。
游戏规则
非常简单:在随机生成的点中,找到之间距离最短的点,计算两点间的直线距离并连接点,然后加分。
实现
初始化
布局
<div id="app">
<div id="score"></div>
<svg id="svg"></svg>
<div id="launch-screen" class="is-visible">
<div id="launch-screen-content">
<h1 id="launch-screen__title"></h1>
<p id="launch-screen__description"></p>
<button class="btn" id="start-btn">PLAY</button>
</div>
</div>
</div>
开始游戏
app.launchScreen(
0,
"最短距离",
"寻找最近的点.",
"开始"
);
激活点用于存储游戏过程中单击点的数据执行进行,selected属性为false则未选中无法进行选择,为true 则可以单击,监听点击push进svg中
function Dot(r, cx, cy) {
this.r = r;
this.cx = cx;
this.cy = cy;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.class = "dot";
this.update = function () {
this.el.setAttribute("r", this.r);
this.el.setAttribute("cx", this.cx);
this.el.setAttribute("cy", this.cy);
this.setAttr("class", this.class);
};
// 激活一个点用于存储游戏中每个点的所有数据的对象。
this.activate = function () {
for (i = 0; i < dots.num; i++) {
dots.list[i].setAttr("data-selected", "false");
}
this.setAttr("data-selected", "true");
// 将所有其他点的 selected 属性设置为 false,因此它们未被选中且无法单击。
// 它将这个点的 selected 属性设置为 true,以便它现在可以选择并且可以单击。
};
this.visited = function () {
this.setAttr("data-visited", "true");
// 创建一个新的函数 单击点进行访问,执行函数
// 在这种情况下,它将其自己的访问属性设置为 true,以便我们知道哪些点之前已访问过,
// 哪些点在我们当前与游戏的会话期间尚未访问过。
};
// 将属性设置为元素
this.setAttr = function (attr, value) {
this.el.setAttribute(attr, value);
};
// 获取元素的属性。
this.getAttr = function (attr) {
return this.el.getAttribute(attr);
};
// 元素追加到SVG并附加事件监听器
this.append = function () {
svg.appendChild(this.el);
this.el.addEventListener("click", this.onClick);
};
// 点击点元素
this.onClick = function (event) {
//gets the id and the coords of the dot
var thisId = Number(event.target.getAttribute("data-id").substr(3, 2));
var thisCx = dots.list[thisId].cx;
var thisCy = dots.list[thisId].cy;
// 计算点之间的距离
var distances = [];
for (i = 0; i < dots.num; i++) {
distances[i] = [i, getDistance(dots.selected, dots.list[i])];
}
distances.sort(comparator);
distances.splice(0, 1);
var distancesLeft = [];
for (i = 0; i < distances.length; i++) {
if (dots.left.includes(distances[i][0])) {
distancesLeft.push(distances[i][0]);
}
}
//如果元素是最近的
if (thisId == distancesLeft[0] && dots.left.includes(thisId)) {
// 计算距离
var newDistance = getDistance(dots.list[thisId], dots.selected);
app.score.update(1); // punteggio x numero di poi
// app.score.update(newDistance); punteggio x distanza
//设置为选定的点
dots.list[thisId].activate();
dots.list[thisId].visited();
// 创建线
lines.list.push(
new Line(
dots.selected.cx,
dots.selected.cy,
dots.list[thisId].cx,
dots.list[thisId].cy
)
);
lines.list[lines.list.length - 1].update();
lines.list[lines.list.length - 1].append();
// 创建预览行
//除去这些,你就能活下去了
svg.addEventListener("mousemove", function prelineMove(e) {
mouseX = e.pageX;
mouseY = e.pageY;
app.preline.update(thisCx, thisCy, mouseX, mouseY);
});
//保存选定的点坐标
dots.selected.id = thisId;
dots.selected.cx = thisCx;
dots.selected.cy = thisCy;
//将圆点从剩余的圆点列表中移除
for (i = 0; i < dots.left.length; i++) {
if (dots.left[i] === thisId) {
dots.left.splice(i, 1);
}
}
if (dots.left.length == 0) {
app.end(true);
}
} else {
app.end(false);
}
};
}
注意:随机点的数目越多,距离可能很小,图中看出的效果可能不明显。
计算两点之间距离
计算obj1,obj2 两个对象之间的距离。 使用 Math.sqrt 和 Math.pow 函数计算两个对象之间的平方根。
function getRandomArbitrary(min, max) {
return Math.floor(Math.random() * (max - min) + min);
} //计算随机算
关卡,计算得分
// 计算
var app = {};
app.level = 4; //关卡
app.score = {}; //分数
app.score.number = 0; //分数为0
app.score.el = document.getElementById("score");
app.score.update = function(score) {
//计算得分
app.score.number += score;
app.score.el.textContent = app.score.number;
};
//重置按钮分数清零
app.score.reset = function() {
app.score.number = 0;
app.score.update(0);
};
app.results = function(points) {
if (points == "reset") {
sessionStorage.setItem("results", 0);
} else {
if (!sessionStorage.getItem("results")) {
sessionStorage.setItem("results", points);
} else {
var newscore = parseInt(sessionStorage.getItem("results")) + points;
sessionStorage.setItem("results", newscore);
}
}
};
app.launchScreen = function(lastScore, title, description, btnText) {
// 创建一个名为 launchScreen 的函数,该函数将用于创建应用程序的一个实例并将其显示在屏幕上。
app.launchScreen.el = document.getElementById("launch-screen");
// 使用 document.getElementById() 来获取对启动屏幕的标题、描述和 btnText 元素的引用。
app.launchScreen.el.setAttribute("class", "is-visible");
var launchScreenTitle = document.getElementById("launch-screen__title");
launchScreenTitle.textContent = title;
var launchScreenDescription = document.getElementById(
"launch-screen__description"
);
launchScreenDescription.textContent = description;
app.launchScreen.btn = document.getElementById("start-btn");
// 当用户单击 start-btn 或 stop-btn 以分别启动或关闭此屏幕时设置事件侦听器。
// 会将launchScreen 的class 属性设置为“is-visible”,使其在屏幕上可见。
app.launchScreen.btn.textContent = btnText;
app.launchScreen.btn.addEventListener("click", function lauch() {
app.launchScreen.el.setAttribute("class", "");
app.start(app.level);
app.launchScreen.btn.removeEventListener("click", lauch);
});
};
app.preline = new Line(0, 0, 200, 200);
app.preline.setAttr("id", "preline");
// 首先设置要在屏幕上绘制的点数。
// 然后它遍历所有点并为每个点创建一个新点。
连线起点
app.start = function(dotsNum) {
dots.num = dotsNum; // 将dotsNum 变量设置为一个数字
for (i = 0; i < dots.num; i++) {
var cx = getRandomArbitrary(10, screenW - 10);
var cy = getRandomArbitrary(10, screenH - 10);
dots.list[i] = new Dot(8, cx, cy);
dots.list[i].setAttr("data-id", "id-" + i);
dots.list[i].setAttr(
"style",
"animation-delay:" + i / 10 + "s; transform-origin: " + cx + 'px ' + cy + 'px;');
dots.list[i].update();
dots.list[i].append();
dots.left.push(i);
if (i == dots.start) {
dots.selected.cx = dots.list[dots.start].cx;
dots.selected.cy = dots.list[dots.start].cy;
dots.list[dots.start].setAttr("class", "dot dot--starting");
dots.left.splice(i, 1);
}
// 设置了一个id属性,style,animation-delay:10s;变换原点:cx+cy;对于每个点。
// 然后它更新它们并将它们附加到左侧的点列表中(它们将显示在哪里)。
// 添加preline
app.preline.update(
dots.selected.cx,
dots.selected.cy,
dots.selected.cx,
dots.selected.cy
);
// preline 功能,当您将鼠标移到 cx 或 cy 值相对于其父位置(起点)的位置在 0 到 10 像素之间的任何点上时,该功能将更新。
app.preline.append(); // 在屏幕上创建随机数量的点,然后将它们附加到数组中。
svg.addEventListener("mousemove", function prelineMove(e) {
// 一个事件侦听器,用于侦听 mousemove 事件并相应地更新点的位置。
mouseX = e.pageX;
mouseY = e.pageY;
app.preline.update(dots.selected.cx, dots.selected.cy, mouseX, mouseY);
});
}
// 它到达起始点时,它将 data-selected 属性设置为 true
dots.list[dots.start].setAttr("data-selected", "true");
};
游戏开始,下一级,游戏失败
app.end = function(win) {
if (win) {
app.level += 4;
app.results(app.score.number);
} else {
app.level = 4;
}
dots.list = [];
dots.selected = {};
dots.left.length = 0;
svg.innerHTML = "";
if (win) {
app.launchScreen(
app.score.number,
"非常棒!",
"你的分数是: " + sessionStorage.getItem("results") + ' 下一级会更难哦!',
"继续"
);
} else {
app.launchScreen(
0,
"游戏结束!",
"你的最终得分是: " + sessionStorage.getItem("results"),
"再来一局"
);
app.results("reset");
app.score.reset();
}
};
app.launchScreen(
0,
"最短距离",
"寻找最近的点.",
"开始"
);