2013-07-22 41 views
1

因此,让我开始说我想创建一个大的图像或房间,比如5000乘3750,并且画布或查看区域只有800乘599,总是跟随玩家片断。我确实找到了一个关于如何做到这一点的良好指南,使用在java脚本中绘制的背景和播放器(不是从精灵表中获取)。但是我拥有的是一张带背景的精灵画面,玩家,我已经让玩家使用JavaScript绘制的背景进行工作,但不会像我想要的那样从精灵表中获取。 下面是一些代码:Html5帆布游戏,创建比观看帆布大得多的地图

// 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(){ 
    ctxBg.drawImage(imgSprite,0,2250,5000,3750,0,0,5000,3750); 
    }  
// 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 = 800; 
    sHeight = 599; 
// if cropped image is smaller than canvas we need to change the source dimensions 
    if(800 - sx < sWidth){ 
     sWidth = 800 - sx; 
    } 
    if(599 - sy < sHeight){ 
     sHeight = 599 - 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(imgSprite, 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) 
}; 
room.map.generate(); 

继承人的CAMRA /播放器代码:

(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, /*optional*/width, /*optional*/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; 
    this.srcX = 1700; 
    this.srcY = 599; 
    this.drawX = 350; 
    this.drawY = 400; 
    xView = this.x-this.width/2; 
    yView = this.y-this.height/2;   
// move speed in pixels per second 
    this.speed = 100;   
// 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){ 
    ctxPlayer.clearRect(0,0,800,599); 
    context.save(); 
    ctxPlayer.drawImage(imgSprite,this.srcX,this.srcY,this.width,this.height,(this.x-this.width/2),(this.y-this.height/2),this.width,this.height); 
    context.restore();   
    } 
// add "class" Player to our Game object 
    Game.Player = Player; 
    })(); 

它显示的图像和球员,但在画布上不跟随玩家对象,它确实如果我用一个背景就是这样,虽然:

(function(){ 
function Map(width, height){ 
this.width = width; 
this.height = height; 
this.image = null; 
} 
Map.prototype.generate = function(){ 
var ctx = document.createElement("canvas").getContext("2d");   
ctx.canvas.width = this.width; 
ctx.canvas.height = this.height;   
var rows = ~~(this.width/44) + 1; 
var columns = ~~(this.height/44) + 1; 
var color = "red";    
ctx.save();   
ctx.fillStyle = "red";   
for (var x = 0, i = 0; i < rows; x+=44, i++) { 
ctx.beginPath();    
for (var y = 0, j=0; j < columns; y+=44, j++) {    
ctx.rect (x, y, 40, 40);     
} 
color = (color == "red" ? "blue" : "red"); 
ctx.fillStyle = color; 
ctx.fill(); 
ctx.closePath();    
}  
ctx.restore(); 
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; 
} 
dx = 0; 
dy = 0; 
dWidth = sWidth; 
dHeight = sHeight;         
context.drawImage(this.image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);    
} 
Game.Map = Map; 
})(); 

我看了看四周,做了一些谷歌搜索,并使用一个JavaScript检查,但没有运气。任何建议/建议非常感谢。

+0

要回答你的问题,我需要一些更多的信息。首先,如果你打算进行等距投影(这带有一些问题,但没有不能解决的问题)?其次,您是想从Tiles生成地图还是仅从1个图像生成地图? – Vengarioth

+0

为什么在移动角色时不要“移动”地图?你知道 - 当你处理角色并移动它时,改变“相机位置”。 –

回答

2

无论如何,我会给它一个镜头。因此,理论部分:

你试图实现的是简单的场景管理。场景需要一个Camera,一个存储X和Y偏移量以及要显示的宽度和高度的对象(宽度和高度也称为3D图形中的投影平面)。在每个框架中,您将通过相机的偏移量绘制场景(或世界)。

要实现:

要画一个大的图像在一个小画布,只是使用的drawImage()函数的所有9个参数为你做媒体链接。

要画很多小图像像瓷砖,我建议考虑看看场景图,我写了一个更深入的回答在Collision detection in HTML5 canvas. Optimization too

前段时间如果绘制每帧很多对象,注意,你可以总是创建不在html DOM中的画布对象以缓存绘制结果,这对于获得良好性能是必要的。绘制调用由于其渲染状态更改和流式传输成本而非常昂贵,而不是由于像素本身。

最后,为了在上面画出你的角色,你需要某种z索引,所以你的绘制循环知道玩家在地上,你可以通过图层或存储你的游戏对象的az索引来做到这一点。

到目前为止,您已经走上正轨!