修复画布速度错误

时间:2014-01-12 16:59:19

标签: javascript canvas

我是使用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

1 个答案:

答案 0 :(得分:0)

我找到了我的错误。我想如果有人遇到类似的问题我会回答。

我的错误与我的按钮对象有关。在每次单击时,我的checkMouseDown函数调用wasClicked函数来检查是否已单击按钮对象。我的按钮对象在循环开始之前创建,我的wasClicked函数没有任何逻辑来检测按钮是否已被绘制。所以我在按钮对象this.isDrawn中添加了另一个变量;然后我添加了this.isDrawn = true;如果在绘制后点击了对象,则将draw()函数和if(this.isDrawn)语句写入wasClicked函数,并将this.isDrawn = false写入逻辑。

感谢Ken指导我远离我的船舶绘图功能=)