我是使用JavaScript进行编程并使用画布的新手。
我正在编写一个游戏作为一个有趣的副项目。我在游戏中遇到了一个错误,当用户鼠标在各种不可预测的地方点击屏幕时,背景将开始越来越快地加速。我的游戏根据Player1的速度以增量方式移动Player1和背景。我最好的猜测是以某种方式当用户点击屏幕时,this.drawX + = this.speed在循环重新启动之前被多次计算并调用requestAnimationFrame。这是地图和玩家绘制功能的代码片段。此函数是播放器对象的原型。
// Canvas Context's
var canvasBg = document.getElementById('canvasBg');
var ctxBg = canvasBg.getContext('2d');
var canvasPlanets = document.getElementById('canvasPlanets');
var ctxPlanets = canvasPlanets.getContext('2d');
var canvasShip = document.getElementById('canvasShip');
var ctxShip = canvasShip.getContext('2d');
var canvasHUD = document.getElementById('canvasHUD');
var ctxHUD = canvasHUD.getContext('2d');
var canvasWindow = document.getElementById('canvasWindow');
var ctxWindow = canvasWindow.getContext('2d');
var canvasButtons = document.getElementById('canvasButtons');
var ctxButtons = canvasButtons.getContext('2d');
// ----------------------------------End Canvas Context
ctxHUD.fillStyle = "#fff";
ctxHUD.font = "bold 20px Arial";
ctxWindow.fillStyle = "#fff";
ctxWindow.font = "bold 16px Helvica";
var MAXspeed = 10;
var MINspeed = 2;
var inSpace = true;
var onSurface = false;
// Objects
var Player1;
var Planet1;
var Resource_0001;
var LandBtn = new Button(560,380,"Land");
var SpaceBtn = new Button(710,10,"Orbit");
var CloseBtn = new Button(620,140,"Close");
CloseBtn.srcY = 60;
CloseBtn.srcW = 39;
CloseBtn.srcH = 39;
CloseBtn.width = 39;
CloseBtn.height = 39;
CloseBtn.showText = false;
//-----end Objects
var SurfaceX = 0;
var SurfaceMap = 0;
var SurfaceMap2 = -1600;
var SpaceMapX = 0;
var SpaceMapY = 0;
var Flag = false;
var gameWidth = canvasBg.width;
var gameHeight = canvasBg.height;
var mouseX = -1;
var mouseY = -1;
var mouseIsDown = false;
var isPlaying = false;
var requestAnimFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame;
// Load Images
var imgMap = new Image();
imgMap.src = 'images/Bg.png';
var imgButtons = new Image();
imgButtons.src = 'images/button_sprite.png';
var windowIsOpen = false;
var imgBlueWindow = new Image();
imgBlueWindow.src = 'images/blue_window.png';
var imgSprite = new Image();
imgSprite.src = 'images/sprite.png';
var imgPlanets = new Image();
imgPlanets.src = 'images/earthlike_p1.png';
var imgBluesky1 = new Image();
imgBluesky1.src = 'images/bluesky1.png';
// ------------- End Loading Images
ctxBg.drawImage(imgMap,0,0,gameWidth,gameHeight,0,0,gameWidth,gameHeight);
imgMap.addEventListener('load',init,false);
// Main Functions
function init(){
Player1 = new Ship();
Planet1 = new Planet();
Planet2 = new Planet();
Planet2.coordX = 2434;
Planet2.coordY = 2550;
Planet2.height = 75;
Planet2.width = 75;
Planet2.planetType = "Medium Earthlike."
document.addEventListener('keydown',checkKeyDown,false);
document.addEventListener('keyup',checkKeyUp,false);
document.addEventListener("mousedown", checkMouseDown, false);
document.addEventListener("mouseup", checkMouseUp, false);
startLoop();
}
function loop() {
if (isPlaying) {
clearCtx();
Player1.draw();
Planet1.draw();
Planet2.draw();
if(Player1.speed >= MAXspeed) Player1.speed = MAXspeed;
if(Player1.speed <= MINspeed) Player1.speed = MINspeed;
requestAnimFrame(loop);
}
}
function startLoop() {
clearCtx();
clearMouse();
isPlaying = true;
if(inSpace) loop();
if(onSurface) planetSurface();
}
function stopLoop() {
isPlaying = false;
}
// End of main functions
function ifClicked(obj){
if(mouseX >= obj.drawX && mouseX <= obj.drawX + obj.width){
if(mouseY >= obj.drawY && mouseY <= obj.drawY + obj.height){
obj.isClicked = true;
}
}
else{
obj.isClicked = false;
}
if(obj.onSurface === true){
if(mouseX >= obj.surfX && mouseX <= obj.surfX + obj.width){
if(mouseY >= obj.surfY && mouseY <= obj.surfY + obj.height){
obj.isClicked = true;
}
}
else{
obj.isClicked = false;
}
}
}
function landOnSurface(){
inSpace = false;
onSurface = true;
Resource_0001 = new Resource("Wood");
Resource_0002 = new Resource("Alloy");
Resource_0002.coordX = 1600;
Player1.speed = 10;
Player1.onSurface = true;
startLoop();
}
function planetSurface(){
if (isPlaying) {
if(onSurface){
clearCtx();
Player1.draw();
Resource_0001.draw();
Resource_0002.draw();
SpaceBtn.draw();
if(Player1.speed >= MAXspeed) Player1.speed = MAXspeed;
if(Player1.speed <= MINspeed) Player1.speed = MINspeed;
requestAnimFrame(planetSurface);
}
}
}
// --------------------------------------------------------------OBJECTS
// ---------------Button Object --------------------------------------->>>>>>
function Button(X,Y,TYPE){
this.drawX = X || 0; // 560
this.drawY = Y || 0; // 380
this.buttonType = TYPE || "";
this.srcX = 0;
this.srcY = 0;
this.srcH = 30;
this.srcW = 70;
this.width = 70;
this.height = 30;
this.isClicked = false;
this.showText = true;
}
Button.prototype.draw = function(){
ctxButtons.fillStyle = "#fff";
ctxButtons.font = "bold 14px Helvica";
ctxButtons.shadowColor = "#000";
ctxButtons.shadowBlur = 2;
ctxButtons.shadowOffsetX = 2;
ctxButtons.shadowOffsetY = 2;
ctxButtons.drawImage(imgButtons,this.srcX,this.srcY,this.srcW,this.srcH,this.drawX,this.drawY,this.width,this.height);
if(this.showText) ctxButtons.fillText(" " + this.buttonType,this.drawX + 15,this.drawY + 20);
};
Button.prototype.wasClicked = function(){
ifClicked(this);
if(this.isClicked){
if(this.buttonType === "Land"){
stopLoop();
windowIsOpen = false;
landOnSurface();
}
if(this.buttonType === ""){
ctxButtons.clearRect(0,0,gameWidth,gameHeight);
}
if(this.buttonType === "Orbit"){
stopLoop();
inSpace = true;
onSurface = false;
Player1.speed = MINspeed;
Player1.onSurface = false;
startLoop();
}
if(this.buttonType === "Close"){
windowIsOpen = false;
ctxButtons.clearRect(0,0,gameWidth,gameHeight);
ctxWindow.clearRect(0,0,gameWidth,gameHeight);
startLoop();
}
}
};
//----------------------------------------------- End of Button Object -----------<<<<<<<<<<<<<<<<<<<<<<<<<<<
//--------------------------------- Resource Nodes ---------------->>>>>>>>>>>>>>
function Resource(TYPE){
this.srcX = 0;
this.srcY = 70;
this.srcH = 75;
this.srcW = 75;
this.width = 25;
this.height = 25;
this.coordX = -1020;
this.drawY = 420;
this.drawX = this.coordX - SurfaceX;
this.ResourceType = TYPE || "Water";
this.isClicked = false;
}
Resource.prototype.getResourceType = function(){
if(this.ResourceType === "Oil") this.srcX = 0;
if(this.ResourceType === "Alloy") this.srcX = 75;
if(this.ResourceType === "Wood") this.srcX = 150;
if(this.ResourceType === "Diamond") this.srcX = 225;
if(this.ResourceType === "Organics") this.srcX = 300;
if(this.ResourceType === "Water") this.srcX = 375;
};
Resource.prototype.draw = function(){
ctxPlanets.shadowColor = "#222";
ctxPlanets.shadowBlur = 1;
ctxPlanets.shadowOffsetX = 2;
ctxPlanets.shadowOffsetY = 2;
this.drawX = this.coordX - SurfaceX;
this.getResourceType();
ifClicked(this);
if(this.isClicked) this.openWindow();
ctxPlanets.drawImage(imgSprite,this.srcX,this.srcY,this.srcW,this.srcH,this.drawX,this.drawY,this.width,this.height);
};
Resource.prototype.openWindow = function(){
ctxWindow.drawImage(imgBlueWindow,0,0,gameWidth,gameHeight,0,0,gameWidth,gameHeight);
ctxWindow.fillText("Resource Type: " + this.ResourceType, 220,210);
windowIsOpen = true;
CloseBtn.draw();
stopLoop();
};
//-----------------------------------End Of Resource Nodes ------------------------------<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,
// Planet Functions
function Planet(){
this.srcX = 0;
this.srcY = 0;
this.srcW = 100;
this.srcH = 100;
this.width = 50;
this.height = 50;
this.coordX = 400;
this.coordY = 400;
this.planetType = "Small Earthlike."
this.drawX = this.coordX - SpaceMapX;
this.drawY = this.coordY - SpaceMapY;
this.isClicked = false;
this.nearShip = false;
}
Planet.prototype.draw = function(){
this.drawX = this.coordX - SpaceMapX;
this.drawY = this.coordY - SpaceMapY;
ctxPlanets.drawImage(imgPlanets,this.srcX,this.srcY,this.srcW,this.srcH,this.drawX,this.drawY,this.width,this.height);
ifClicked(this);
if(this.isClicked) this.openWindow();
this.shipInRange(Player1);
};
Planet.prototype.shipInRange = function(obj){
if(obj.drawX + obj.width >= this.drawX - (obj.width * 2) || obj.drawY + obj.height >= this.drawY - (obj.height * 2)){
this.nearShip = true;
}
if(obj.drawX + obj.width <= this.drawX - (obj.width * 2) || obj.drawY + obj.height <= this.drawY - (obj.height * 2)){
this.nearShip = false;
}
if(obj.drawX >= this.drawX + this.width + (obj.width * 2) || obj.drawY >= this.drawY + this.height + (obj.height * 2)){
this.nearShip = false;
}
};
Planet.prototype.openWindow = function(){
ctxButtons.clearRect(0,0,gameWidth,gameHeight);
ctxWindow.clearRect(0,0,gameWidth,gameHeight);
if(this.nearShip){
LandBtn.draw();
}
CloseBtn.draw();
ctxWindow.drawImage(imgBlueWindow,0,0,gameWidth,gameHeight,0,0,gameWidth,gameHeight);
ctxWindow.fillText("Planet Type: " + this.planetType, 220,210);
windowIsOpen = true;
stopLoop();
};
function DrawSurfaceImg(){
if(SurfaceMap2 >= 0) SurfaceMap2 = -1600;
if(SurfaceMap2 < -1600) SurfaceMap2 = -1;
if(SurfaceMap >= 1600) SurfaceMap = 0;
if(SurfaceMap < 0) SurfaceMap = 1599;
ctxBg.drawImage(imgBluesky1, 0, 0, 1600, gameHeight, SurfaceMap, 0, 1600, gameHeight);
ctxBg.drawImage(imgBluesky1, 0, 0, 1600, gameHeight, SurfaceMap2, 0, 1600, gameHeight);
}
//------------------------End of Planet Functions
// Bullet Functions
/*------------------------------------------------------------------------------------------------
function Bullet(){
this.speed = 5;
this.drawX = -100;
this.drawY = 0;
this.srcX = 0;
this.srcY = 60;
this.width = 20;
this.height = 20;
}
Bullet.prototype.draw = function() {
this.drawX += this.speed;
ctxShip.drawImage(imgSprite,this.srcX,this.srcY,this.width,this.height,this.drawX,this.drawY,this.width,this.height);
if (this.drawX > gameWidth) this.recycle();
};
Bullet.prototype.fire = function(X,Y) {
this.drawX = X;
this.drawY = Y;
};
Bullet.prototype.recycle = function() {
this.drawX = -100;
};
------------------------------------------------------------------------------------------------*/
// end of Bullet Functions
// Ship functions
function Ship(){
this.classOfShip = "One man pod.";
this.srcX = 0;
this.srcY = 0;
this.srcW = 60;
this.srcH = 60;
this.drawX = 0;
this.drawY = 0;
this.surfX = 210;
this.surfY = 0;
this.noseX = this.drawX;
this.noseY = this.drawY;
this.width = 35;
this.height = 35;
this.speed = MINspeed;
this.edgeY = Math.round(gameHeight - this.height - this.speed);
this.edgeX = Math.round(gameWidth - this.width - this.speed);
this.isUpKey = false;
this.isDownKey = false;
this.isLeftKey = false;
this.isRightKey = false;
this.isSpacebar = false;
this.isShooting = false;
this.isMoving = false;
this.isClicked = false;
this.onSurface = false;
/*------------------------------
this.bullets = [];
this.currentBullet = 0;
this.maxBullets = 25;
for (var i = 0; i < this.maxBullets; i++) this.bullets[this.bullets.length] = new Bullet(this);
----------------------------------*/
}
Ship.prototype.draw = function() {
this.updateCoords();
this.checkPos();
this.updateHUD();
ifClicked(this);
if(this.isClicked) this.openWindow();
if(inSpace) ctxShip.drawImage(imgSprite,this.srcX,this.srcY,this.srcW,this.srcH,this.drawX,this.drawY,this.height,this.width);
if(onSurface) ctxShip.drawImage(imgSprite,this.srcX,this.srcY,this.srcW,this.srcH,this.surfX,this.surfY,this.height,this.width);
//this.checkShooting();
//this.drawAllBullets();
};
Ship.prototype.updateHUD = function(){
if(inSpace){
ctxHUD.fillStyle = "#fff";
// ctxHUD.fillText("mouseX: " + mouseX + " mouseY: " + mouseY,490,30);
ctxHUD.fillText("Speed: " + Math.round(this.speed), 60,30);
}
if(onSurface){
ctxHUD.fillStyle = "#000";
ctxHUD.fillText("SurfaceX: " + SurfaceX, 20,60);
ctxHUD.fillText("Speed: " + Math.round(this.speed), 20,30);
// ctxHUD.fillText("mouseX: " + mouseX + " mouseY: " + mouseY,300,30);
}
};
Ship.prototype.checkPos = function (){
var flybuffer = 0;
var max_X = 0;
var max_Y = 0;
var speed = Math.round(this.speed);
if(onSurface){
max_X = 2000000;
max_Y = gameHeight;
flybuffer = 220;
speed = 10;
if(!mouseIsDown){
if (this.isUpKey) {
if(this.surfY > 0) this.surfY -= speed;
}
if (this.isRightKey && SurfaceMap < max_X) {
SurfaceMap -= speed;
SurfaceMap2 -= speed;
SurfaceX += speed;
if(this.surfX < this.edgeX - 200) this.surfX += speed;
}
if (this.isDownKey) {
if(this.surfY <= gameHeight - flybuffer) this.surfY += speed;
}
if (this.isLeftKey) {
SurfaceMap += speed;
SurfaceMap2 += speed;
SurfaceX -= speed;
if(this.surfX > 200) this.surfX -= speed;
}
}
DrawSurfaceImg();
}
if(inSpace ){
max_X = 2180; // No Higher! Map bugs out, this is the threshold.
max_Y = 2490; // No Higher! Map bugs out, this is the threshold.
flybuffer = 90;
if(!mouseIsDown){
if (this.isUpKey && SpaceMapY > 0) {
if(this.drawY > flybuffer) this.drawY -= speed;
if(SpaceMapY < flybuffer) this.drawY -= speed;
SpaceMapY -= speed;
}
if (this.isRightKey && SpaceMapX < max_X) {
if(this.drawX < this.edgeX - flybuffer) this.drawX += speed;
if(SpaceMapX > max_X - flybuffer) this.drawX += speed;
SpaceMapX += speed;
}
if (this.isDownKey && SpaceMapY < max_Y) {
if(this.drawY < this.edgeY - flybuffer) this.drawY += speed;
if(SpaceMapY > max_Y - flybuffer) this.drawY += speed;
SpaceMapY += speed;
}
if (this.isLeftKey && SpaceMapX > 0) {
if(this.drawX > flybuffer) this.drawX -= speed;
if(SpaceMapX < flybuffer) this.drawX -= speed;
SpaceMapX -= speed;
}
}
ctxBg.drawImage(imgMap,SpaceMapX,SpaceMapY,gameWidth,gameHeight,0,0,gameWidth,gameHeight);
}
};
Ship.prototype.updateCoords = function(){
if(this.isUpKey) this.srcX = 360;
if(this.isDownKey) this.srcX = 120;
if(this.isLeftKey) this.srcX = 240;
if(this.isRightKey) this.srcX = 0;
if(this.isUpKey && this.isLeftKey) this.srcX = 300;
if(this.isUpKey && this.isRightKey) this.srcX = 420;
if(this.isDownKey && this.isLeftKey) this.srcX = 180;
if(this.isDownKey && this.isRightKey) this.srcX = 60;
this.noseX = (this.drawX + this.width) - this.speed;
this.noseY = (this.drawY + this.height) - this.speed;
this.leftX = this.drawX;
this.rightX = this.drawX + this.width;
this.topY = this.drawY;
this.bottomY = this.drawY + this.height;
};
Ship.prototype.openWindow = function(){
ctxWindow.fillStyle = "#fff";
ctxWindow.font = "bold 15px Helvica";
ctxWindow.drawImage(imgBlueWindow,0,0,gameWidth,gameHeight,0,0,gameWidth,gameHeight);
ctxWindow.fillText("Class: " + this.classOfShip, 220,210);
ctxWindow.fillText("Speed: " + this.speed, 220,225);
windowIsOpen = true;
if(onSurface){
ctxWindow.fillText("Resources Found at " + Resource_0001.coordX + " and " + Resource_0002.coordX, 220,240);
}
CloseBtn.draw();
stopLoop();
};
/*----------------------------------------------------------------------------------------
Ship.prototype.checkShooting = function() {
if (this.isSpacebar && !this.isShooting) {
this.isShooting = true;
this.bullets[this.currentBullet].fire(this.noseX, this.noseY);
this.currentBullet++;
if (this.currentBullet >= this.bullets.length) this.currentBullet = 0;
} else if (!this.isSpacebar) {
this.isShooting = false;
}
};
Ship.prototype.drawAllBullets = function() {
for (var i = 0; i < this.bullets.length; i++) {
if (this.bullets[i].drawX >= 0) this.bullets[i].draw();
}
};
-----------------------------------------------------------------------------------------*/
function clearCtx() {
ctxShip.clearRect(0,0,gameWidth,gameHeight);
ctxBg.clearRect(0,0,gameWidth,gameHeight);
ctxHUD.clearRect(0,0,gameWidth,gameHeight);
ctxPlanets.clearRect(0,0,gameWidth,gameHeight);
ctxWindow.clearRect(0,0,gameWidth,gameHeight);
ctxButtons.clearRect(0,0,gameWidth,gameHeight);
}
// end of Ship function
//----------------------------------------------------END OF OBJECTS
// Event Functions
function clearMouse(){
if(inSpace){
mouseX = 10000;
mouseY = 10000;
}
if(onSurface){
var tempX = Math.abs(SurfaceX);
mouseY = gameHeight + 100;
}
}
function checkMouseDown(e) {
var mX = (e.clientX - (canvasBg.offsetLeft - canvasBg.scrollLeft));
var mY = (e.clientY - (canvasBg.offsetTop - canvasBg.scrollTop));
if(mX <= gameWidth && mX >= 0) mouseX = mX;
if(mY <= gameHeight && mY >= 0) mouseY = mY;
mouseIsDown = true;
LandBtn.wasClicked();
SpaceBtn.wasClicked();
CloseBtn.wasClicked();
}
function checkMouseUp(e){
mouseIsDown = false;
clearMouse();
}
function checkKeyDown(e){
var keyID = e.keyCode || e.which;
if(keyID === 38 || keyID === 87){ // up arrow or W key
Player1.isUpKey = true;
Player1.isMoving = true;
e.preventDefault();
}
if(keyID === 39|| keyID === 68){ // right arrow or D key
Player1.isRightKey = true;
Player1.isMoving = true;
e.preventDefault();
}
if(keyID === 40 || keyID === 83){ // down arrow or S key
Player1.isDownKey = true;
Player1.isMoving = true;
e.preventDefault();
}
if(keyID === 37 || keyID === 65){ // left arrow or A key
Player1.isLeftKey = true;
Player1.isMoving = true;
e.preventDefault();
}
/*
if (keyID === 32) { //spacebar
Player1.isSpacebar = true;
e.preventDefault();
}
*/
}
function checkKeyUp(e){
var keyID = e.keyCode || e.which;
if(keyID === 38 || keyID === 87){ // up arrow or W key
Player1.isUpKey = false;
Player1.isMoving = false;
e.preventDefault();
}
if(keyID === 39|| keyID === 68){ // right arrow or D key
Player1.isRightKey = false;
Player1.isMoving = false;
e.preventDefault();
}
if(keyID === 40 || keyID === 83){ // down arrow or S key
Player1.isDownKey = false;
Player1.isMoving = false;
e.preventDefault();
}
if(keyID === 37 || keyID === 65){ // left arrow or A key
Player1.isLeftKey = false;
Player1.isMoving = false;
e.preventDefault();
}
/*
if (keyID === 32) { //spacebar
Player1.isSpacebar = false;
e.preventDefault();
}
*/
}
// end of Event Functions
答案 0 :(得分:0)
我找到了我的错误。我想如果有人遇到类似的问题我会回答。
我的错误与我的按钮对象有关。在每次单击时,我的checkMouseDown函数调用wasClicked函数来检查是否已单击按钮对象。我的按钮对象在循环开始之前创建,我的wasClicked函数没有任何逻辑来检测按钮是否已被绘制。所以我在按钮对象this.isDrawn中添加了另一个变量;然后我添加了this.isDrawn = true;如果在绘制后点击了对象,则将draw()函数和if(this.isDrawn)语句写入wasClicked函数,并将this.isDrawn = false写入逻辑。
感谢Ken指导我远离我的船舶绘图功能=)