- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想让我的游戏可以探索,我们可以在 map 上四处移动。我尽力实现了这段代码:https://jsfiddle.net/gfcarv/QKgHs/但它对我不起作用,我尝试通过多种方式解决这个问题,我搜索了互联网,但找不到任何适合我的代码的简单视口(viewport)。
我只想让玩家始终处于 Canvas 的中间,当我们单击(或按住单击)时它会移动 map ,但每个游戏对象都保持在它们的位置。如果它到达 map 的任何一侧,只要让它这样做,它就可以越过 map 。我想要 map ,简单的图像或一些生成的 Canvas 矩形,或其他任何东西。
这是我的简化代码:
function randomNumberFromRange( min, max ) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function testCollisionRectRect( rectangle1, rectangle2 ) {
return rectangle1.x - rectangle1.width/2 <= rectangle2.x - rectangle2.width/2 + rectangle2.width
&& rectangle2.x - rectangle2.width/2 <= rectangle1.x - rectangle1.width/2 + rectangle1.width
&& rectangle1.y - rectangle1.height/2 <= rectangle2.y - rectangle2.height/2 + rectangle2.height
&& rectangle2.y - rectangle2.height/2 <= rectangle1.y - rectangle1.height/2 + rectangle1.height;
}
Array.prototype.remove = function() {
var what, a = arguments, L = a.length, ax;
while (L && this.length) {
what = a[--L];
while ((ax = this.indexOf(what)) !== -1) {
this.splice(ax, 1);
}
}
return this;
}; // Function to pop specific element drom array by value
function drawLine( startX, startY, endX, endY, color, width ) {
ctx.save();
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.beginPath();
ctx.moveTo(startX,startY);
ctx.lineTo(endX,endY);
ctx.stroke();
ctx.restore();
}
function drawBorder( x, y, width, height, lineWidth, strokeColor ) {
ctx.save();
ctx.lineWidth = lineWidth;
ctx.strokeStyle = strokeColor;
ctx.strokeRect( x, y, width, height);
ctx.restore();
}
function drawRect( x, y, width, height, fillColor ) {
ctx.save();
ctx.fillStyle = fillColor;
ctx.fillRect( x, y, width, height );
ctx.restore();
}
// ====================
// Global variables
// ====================
var ctx = $("#canvas")[0].getContext('2d'),
canvas = document.getElementById('canvas'),
cHeight = canvas.height = 500,
cWidth = canvas.width = 500,
canvasOffset = $('#canvas').offset(),
offsetX = canvasOffset.left,
offsetY = canvasOffset.top,
frameCounter = 0,
enemyList = [],
spawningEnemies_FLAG = true,
isLeftMouseButtonHeld_FLAG = false,
cursors = ['default', 'pointer'],
enemiesOnMap = 100,
fps = 120,
mouseX,
mouseY;
// canvas settings
ctx.font = '22px Arial';
var sharedBehaviour = {
x: cWidth / 2,
y: cHeight / 2,
id: undefined,
type: 'entity',
width: 15,
height: 15,
fillColor: '#E15258',
targetX: null,
targetY: null,
bulletSpeed: 1,
speed: 1,
update( type ) {
// if there is target
if( this.targetX !== null ) {
// Find out distance to target
var distanceX = this.targetX - this.x; // distance on X axis
var distanceY = this.targetY - this.y; // distance on Y axis
var distanceToTarget = Math.sqrt( distanceX*distanceX + distanceY*distanceY ); // distance
// If distance is smaller or equal speed, then just set position
if( distanceToTarget <= this.speed ) {
this.x = this.targetX;
this.y = this.targetY;
// Then reset
this.targetX = this.targetY = null;
} else { // If distance is bigger than speed, so we want to move with speed
distanceX = distanceX / distanceToTarget;
distanceY = distanceY / distanceToTarget;
distanceX = distanceX * this.speed;
distanceY = distanceY * this.speed;
this.x += distanceX;
this.y += distanceY;
}
}
},
draw( type ) {
drawRect( this.x - this.width/2, this.y - this.height/2, this.width, this.height, this.fillColor );
},
isColliding( entity ) {
return testCollisionRectRect( this, entity );
}
};
var player = Object.assign({}, sharedBehaviour, {
x: cWidth/2 - 12.5,
y: cHeight/2 - 12.5,
id: 980722,
type: 'player',
width: 25,
height: 25,
fillColor: '#82d877',
speed: 2.5,
isWithinRange( entity, val ) {
// Check if enemy is on player
var distanceX = this.x - entity.x;
var distanceY = this.y - entity.y;
return Math.sqrt( distanceX*distanceX + distanceY*distanceY ) < val;
}
});
function createEnemy( x, y, type, width, height, fillColor, speed, name ) {
var newEnemy = Object.assign({}, sharedBehaviour, {
x,
y,
type,
width,
height,
name,
fillColor,
speed,
setTarget( entity ) {
this.targetX = entity.x + randomNumberFromRange(-50, 50); // Set X with some random number
this.targetY = entity.y + randomNumberFromRange(-50, 50); // Set Y with some random number
},
isOnPlayer( val ) {
// Check if enemy is on player
var distanceX = player.x - this.x;
var distanceY = player.y - this.y;
return Math.sqrt( distanceX*distanceX + distanceY*distanceY ) < val;
},
isMouseOver( ) {
return (this.mouseX + this.width/2 >= this.x && this.mouseX + this.width/2 <= this.x + this.width && this.mouseY + this.height/2 >= this.y && this.mouseY + this.height/2 <= this.y + this.height);
}
});
enemyList.push( newEnemy );
}
function newGame( ) {
player.x = cWidth/2 - 12.5;
player.y = cHeight/2 - 12.5;
frameCounter = 0;
enemyList = [];
spawningEnemies_FLAG = true;
isLeftMouseButtonHeld_FLAG = false;
// Spawning enemies
for( i=0; i < randomNumberFromRange(15, 25); i++ ) {
createEnemy( randomNumberFromRange(0, cWidth), randomNumberFromRange(0, cHeight), 'passive', randomNumberFromRange(12, 18), randomNumberFromRange(12, 18), 'red', 1, 's' );
createEnemy( randomNumberFromRange(0, cWidth), randomNumberFromRange(0, cHeight), 'agressive', randomNumberFromRange(10, 16), randomNumberFromRange(10, 16), 'lightblue', 1.5, 'l' );
}
update();
}
function update( ) {
frameCounter++;
ctx.clearRect(0,0,cWidth,cHeight);
// ========== Update ==========
// Player
player.update('player');
// Enemies
enemyList.forEach( enemy => { enemy.update(); });
// ========== Draw ==========
// Enemies
enemyList.forEach( enemy => { enemy.draw(); });
// Player
player.draw('player');
// ========== Conditions ==========
// Enemies
// Behaviour
enemyList.forEach( enemy => {
if ( Math.random() < ( 1 / 15 ) ) {
if ( enemy.isOnPlayer( player.circleRadius ) ) {
if ( ! (enemy.isOnPlayer( 50 )) ) {
enemy.setTarget( player );
}
}
}
if ( Math.random() < ( 1 / 800 )) {
if ( ! (enemy.isOnPlayer( player.circleRadius )) ) enemy.setTarget( enemy );
}
if ( enemy.isOnPlayer(player.circleRadius/2 - 25 ) ) {
enemy.targetX = enemy.targetY = null;
}
( enemyList.length === enemiesOnMap ) ? spawningEnemies_FLAG = false : spawningEnemies_FLAG = true;
});
setTimeout(function() { requestAnimationFrame(update); }, 1000 / fps);
}
function setPlayerTarget_and_checkPlayerPosition( mouse ) {
player.targetX = mouseX;
player.targetY = mouseY;
if (player.targetX < player.width/2) player.targetX = player.width/2;
if (player.targetX > cWidth - player.width/2) player.targetX = cWidth - player.width/2;
if (player.targetY < player.height/2) player.targetY = player.height/2;
if (player.targetY > cHeight - player.height/2) player.targetY = cHeight - player.height/2;
}
canvas.addEventListener('mousedown', function( mouse ) {
isLeftMouseButtonHeld_FLAG = true;
setPlayerTarget_and_checkPlayerPosition(mouse);
});
canvas.addEventListener('mouseup', function( mouse ) {
isLeftMouseButtonHeld_FLAG = false;
});
canvas.addEventListener('mousemove', function( mouse ) {
if( isLeftMouseButtonHeld_FLAG ) {
setPlayerTarget_and_checkPlayerPosition(mouse);
}
});
canvas.addEventListener('mousemove', function( mouse ) {
mouseX = parseInt(mouse.clientX - offsetX);
mouseY = parseInt(mouse.clientY - offsetY);
});
newGame();
canvas { border: 1px solid black; background-color: white; }
<canvas id="canvas"></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
最佳答案
移动视口(viewport)以使玩家保持居中非常容易:
您可以简单地使用 ctx.setTransform(1, 0, 0, 1, centerX - player.x, centerY - player.Y)
;
现在,根据您当前的鼠标逻辑,您实际上需要一个 viewPort
对象,它只有两个属性 x
和 y
这样您就可以仍能获得光标与播放器之间的正确距离。
您显然还需要删除在 setPlayerTarget_and_checkPlayerPosition
函数中所做的边界检查。
function randomNumberFromRange( min, max ) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function testCollisionRectRect( rectangle1, rectangle2 ) {
return rectangle1.x - rectangle1.width/2 <= rectangle2.x - rectangle2.width/2 + rectangle2.width
&& rectangle2.x - rectangle2.width/2 <= rectangle1.x - rectangle1.width/2 + rectangle1.width
&& rectangle1.y - rectangle1.height/2 <= rectangle2.y - rectangle2.height/2 + rectangle2.height
&& rectangle2.y - rectangle2.height/2 <= rectangle1.y - rectangle1.height/2 + rectangle1.height;
}
Array.prototype.remove = function() {
var what, a = arguments, L = a.length, ax;
while (L && this.length) {
what = a[--L];
while ((ax = this.indexOf(what)) !== -1) {
this.splice(ax, 1);
}
}
return this;
}; // Function to pop specific element drom array by value
function drawLine( startX, startY, endX, endY, color, width ) {
ctx.save();
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.beginPath();
ctx.moveTo(startX,startY);
ctx.lineTo(endX,endY);
ctx.stroke();
ctx.restore();
}
function drawBorder( x, y, width, height, lineWidth, strokeColor ) {
ctx.save();
ctx.lineWidth = lineWidth;
ctx.strokeStyle = strokeColor;
ctx.strokeRect( x, y, width, height);
ctx.restore();
}
function drawRect( x, y, width, height, fillColor ) {
ctx.save();
ctx.fillStyle = fillColor;
ctx.fillRect( x, y, width, height );
ctx.restore();
}
// ====================
// Global variables
// ====================
var ctx = $("#canvas")[0].getContext('2d'),
canvas = document.getElementById('canvas'),
cHeight = canvas.height = 500,
cWidth = canvas.width = 500,
canvasOffset = $('#canvas').offset(),
offsetX = canvasOffset.left,
offsetY = canvasOffset.top,
frameCounter = 0,
enemyList = [],
spawningEnemies_FLAG = true,
isLeftMouseButtonHeld_FLAG = false,
cursors = ['default', 'pointer'],
enemiesOnMap = 100,
fps = 120,
mouseX,
mouseY;
// canvas settings
ctx.font = '22px Arial';
var viewPort = {
x: cWidth/2,
y: cHeight/2,
update() {
this.x = cWidth / 2 - player.x;
this.y = cHeight / 2 - player.y;
}
};
var sharedBehaviour = {
x: cWidth / 2,
y: cHeight / 2,
id: undefined,
type: 'entity',
width: 15,
height: 15,
fillColor: '#E15258',
targetX: null,
targetY: null,
bulletSpeed: 1,
speed: 1,
update( type ) {
// if there is target
if( this.targetX !== null ) {
// Find out distance to target
var distanceX = this.targetX - this.x; // distance on X axis
var distanceY = this.targetY - this.y; // distance on Y axis
var distanceToTarget = Math.sqrt( distanceX*distanceX + distanceY*distanceY ); // distance
// If distance is smaller or equal speed, then just set position
if( distanceToTarget <= this.speed ) {
this.x = this.targetX;
this.y = this.targetY;
// Then reset
this.targetX = this.targetY = null;
} else { // If distance is bigger than speed, so we want to move with speed
distanceX = distanceX / distanceToTarget;
distanceY = distanceY / distanceToTarget;
distanceX = distanceX * this.speed;
distanceY = distanceY * this.speed;
this.x += distanceX;
this.y += distanceY;
}
}
},
draw( type ) {
drawRect( this.x - this.width/2, this.y - this.height/2, this.width, this.height, this.fillColor );
},
isColliding( entity ) {
return testCollisionRectRect( this, entity );
}
};
var player = Object.assign({}, sharedBehaviour, {
x: cWidth/2 - 12.5,
y: cHeight/2 - 12.5,
id: 980722,
type: 'player',
width: 25,
height: 25,
fillColor: '#82d877',
speed: 2.5,
isWithinRange( entity, val ) {
// Check if enemy is on player
var distanceX = this.x - entity.x;
var distanceY = this.y - entity.y;
return Math.sqrt( distanceX*distanceX + distanceY*distanceY ) < val;
}
});
function createEnemy( x, y, type, width, height, fillColor, speed, name ) {
var newEnemy = Object.assign({}, sharedBehaviour, {
x,
y,
type,
width,
height,
name,
fillColor,
speed,
setTarget( entity ) {
this.targetX = entity.x + randomNumberFromRange(-50, 50); // Set X with some random number
this.targetY = entity.y + randomNumberFromRange(-50, 50); // Set Y with some random number
},
isOnPlayer( val ) {
// Check if enemy is on player
var distanceX = player.x - this.x;
var distanceY = player.y - this.y;
return Math.sqrt( distanceX*distanceX + distanceY*distanceY ) < val;
},
isMouseOver( ) {
return (this.mouseX + this.width/2 >= this.x && this.mouseX + this.width/2 <= this.x + this.width && this.mouseY + this.height/2 >= this.y && this.mouseY + this.height/2 <= this.y + this.height);
}
});
enemyList.push( newEnemy );
}
function newGame( ) {
player.x = cWidth/2 - 12.5;
player.y = cHeight/2 - 12.5;
frameCounter = 0;
enemyList = [];
spawningEnemies_FLAG = true;
isLeftMouseButtonHeld_FLAG = false;
// Spawning enemies
for( i=0; i < randomNumberFromRange(15, 25); i++ ) {
createEnemy( randomNumberFromRange(0, cWidth), randomNumberFromRange(0, cHeight), 'passive', randomNumberFromRange(12, 18), randomNumberFromRange(12, 18), 'red', 1, 's' );
createEnemy( randomNumberFromRange(0, cWidth), randomNumberFromRange(0, cHeight), 'agressive', randomNumberFromRange(10, 16), randomNumberFromRange(10, 16), 'lightblue', 1.5, 'l' );
}
update();
}
function update( ) {
frameCounter++;
ctx.setTransform(1,0,0,1,0,0); // reset before clearing
ctx.clearRect(0,0,cWidth,cHeight);
// ========== Update ==========
// Player
player.update('player');
// Enemies
enemyList.forEach( enemy => { enemy.update(); });
// viewPort
viewPort.update()
// ========== Draw ==========
// viewPort
ctx.setTransform(1,0,0,1, viewPort.x, viewPort.y);
// Enemies
enemyList.forEach( enemy => { enemy.draw(); });
// Player
player.draw('player');
// ========== Conditions ==========
// Enemies
// Behaviour
enemyList.forEach( enemy => {
if ( Math.random() < ( 1 / 15 ) ) {
if ( enemy.isOnPlayer( player.circleRadius ) ) {
if ( ! (enemy.isOnPlayer( 50 )) ) {
enemy.setTarget( player );
}
}
}
if ( Math.random() < ( 1 / 800 )) {
if ( ! (enemy.isOnPlayer( player.circleRadius )) ) enemy.setTarget( enemy );
}
if ( enemy.isOnPlayer(player.circleRadius/2 - 25 ) ) {
enemy.targetX = enemy.targetY = null;
}
( enemyList.length === enemiesOnMap ) ? spawningEnemies_FLAG = false : spawningEnemies_FLAG = true;
});
// this is bad vvv
// setTimeout(function() {
requestAnimationFrame(update);
//}, 1000 / fps);
}
function setPlayerTarget_and_checkPlayerPosition( mouse ) {
player.targetX = mouseX;
player.targetY = mouseY;
// a few lines are gone here...
}
canvas.addEventListener('mousedown', function( mouse ) {
isLeftMouseButtonHeld_FLAG = true;
setPlayerTarget_and_checkPlayerPosition(mouse);
});
canvas.addEventListener('mouseup', function( mouse ) {
isLeftMouseButtonHeld_FLAG = false;
});
canvas.addEventListener('mousemove', function( mouse ) {
if( isLeftMouseButtonHeld_FLAG ) {
setPlayerTarget_and_checkPlayerPosition(mouse);
}
});
canvas.addEventListener('mousemove', function( mouse ) {
var rect = canvas.getBoundingClientRect(); // offset may change in snippets
mouseX = parseInt(mouse.clientX - rect.left - viewPort.x);
mouseY = parseInt(mouse.clientY - rect.top - viewPort.y);
});
newGame();
canvas { border: 1px solid black; background-color: white; }
<canvas id="canvas"></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
关于javascript - Canvas 简单游戏视口(viewport),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45277706/
我可以使用两种方法添加一个 child ,一种是 Canvas.AddVisualChild(Visual); Canvas.AddLogicalChild(Visual); 我在视觉对象的 Draw
在过去的几周里,我一直在尝试各种方法,试图找到将 BDD 用于依赖于 HTML5 Canvas 元素以及用户与之交互的 Web 应用程序的最佳方法。 我一直在使用 Jasmine 和 Cucumber
我正在尝试完成撤消/重做。我正在使用loadFromJSON(...)从我存储在数组中的 Canvas 状态重新构建 Canvas 。基本上,我的想法是破坏现有的 Canvas 并重新构建 Canva
我正在尝试在 Canvas 上设置简单的放大/缩小功能。我正在使用 KineticJS 处理触摸事件并在 Canvas 中绘图,但无法实现缩放。 KinteicJS 有一个类似的例子,但它们总是在中心
我正在使用 processing.js 在 javascript 中开发一个画笔应用程序 它正在使用 Canvas 对象。我想在 Canvas 的背景中保留一个图像。在前景中画一些东西。在保存时,我只
您好,我想为 discord.js Bot 安装 Canvas 。 当我尝试使用以下命令安装 Canvas 时npm install canvas我收到以下错误: pi@server:~/Bots/D
我正在尝试使用 Canvas 和动力学的组合来构建填充图案,但在尝试获得连续线时遇到了问题。 此 jsfiddle显示了到目前为止我所拥有的,但是因为我的重复模式是正方形,角会影响线条,我尝试使用 l
我正在开发一个 webassembly 程序。 我可以使用 emscripten_set_canvas_size 设置 Canvas 大小(我一直读到我需要切换到新的 API,因为这个 API 会贬值
您好,我已经为第一个 Canvas 中的第一个图像创建了一个圆形表单,但我没有成功使用第一个 Canvas 的 dataURL 并将其添加到第二个 Canvas 中。 这是我的 fiddle :htt
问题在于不同浏览器之间的不一致。 使用Dart Chrome,JS Chrome,JS Opera运行 双击可以进入和退出全屏 m_oCanvas.width =(window.screen.widt
我正在使用Flutter框架和Dart开发图像编辑器,因此无法将矩阵滤镜应用于 Canvas 。 我正在尝试使用“Paint”类和“canvas.drawPaint(paint)”函数将矩阵过滤器应用
如果在已经具有非整数比例因子的 Canvas 上绘制图像,我会遇到 Canvas 上下文drawImage()方法的问题。似乎这样的图像以一种奇怪的方式被剪切(有时图像的最右边的部分被剪切,有时是最底
Canvas 的“宽度”属性值有限制吗? 在下面的示例中,我在 ScrolledWindow 中创建一个 Canvas。 # Packages package require BWidget # Ma
我正在尝试制作类似于 this article 底部的效果的文本效果 我建议的方法是: 制作两个 Canvas ,一个是可见的,另一个是不可见的我用它作为缓冲区。 在缓冲区 Canvas 上绘制一些文
例如var new = canvas.toDataURL("image/png"); 我希望这个新变量中存在的 base64 显示到存在的第二个 Canvas 元素中。但是它不使用 drawimage
有人有使用这两个 Node.js 库中的一个或两个的经验吗?很想知道每个人的成功或困难。 最佳答案 LearnBoost是社区中最多产的 Node 模块开发人员之一,因此我选择使用 node-canv
如何知道 Canvas 运行的是“WebGL”还是普通 Canvas ? 通过检查源代码,我发现这两种情况都是 Canvas 。 最佳答案 这真的取决于你想如何去发现。 例如你可以这样调用 `getC
在 Canvas 上绘图非常好。甚至橡皮擦也能正常工作。问题是,当 Canvas 保存为图像时,它绘制的是黑线而不是橡皮擦。 为了更好地理解,我添加了屏幕截图和代码。 1。在删除绘图时 - 一个。源代
我正在尝试为 Canvas 附加鼠标悬停和鼠标移出事件: 默认 Canvas 是函数drawcircle的 Canvas 。 如果用户越过 Canvas ,应将其更改为drawEllipse的 Can
我正在使用 Three.js 构建一个简单的 2D 游戏。我只使用世界的 X 和 Y 位置来移动对象,将它们的 z 位置保留为零。我使用禁用旋转的 TrackballControls,以允许使用右键单
我是一名优秀的程序员,十分优秀!