- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在创建一个使用碰撞检测的 HTML5 迷你游戏,我最近发现它存在速度问题:
我认为这个问题的原因是...
在 60fps 代码中有两个 forEach
循环,一个用于 rects
数组,另一个用于 lasers
数组。因此,当 Canvas 中有 5 个矩形和 5 个激光时,它将在第一个 forEach
中循环 5 次,在第二个每一帧 中循环五次,并且每个 forEach
函数中有很多 ifs
,使游戏变慢。我如何才能将其更改为CPU 密集型?
如果你知道这个小游戏中更大的速度问题,请随时帮助我解决它。
这是我的全部代码:
我强烈建议您查看 JSFiddle而不是下面的代码,因为有 400 多行。
<!DOCTYPE html>
<html>
<head>
<title>VelJS α</title>
<!-- This app was coded by Tiago Marinho -->
<!-- Do not leech it! -->
<link rel="shortcut icon" href="http://i.imgur.com/Jja8mvg.png">
<!-- EaselJS: -->
<script src="http://static.tumblr.com/uzcr0ts/uzIn1l1v2/easeljs-0.7.1.min.js"></script>
<script src="http://pastebin.com/raw.php?i=W4S2mtCp"></script>
<!-- jQuery: -->
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
(function () {
// Primary vars (stage, circle, rects):
var stage,
circle, // Hero!
rects = [], // Platforms
lasers = [];
// Velocity vars:
var xvel = 0, // X Velocity
yvel = 0, // Y Velocity
xvelpast = 0,
yvelpast = 0;
// Keyvars (up, left, right, down):
var up = false, // W or arrow up
left = false, // A or arrow left
right = false, // D or arrow right
down = false; // S or arrow down
// Other vars (maxvel, col, pause):
var maxvel = 256, // Maximum velocity
col = false, // Collision detection helper (returns true if collided side-to-side)
pause = false;
// Volatility vars (rmdir, pastrmdir):
var rmdir = 0,
pastrmdir = 0;
// Main part (aka creating stage, creating circle, etc):
function init() {
stage = new createjs.Stage("canvas");
// Creating circle:
var circle = new createjs.Shape();
circle.radius = 11;
circle.graphics.beginFill("#fff").beginStroke("white").drawCircle(circle.radius - 0.5, circle.radius - 0.5, circle.radius);
circle.width = circle.radius * 2;
circle.height = circle.radius * 2;
stage.addChild(circle);
setTimeout(function () {
// newobj(W, H, X, Y)
newobj("laser", 3, 244, stage.canvas.width / 2 - 125, stage.canvas.height / 4 * 3 - 247);
newobj("rect", 125, 3, stage.canvas.width / 2 - 125, stage.canvas.height / 4 * 3 - 250);
}, 250); // Wait until first tick finishes and stage is resized to 100%, then calculate the middle of canvas.
// User Input (Redirect input to Input Handler):
// Keydown:
document.addEventListener("keydown", function (evt) {
if (evt.keyCode == 87 || evt.keyCode == 38) { // up
up = true;
}
if (evt.keyCode == 65 || evt.keyCode == 37) { // left
left = true;
}
if (evt.keyCode == 68 || evt.keyCode == 39) { // right
right = true;
}
if (evt.keyCode == 83 || evt.keyCode == 40) { // down
down = true;
}
if (evt.keyCode == 8 || evt.keyCode == 80) { // del/p
if (pause == false) {
xvelpast = xvel;
yvelpast = yvel;
pause = true;
var fadestep = 0;
for (var i = 1; i > 0; i -= 0.1) {
i = parseFloat(i.toFixed(1));
fadestep++;
fadeFill("circle", i, fadestep);
rects.forEach(function (rect) {
fadeFill("rect", i, fadestep);
});
}
} else {
pause = false;
xvel = xvelpast;
yvel = yvelpast;
var fadestep = 0;
for (var i = 0; i <= 1; i += 0.1) {
i = parseFloat(i.toFixed(1));
fadestep++;
fadeFill("circle", i, fadestep);
rects.forEach(function (rect) {
fadeFill("rect", i, fadestep);
});
}
}
}
});
// Keyup:
document.addEventListener("keyup", function (evt) {
if (evt.keyCode == 87 || evt.keyCode == 38) { // up
up = false;
}
if (evt.keyCode == 65 || evt.keyCode == 37) { // left
left = false;
}
if (evt.keyCode == 68 || evt.keyCode == 39) { // right
right = false;
}
if (evt.keyCode == 83 || evt.keyCode == 40) { // down
down = false;
}
});
// Functions:
// Fade beginFill to a lower alpha:
function fadeFill(obj, i, t) {
setTimeout(function () {
if (obj == "circle") {
circle.graphics.clear().beginFill("rgba(255,255,255," + i + ")").beginStroke("white").drawCircle(circle.radius, circle.radius, circle.radius).endFill();
}
if (obj == "rect") {
for (var r = 0; r < rects.length; r++) {
rects[r].graphics.clear().beginFill("rgba(255,255,255," + i + ")").beginStroke("white").drawRect(0, 0, rects[r].width, rects[r].height).endFill();
}
}
}, t * 20);
};
// To create new rects:
function newobj(type, w, h, x, y) {
if (type == "rect") {
var rect = new createjs.Shape();
rect.graphics.beginFill("#fff").beginStroke("white").drawRect(0, 0, w, h);
rect.width = w + 1;
rect.height = h + 1;
rect.y = Math.round(y) + 0.5;
rect.x = Math.round(x) + 0.5;
stage.addChild(rect);
rects.push(rect);
}
if (type == "laser") {
var laser = new createjs.Shape();
if (w >= h) {
laser.graphics.beginFill("#c22").drawRect(0, 0, w, 1);
laser.width = w;
laser.height = 1;
} else {
laser.graphics.beginFill("#c22").drawRect(0, 0, 1, h);
laser.width = 1;
laser.height = h;
}
laser.shadow = new createjs.Shadow("#ff0000", 0, 0, 5);
laser.y = Math.round(y);
laser.x = Math.round(x);
stage.addChild(laser);
lasers.push(laser);
}
}
// Collision recoil:
function cls(clsdir) {
if (clsdir == "top") {
if (yvel <= 4) {
yvel = 0;
} else {
yvel = Math.round(yvel * -0.5);
}
}
if (clsdir == "left") {
if (xvel <= 4) {
xvel = 0;
} else {
xvel = Math.round(xvel * -0.5);
}
}
if (clsdir == "right") {
if (xvel >= -4) {
xvel = 0;
} else {
xvel = Math.round(xvel * -0.5);
}
}
if (clsdir == "bottom") {
if (yvel >= -4) {
yvel = 0;
} else {
yvel = Math.round(yvel * -0.5);
}
}
col = true;
}
// Die:
function die() {
circle.alpha = 1;
createjs.Tween.get(circle).to({
alpha: 0
}, 250).call(handleComplete);
function handleComplete() {
circle.x = stage.canvas.width / 2 - circle.radius;
circle.y = stage.canvas.height / 2 - circle.radius;
createjs.Tween.get(circle).to({
alpha: 1
}, 250);
yvel = 0;
xvel = 0;
yvelpast = 0;
xvelpast = 0;
}
yvel = yvel/2;
xvel = xvel/2;
}
// Set Intervals:
// Speed/Score:
setInterval(function () {
if (pause == false) {
speed = Math.abs(xvel) + Math.abs(yvel);
$(".speed").html("Speed: " + speed);
} else {
speed = Math.abs(xvelpast) + Math.abs(yvelpast);
$(".speed").html("Speed: " + speed + " (Paused)");
}
}, 175);
// Tick:
createjs.Ticker.on("tick", tick);
createjs.Ticker.setFPS(60);
function tick(event) {
// Input Handler:
if (up == true) {
yvel -= 2;
} else {
if (yvel < 0) {
yvel++;
}
}
if (left == true) {
xvel -= 2;
} else {
if (xvel < 0) {
xvel++;
}
}
if (right == true) {
xvel += 2;
} else {
if (xvel > 0) {
xvel--;
}
}
if (down == true) {
yvel += 2;
} else {
if (yvel > 0) {
yvel--;
}
}
// Volatility:
pastrmdir = rmdir;
rmdir = Math.floor((Math.random() * 20) + 1);
if (rmdir == 1 && pastrmdir != 4) {
yvel--;
}
if (rmdir == 2 && pastrmdir != 3) {
xvel--;
}
if (rmdir == 3 && pastrmdir != 2) {
xvel++;
}
if (rmdir == 4 && pastrmdir != 1) {
yvel++;
}
// Velocity limiter:
if (xvel > maxvel || xvel < maxvel * -1) {
(xvel > 0) ? xvel = maxvel : xvel = maxvel * -1;
}
if (yvel > maxvel || yvel < maxvel * -1) {
(yvel > 0) ? yvel = maxvel : yvel = maxvel * -1;
}
// Collision handler:
// xvel and yvel modifications must be before this!
rects.forEach(function (rect) { // Affect all rects
// Collision detection:
// (This MUST BE after every change in xvel/yvel)
// Next circle position calculation:
nextposx = circle.x + event.delta / 1000 * xvel * 30,
nextposy = circle.y + event.delta / 1000 * yvel * 30;
// Collision between objects (Rect and Circle):
if (nextposy + circle.height > rect.y && circle.y + circle.height < rect.y && circle.x + circle.width > rect.x && circle.x < rect.x + rect.width) {
cls("top");
}
if (nextposx + circle.width > rect.x && circle.x + circle.width < rect.x && circle.y + circle.height > rect.y && circle.y < rect.y + rect.height) {
cls("left");
}
if (nextposx < rect.x + rect.width && circle.x > rect.x + rect.width && circle.y + circle.height > rect.y && circle.y < rect.y + rect.height) {
cls("right");
}
if (nextposy < rect.y + rect.height && circle.y > rect.y + rect.height && circle.x + circle.width > rect.x && circle.x < rect.x + rect.width) {
cls("bottom");
}
rects.forEach(function (rect) {
// Check side-to-side collisions with other rects:
if (nextposy + circle.height > rect.y && circle.y + circle.height < rect.y && circle.x + circle.width > rect.x && circle.x < rect.x + rect.width) {
col = true;
}
if (nextposx + circle.width > rect.x && circle.x + circle.width < rect.x && circle.y + circle.height > rect.y && circle.y < rect.y + rect.height) {
col = true;
}
if (nextposx < rect.x + rect.width && circle.x > rect.x + rect.width && circle.y + circle.height > rect.y && circle.y < rect.y + rect.height) {
col = true;
}
if (nextposy < rect.y + rect.height && circle.y > rect.y + rect.height && circle.x + circle.width > rect.x && circle.x < rect.x + rect.width) {
col = true;
}
});
// Edge-to-edge collision between objects (Rect and Circle) - Note that this will not occur if a side-to-side collision occurred in the current frame!:
if (nextposy + circle.height > rect.y &&
nextposx + circle.width > rect.x &&
nextposx < rect.x + rect.width &&
nextposy < rect.y + rect.height &&
col == false) {
if (circle.y + circle.height < rect.y &&
circle.x + circle.width < rect.x) {
cls("top");
cls("left");
}
if (circle.y > rect.y + rect.height &&
circle.x + circle.width < rect.x) {
cls("bottom");
cls("left");
}
if (circle.y + circle.height < rect.y &&
circle.x > rect.x + rect.width) {
cls("top");
cls("right");
}
if (circle.y > rect.y + rect.height &&
circle.x > rect.x + rect.width) {
cls("bottom");
cls("right");
}
}
col = false;
// Stage collision:
if (nextposy < 0) { // Collided with TOP of stage. Trust me.
cls("bottom"); // Inverted clsdir is proposital!
}
if (nextposx < 0) {
cls("right");
}
if (nextposx + circle.width > stage.canvas.width) {
cls("left");
}
if (nextposy + circle.height > stage.canvas.height) {
cls("top");
}
});
// Laser collision handler:
lasers.forEach(function (laser) {
laser.alpha = Math.random() + 0.5;
nextposx = circle.x + event.delta / 1000 * xvel * 30,
nextposy = circle.y + event.delta / 1000 * yvel * 30;
if (nextposy + circle.height > laser.y && circle.y + circle.height < laser.y && circle.x + circle.width > laser.x && circle.x < laser.x + laser.width) {
circle.y = laser.y-circle.height;
die();
}
if (nextposx + circle.width > laser.x && circle.x + circle.width < laser.x && circle.y + circle.height > laser.y && circle.y < laser.y + laser.height) {
circle.x = laser.x-circle.width;
die();
}
if (nextposx < laser.x + laser.width && circle.x > laser.x + laser.width && circle.y + circle.height > laser.y && circle.y < laser.y + laser.height) {
circle.x = laser.x+laser.width;
die();
}
if (nextposy < laser.y + laser.height && circle.y > laser.y + laser.height && circle.x + circle.width > laser.x && circle.x < laser.x + laser.width) {
circle.y = laser.y+laser.height;
die();
}
});
// Velocity:
if (pause == true) {
xvel = 0;
yvel = 0;
}
circle.x += event.delta / 1000 * xvel * 20;
circle.y += event.delta / 1000 * yvel * 20;
// Stage.canvas 100% width and height:
stage.canvas.width = window.innerWidth;
stage.canvas.height = window.innerHeight;
// Update stage:
stage.update(event);
}
setTimeout(function () {
// Centre circle:
circle.x = stage.canvas.width / 2 - circle.radius;
circle.y = stage.canvas.height / 2 - circle.radius;
// Fade-in after loading:
$(".speed").css({
opacity: 1
});
$("canvas").css({
opacity: 1
});
}, 500);
}
$(function () {
init();
});
})();
</script>
<style>
* {
margin: 0;
}
html,
body {
-webkit-font-smoothing: antialiased;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
color: #fff;
background-color: #181818
}
.build {
position: absolute;
bottom: 5px;
right: 5px;
color: rgba(255, 255, 255, 0.05)
}
canvas {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
opacity: 0;
position: absolute;
top: 0;
left: 0;
-moz-transition: 5s ease;
-o-transition: 5s ease;
-webkit-transition: 5s ease;
transition: 5s ease
}
.speed {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
opacity: 0;
position: absolute;
top: 5px;
left: 5px;
color: #fff;
font-size: 16px;
-moz-transition: 5s ease;
-o-transition: 5s ease;
-webkit-transition: 5s ease;
transition: 5s ease
}
h2 {
text-align: center;
font-size: 22px;
font-weight: 700
}
p {
font-size: 16px;
margin: 0
}
</style>
</head>
<body>
<p class="speed"></p>
<p class="build">α256</p>
<canvas id="canvas">
<h2>Your browser doesn't support Canvas.</h2>
<p>Switch to <b>Chrome 33</b>, <b>Firefox 27</b> or <b>Safari 7</b>.</p>
</canvas>
</body>
</html>
最佳答案
游戏逻辑不是真正的问题,它慢的原因是你通过设置宽度和高度在每个刻度“创建”一个新的 Canvas :
stage.canvas.width = window.innerWidth;
stage.canvas.height = window.innerHeight;
因此,即使您将 Canvas 宽度和高度设置为相同的值,在引擎盖下也几乎构建了一个新 Canvas 。如果您从游戏循环中删除上面的行,它应该可以顺利运行。
只需设置一次 Canvas 宽度和高度,然后监听窗口调整大小并在浏览器窗口更改大小时设置它。
关于javascript - forEach inside Ticker 使 Canvas 变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22566527/
我已经在谷歌上搜索这个问题一段时间了,但我还没有找到有效的解决方案。 问题是 SSH 登录到我的服务器突然变得很慢。我可以看到身份验证需要大约 10 秒才能继续,这是我的 ssh 详细日志: Open
我正在使用 AVPlayer 在我的项目中播放在线视频。视频播放良好。现在我想减少/增加视频的 fps。以下是我正在使用的代码: self.asset = [AVAsset assetWithURL:
在 Raspberry Pi 上运行两个使用 python gpio 引脚的程序时,一个变慢。一种是磁传感器,另一种是温湿度传感器。后者是放慢速度的。它不是每 2 秒打印一次温度,而是每 5 到 10
我从 Redis 向我的应用程序提供一个 json,然后我对其进行解码和循环。 这是我从 Redis 提供的 json 的样子: [ { "titel": "test 1",
Ejabberd 版本:19.9.0 在发送 OMEMO 消息时(使用 websockets),例如
我们有相当大的代码库(150 多个项目、400000 多行 Java 代码、一些 Groovy 和 Gradle 代码、一些 Perl 代码、一些 XML、大量 JSP 等)。我设法在 Spring
我在一个网站上工作,您可以在其中创建 svg 艺术品,这意味着您可以动态添加元素、缩放、颜色并移动它们。 问题是,当你开始在他们身上施加阴影时,一切都会开始变慢。对于这个的现场演示,this是我正在开
有没有办法分析 Vim 插件? 当我打开一个大的 .py 时,我的 MacVim 变得越来越慢。我知道我可以取消选择所有插件并逐一重新选择以检查哪个插件是罪魁祸首,但是有没有更快的方法? 我的 dot
我正在构建一个JavaFX应用程序。我知道它使用反射,并且反射可能不如我在代码中构建 UI 时那么快。 所以, 如何设计我的 Controller 以使由反射引起的开销尽可能小? 带/不带 @FXML
我对 UITableViewCell 进行了子类化显示从 1 到 70 的数字。 在每个单元格中,我都在检查中奖号码并检查他们的背景。问题是,经过几次滚动后,tableview 变得非常缓慢,甚至无法
如果我想group_by 和filter 那些在数据集中有任何NA 或factor 值的,我想在 dplyr 中使用 any 函数,但发现它对 NAs 或 factor 运行缓慢(但不是为了寻找任何数
我有一个问题。在我的解决方案中,我需要将数千个数据插入数据库。我正在使用批处理准备语句在一个请求中插入多行。在我调用插入几次之后, hibernate 变得更慢了。 我猜它会在我提交后检查数据库是否有
我从 json url 获取数据,但是当我想加载图像时,速度非常慢! class NewsTableViewController: UITableViewController { var id
我有一个相当简单的托管 Realm 对象 RealmAlertItem由一些字符串和 float 组成。我有一个函数 showAlertNotification()随后被调用(从网络外部触发)并且它依
请参阅下面的表格结构。 CREATE TABLE `oarc` ( `ID` bigint(20) NOT NULL AUTO_INCREMENT, `zID` int(11) NOT N
IntelliJ 慢得像爬行。键之间没有 1-2 个延迟几乎无法打字。我已经更新了堆大小。我在我的 Macbook Pro 上运行大约 2GB RAM。自从它一直在放缓。我已经增加了堆大小,但无济于事
我的 Web 应用程序遇到了性能问题。发现瓶颈是db。应用程序在具有 4 个 CPU 和 2GB RAM 的 LAMP 服务器 (VPS) 上运行。 将新记录插入数据库(包含大约 100.000 条记
我有关于自定义 DispatchQueue 的问题。 我创建了一个队列,并将其用作captureOutput:方法的队列。这是一个代码片段: //At the file header private
我是一名移动 QA。现在我们有一个关于网络响应和 UI 渲染之间的竞争条件的问题。我们猜测如果 UI 渲染比网络响应慢,那么它就会崩溃。 我们已经尝试通过使用 Charles 的本地 map 功能来加
我在 firefox 中遇到了一些奇怪的行为,我正在构建一个单页作品集,作为一名平面设计师,编码一直很困难。我想平滑地控制导航,然后向所有元素添加缩放(最初设计为 1920x1080 全屏)。讲师扔了
我是一名优秀的程序员,十分优秀!