0

让我试着解释一下我现在拥有的东西,以及我想要添加的东西。现在我有一个 500x899 的画布,跟随一个精灵(播放器)到一个 5000x3750 的背景图像(地图)上。两者都在同一个精灵表上。现在,如果按下箭头键,玩家精灵会沿着地图向那个方向移动,而画布会跟随玩家。- 但我想要的是让左/右箭头键旋转玩家,向上键让玩家朝那个方向移动。这是我的代码,它很多,但它有条理:

// wrapper for "class" Rectangle
    (function(){
        function Rectangle(left, top, width, height){
            this.left = left || 0;
            this.top = top || 0;
            this.right = (left + width) || 0;
            this.bottom = (top + height) || 0;
        }

        Rectangle.prototype.set = function(left, top, width, height){
            this.left = left;
            this.top = top;
            this.width = width || this.width;
            this.height = height || this.height;
            this.right = (this.left + this.width);
            this.bottom = (this.top + this.height);
        }

        Rectangle.prototype.within = function(r) {
            return (r.left <= this.left && 
                    r.right >= this.right &&
                    r.top <= this.top && 
                    r.bottom >= this.bottom);
        }       

        Rectangle.prototype.overlaps = function(r) {
            return (this.left < r.right && 
                    r.left < this.right && 
                    this.top < r.bottom &&
                    r.top < this.bottom);
        }

        // add "class" Rectangle to our Game object
        Game.Rectangle = Rectangle;
    })();   

    // wrapper for "class" Camera (avoid global objects)
    (function(){

        // possibles axis to move the camera
        var AXIS = {
            NONE: "none", 
            HORIZONTAL: "horizontal", 
            VERTICAL: "vertical", 
            BOTH: "both"
        };

        // Camera constructor
        function Camera(xView, yView, canvasWidth, canvasHeight, worldWidth, worldHeight)
        {
            // position of camera (left-top coordinate)
            this.xView = xView || 0;
            this.yView = yView || 0;

            // distance from followed object to border before camera starts move
            this.xDeadZone = 0; // min distance to horizontal borders
            this.yDeadZone = 0; // min distance to vertical borders

            // viewport dimensions
            this.wView = 800;
            this.hView = 599;           

            // allow camera to move in vertical and horizontal axis
            this.axis = AXIS.BOTH;  

            // object that should be followed
            this.followed = null;

            // rectangle that represents the viewport
            this.viewportRect = new Game.Rectangle(this.xView, this.yView, this.wView, this.hView);             

            // rectangle that represents the world's boundary (room's boundary)
            this.worldRect = new Game.Rectangle(this.xView, this.yView, this.wView, this.hView);

        }

        // gameObject needs to have "x" and "y" properties (as world(or room) position)
        Camera.prototype.follow = function(gameObject, xDeadZone, yDeadZone)
        {       
            this.followed = gameObject; 
            this.xDeadZone = xDeadZone;
            this.yDeadZone = yDeadZone;
        }                   

        Camera.prototype.update = function()
        {
            // keep following the player (or other desired object)
            if(this.followed != null)
            {       
                if(this.axis == AXIS.HORIZONTAL || this.axis == AXIS.BOTH)
                {       
                    // moves camera on horizontal axis based on followed object position
                    if(this.followed.x - this.xView  + this.xDeadZone > this.wView)
                        this.xView = this.followed.x - (this.wView - this.xDeadZone);
                    else if(this.followed.x  - this.xDeadZone < this.xView)
                        this.xView = this.followed.x  - this.xDeadZone;

                }
                if(this.axis == AXIS.VERTICAL || this.axis == AXIS.BOTH)
                {
                    // moves camera on vertical axis based on followed object position
                    if(this.followed.y - this.yView + this.yDeadZone > this.hView)
                        this.yView = this.followed.y - (this.hView - this.yDeadZone);
                    else if(this.followed.y - this.yDeadZone < this.yView)
                        this.yView = this.followed.y - this.yDeadZone;
                }                       

            }       

            // update viewportRect
            this.viewportRect.set(this.xView, this.yView);

            // don't let camera leaves the world's boundary
            if(!this.viewportRect.within(this.worldRect))
            {
                if(this.viewportRect.left < this.worldRect.left)
                    this.xView = this.worldRect.left;
                if(this.viewportRect.top < this.worldRect.top)                  
                    this.yView = this.worldRect.top;
                if(this.viewportRect.right > this.worldRect.right)
                    this.xView = this.worldRect.right - this.wView;
                if(this.viewportRect.bottom > this.worldRect.bottom)                    
                    this.yView = this.worldRect.bottom - this.hView;
            }

        }   

        // add "class" Camera to our Game object
        Game.Camera = Camera;

    })();

    // wrapper for "class" Player
    (function(){
        function Player(x, y){
            // (x, y) = center of object
            // ATTENTION:
            // it represents the player position on the world(room), not the canvas position
            this.x = x;
            this.y = y; 
            // move speed in pixels per second
            this.speed = 200;       

            // render properties
            this.width = 85;
            this.height = 80;
        }

        Player.prototype.update = function(step, worldWidth, worldHeight){
            // parameter step is the time between frames ( in seconds )

            // check controls and move the player accordingly
            if(Game.controls.left)
                this.x -= this.speed * step;
            if(Game.controls.up)
                this.y -= this.speed * step;
            if(Game.controls.right)
                this.x += this.speed * step;
            if(Game.controls.down)
                this.y += this.speed * step;        

            // don't let player leaves the world's boundary
            if(this.x - this.width/2 < 0){
                this.x = this.width/2;
            }
            if(this.y - this.height/2 < 0){
                this.y = this.height/2;
            }
            if(this.x + this.width/2 > worldWidth){
                this.x = worldWidth - this.width/2;
            }
            if(this.y + this.height/2 > worldHeight){
                this.y = worldHeight - this.height/2;
            }
        }

        Player.prototype.draw = function(context, xView, yView){
            context.save();
            // before draw we need to convert player world's position to canvas position
            context.drawImage(imgSprite,1700,599, this.width, this.height,(this.x-this.width/2) - xView, (this.y-this.height/2) - yView, this.width, this.height);
            context.restore();
            }   
        // add "class" Player to our Game object
        Game.Player = Player;
    })();


    // wrapper for "class" Map
    (function(){
        function Map(width, height){
            // map dimensions
            this.width = width;
            this.height = height;

            // map texture
            this.image = null;
        }

        // generate an example of a large map
        Map.prototype.generate = function(){
            this.x = 0;
            this.y = 0; 
            var ctx = document.createElement("canvas").getContext("2d");        
            ctx.canvas.width = this.width;
            ctx.canvas.height = this.height;    
            ctx.drawImage(imgSprite,0,2250,this.width,this.height,this.x,this.y,this.width,this.height);    


            ctx.restore();  

            // store the generate map as this image texture
            this.image = new Image();
            this.image.src = ctx.canvas.toDataURL("image/png");                 

            // clear context
            ctx = null;
        }

        // draw the map adjusted to camera
        Map.prototype.draw = function(context, xView, yView){                   
            var sx, sy, dx, dy;
            var sWidth, sHeight, dWidth, dHeight;

            // offset point to crop the image
            sx = xView;
            sy = yView;

            // dimensions of cropped image          
            sWidth =  context.canvas.width;
            sHeight = context.canvas.height;

            // if cropped image is smaller than canvas we need to change the source dimensions
            if(this.image.width - sx < sWidth){
                sWidth = this.image.width - sx;
            }
            if(this.image.height - sy < sHeight){
                sHeight = this.image.height - sy; 
            }

            // location on canvas to draw the croped image
            dx = 0;
            dy = 0;
            // match destination with source to not scale the image
            dWidth = sWidth;
            dHeight = sHeight;                                  

            context.drawImage(this.image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);            
        }

        // add "class" Map to our Game object
        Game.Map = Map;

    })();


    // Game Script
    (function(){
        // prepaire our game canvas
        var canvas = document.getElementById("gameCanvas");
        var context = canvas.getContext("2d");

        // game settings:   
        var FPS = 30;
        var INTERVAL = 1000/FPS; // milliseconds
        var STEP = INTERVAL/1000 // seconds

        // setup an object that represents the room
        var room = {
            width: 5000,
            height: 3750,
            map: new Game.Map(5000, 3750)
        };

        // generate a large image texture for the room
        room.map.generate();

        // setup player
        var player = new Game.Player(85, 80);

        // setup the magic camera !!!
        var camera = new Game.Camera(0, 0, 800, 599, room.width, room.height);      
        camera.follow(player, 800/2, 599/2);

        // Game update function
        var update = function(){            
            player.update(STEP, room.width, room.height);
            camera.update();
        }

        // Game draw function
        var draw = function(){
            // clear the entire canvas
            context.clearRect(0, 0, 800, 599);

            // redraw all objects
            room.map.draw(context, camera.xView, camera.yView);     
            player.draw(context, camera.xView, camera.yView);       
        }

        // Game Loop
        var gameLoop = function(){                      
            update();
            draw();
        }   

        // <-- configure play/pause capabilities:

        // I'll use setInterval instead of requestAnimationFrame for compatibility reason,
        // but it's easy to change that.

        var runningId = -1;

    Game.play = function(){ 
        if(runningId == -1){
            runningId = setInterval(function(){
                gameLoop();
            }, INTERVAL);
            console.log("play");
        }
    }

    Game.togglePause = function(){      
        if(runningId == -1){
            Game.play();
        }
        else
        {
            clearInterval(runningId);
            runningId = -1;
            console.log("paused");
        }
    }   
})();
// <-- configure Game controls:
Game.controls = {
    left: false,
    up: false,
    right: false,
    down: false,
};
window.addEventListener("keydown", function(e){
    switch(e.keyCode)
    {
        case 37: // left arrow
            Game.controls.left = true;
            break;
        case 38: // up arrow
            Game.controls.up = true;
            break;
        case 39: // right arrow
            Game.controls.right = true;
            break;
        case 40: // down arrow
            Game.controls.down = true;
            break;
    }
}, false);
window.addEventListener("keyup", function(e){
    switch(e.keyCode)
    {
        case 37: // left arrow
            Game.controls.left = false;
            break;
        case 38: // up arrow
            Game.controls.up = false;
            break;
        case 39: // right arrow
            Game.controls.right = false;
            break;
        case 40: // down arrow
                Game.controls.down = false;
            break;
        case 80: // key P pauses the game
            Game.togglePause();
            break;      
        }
    }, false);
    // start the game when page is loaded
    window.onload = function(){ 
        Game.play();
    }

这同样适用于画布跟随玩家和所有人,但现在我正在尝试使用箭头键旋转玩家精灵。我使用谷歌并尝试了一些类似的代码:

var thrust = 0;
var rotation = 0;
ctxPlayer.translate(this.width/2, this.height/2);
ctxPlayer.rotate(this.angle);
ctxPlayer.translate(this.x,this.y);
if(Game.controls.left)
this.angle =-3

(对不起,我没有关于轮换的确切尝试,因为每次它不起作用时我都删除了它们)。使用与此类似的代码,我得到的唯一旋转是玩家围绕坐标在一个巨大的圆圈中旋转。(实际上不是在一个位置旋转,也不是按键)

非常感谢任何帮助或建议。

4

1 回答 1

2

更改操作顺序。首先旋转精灵,然后移动它。您将希望精灵的中心位于 0,0(左上角)以获得您想要的效果。以下代码假设您已经从 0,0 开始:

ctxPlayer.save();
ctxPlayer.translate(this.x,this.y);
ctxPlayer.rotate(this.angle);
ctxPlayer.translate(-this.width/2,-this.height/2); // before we draw the sprite lets set the anchor point to its center.
ctxPlater.restore();

http://jsfiddle.net/LRpBM/

于 2013-07-29T03:14:39.727 回答