Javascript 仅在第一帧上读取鼠标位置
我在读画布上的鼠标位置时遇到了麻烦。当在IE中单击画布时,代码读取位置时(半)工作正常,但仅在一个帧上,在chrome中,它只是将值显示为0 以下是完整的代码:Javascript 仅在第一帧上读取鼠标位置,javascript,html,canvas,Javascript,Html,Canvas,我在读画布上的鼠标位置时遇到了麻烦。当在IE中单击画布时,代码读取位置时(半)工作正常,但仅在一个帧上,在chrome中,它只是将值显示为0 以下是完整的代码: <script> var blip = new Audio("blip.mp3"); blip.load(); var levelUp = new Audio("levelUp.mp3"); levelUp.load(); var c
<script>
var blip = new Audio("blip.mp3");
blip.load();
var levelUp = new Audio("levelUp.mp3");
levelUp.load();
var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
context.font = '18pt Calibri';
context.fillStyle = 'white';
//load and draw background image
var bgReady = false;
var background = new Image();
background.src = 'images/background.jpg';
background.onload = function(){
bgReady = true;
}
var startMessage = 'Click the canvas to start';
//load plane image
var planeReady = false;
var planeImage = new Image();
planeImage.src = 'images/plane.png';
planeImage.onload = function() {
planeReady = true;
}
//load missile image
var missileReady = false;
var missileImage = new Image();
missileImage.src = 'images/missile-flipped.gif';
missileImage.onload = function() {
missileReady = true;
}
//initialise lives and score
var score = 0;
var lives = 3;
var missilesLaunched = 0;
var missileSpeed = 5;
var level = 1;
var missileX = 960;
var missileY = Math.random() * 500;
if (missileY > 480) {
missileY = 480;
}
function getMousePos(canvas, event) {
return {
x: input.x - rect.left,
y: input.y - rect.top
};
}
function update_images(event) {
var pos = getMousePos(canvas.getBoundingClientRect(), mouseInput);
planeImage.y = pos.y;
missileX = missileX - missileSpeed;
if (missileX < - 70) {
missilesLaunched++;
missileX = 960;
missileY = Math.random() * 500;
if (missileY > 480) {
missileY = 480;
}
blip.play();
score = missilesLaunched;
if (score % 5 == 0) {
missileSpeed = missileSpeed + 2;
level++;
levelUp.play();
}
}
}
function reload_images() {
if (bgReady = true) {
context.drawImage(background, 0, 0);
}
if (planeReady = true) {
context.drawImage(planeImage, 10, planeImage.y);
}
if (missileReady = true) {
context.drawImage(missileImage, missileX, missileY);
}
context.fillText('Lives: ' + lives, 200, 30);
context.fillText('Score: ' + score, 650, 30);
context.fillText('Level: ' + missileSpeed, 420, 30);
context.fillText('Position: ' + missileImage.y, 420, 70);
}
function main(event) {
var mouseInput = { x: 0, y: 0 };
document.addEventListener("mousemove", function (event) {
mouseInput.x = event.clientX;
mouseInput.y = event.clientY;
});
update_images(event);
reload_images();
if (lives > 0) {
window.requestAnimationFrame(main);
}
else {
}
}
function start() {
context.drawImage(background, 0, 0);
context.fillText('Click the canvas to start', 350, 250);
function startMain(event) {
game.removeEventListener("click", startMain);
main(event);
}
canvas.addEventListener("mousedown", startMain);
}
start();
</script>
var blip=新音频(“blip.mp3”);
blip.load();
var levelUp=新音频(“levelUp.mp3”);
levelUp.load();
var canvas=document.getElementById('game');
var context=canvas.getContext('2d');
context.font='18pt Calibri';
context.fillStyle='white';
//加载并绘制背景图像
var bgrady=false;
var background=新图像();
background.src='images/background.jpg';
background.onload=函数(){
bgrady=true;
}
var startMessage='单击画布开始';
//加载平面图像
var planeReady=false;
var planeImage=新图像();
planeImage.src='images/plane.png';
planeImage.onload=函数(){
planeReady=true;
}
//加载导弹图像
var-missileReady=false;
var missileImage=新图像();
missleimage.src='images/flipled.gif';
missleimage.onload=函数(){
missileReady=正确;
}
//初始化生活和分数
var得分=0;
var=3;
var=0;
var missileSpeed=5;
风险等级=1;
var=960;
var missley=Math.random()*500;
如果(导弹>480){
米斯利=480;
}
函数getMousePos(画布、事件){
返回{
x:input.x-rect.left,
y:input.y-rect.top
};
}
函数更新\u图像(事件){
var pos=getMousePos(canvas.getBoundingClientRect(),mouseInput);
planeImage.y=位置y;
missileX=missileX-missileSpeed;
如果(导弹<-70){
导弹发射++;
missileX=960;
missileY=Math.random()*500;
如果(导弹>480){
米斯利=480;
}
blip.play();
分数=发射的导弹;
如果(分数%5==0){
导弹速度=导弹速度+2;
级别++;
levelUp.play();
}
}
}
函数reload_images(){
如果(bgrady=true){
drawImage(背景,0,0);
}
if(planeReady=true){
drawImage(planeImage,10,planeImage.y);
}
如果(missileReady=true){
drawImage(missileImage、missileX、missileY);
}
context.fillText('lifes:'+lifes,200,30);
context.fillText('Score:'+Score,650,30);
context.fillText('Level:'+missileSpeed,420,30);
context.fillText('Position:'+missileImage.y,420,70);
}
主功能(事件){
var mouseInput={x:0,y:0};
document.addEventListener(“mousemove”,函数(事件){
mouseInput.x=event.clientX;
mouseInput.y=event.clientY;
});
更新图片(事件);
重新加载_图像();
如果(寿命>0){
window.requestAnimationFrame(主);
}
否则{
}
}
函数start(){
drawImage(背景,0,0);
fillText('单击画布开始',350,250);
函数startMain(事件){
removeEventListener(“单击”,开始输入);
主要(活动);
}
canvas.addEventListener(“鼠标向下”,startMain);
}
start();
乔,你应该在每次点击时捕捉鼠标位置
…但实际上,每次单击也会启动一个新游戏(不停止旧游戏)
第一个问题:多次启动游戏引擎在画布的同一实例上绘制
解决方案:
在start
函数中,您需要在触发mousedown
事件侦听器后将其删除
function start () {
// ... other setup
function startMain (event) {
canvas.removeEventListener("click", startMain);
main(event);
}
canvas.addEventListener("click", startMain);
}
现在,它只会在开始之前监听第一次单击,并且只会启动一次
第二个问题:鼠标未按预期更新
解决方案:这里有两个问题。。。
…首先,您在第一次调用时将事件
传递到main
。。。
…然后,将main
传递到requestAnimationFrame
requestAnimationFrame
不会使用事件调用它,它将使用自页面加载以来的微秒数(或毫秒或其他单位作为毫秒的分数精度)调用它
所以第一次得到main({type:“mousedown”,…})代码>
下一次获取main时(4378.00235807)代码>
因此,让我们重构上面的startMain
,以便main
永远不会收集事件,只收集一次
function startMain ( ) {
canvas.removeEventListener("click", startMain);
requestAnimationFrame(main);
}
下一个问题是,即使您只获得了事件,您也只捕获了一个点击事件(正如我们前面提到的,它触发了游戏逻辑的新副本)
您的解决方案是将捕获鼠标事件的代码与读取鼠标位置的代码分开
var mouseInput = { x: 0, y: 0 };
document.addEventListener("mousemove", function (event) {
mouseInput.x = event.clientX;
mouseInput.y = event.clientY;
});
function getMousePos (rect, input) {
return {
x : input.x - rect.left,
y : input.y - rect.top
};
}
// currently in updateImages (should not be there, but... a different story)
var pos = getMousePos(canvas.getBoundingClientRect(), mouseInput);
你还有其他问题…
您正在调用getMousePos
并正在传入game
。我看不出你的JS中在哪里定义了游戏
,所以要么你在别的地方制作游戏
(乞求bug),,要么它是未定义的
,你的应用程序就在那里爆炸了