javascript - Html5 canvas game, creating a map much bigger than viewing canvas -
so let me start off saying trying create large image or room, 5000 3750, , have canvas or viewing area 800 599, following player piece. did find guide on how this, using background , player drawn in java script (not taken sprite sheet). have sprite sheet background, , player, have gotten player work on background drawn javascript, not taken sprite sheet want do. here of code:
// wrapper "class" map (function(){ function map(width, height){ // map dimensions this.width = width; this.height = height; // map texture this.image = null; } // generate example of large map map.prototype.generate = function(){ ctxbg.drawimage(imgsprite,0,2250,5000,3750,0,0,5000,3750); } // draw map adjusted camera map.prototype.draw = function(context, xview, yview){ var sx, sy, dx, dy; var swidth, sheight, dwidth, dheight; // offset point crop image sx = xview; sy = yview; // dimensions of cropped image swidth = 800; sheight = 599; // if cropped image smaller canvas need change source dimensions if(800 - sx < swidth){ swidth = 800 - sx; } if(599 - sy < sheight){ sheight = 599 - sy; } // location on canvas draw croped image dx = 0; dy = 0; // match destination source not scale image dwidth = swidth; dheight = sheight; context.drawimage(imgsprite, sx, sy, swidth, sheight, dx, dy, dwidth, dheight); } // add "class" map 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 object represents room var room = { width: 5000, height: 3750, map: new game.map(5000, 3750) }; room.map.generate();
heres camra/player codes:
(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 our game object game.rectangle = rectangle; })(); // wrapper "class" camera (avoid global objects) (function(){ // possibles axis move 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 followed object border before camera starts move this.xdeadzone = 0; // min distance horizontal borders this.ydeadzone = 0; // min distance vertical borders // viewport dimensions this.wview = 800; this.hview = 599; // allow camera move in vertical , horizontal axis this.axis = axis.both; // object should followed this.followed = null; // rectangle represents viewport this.viewportrect = new game.rectangle(this.xview, this.yview, this.wview, this.hview); // rectangle represents world's boundary (room's boundary) this.worldrect = new game.rectangle(this.xview, this.yview, this.wview, this.hview); } // gameobject needs have "x" , "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 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 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 our game object game.camera = camera; })(); // wrapper "class" player (function(){ function player(x, y){ // (x, y) = center of object // attention: // represents player position on world(room), not 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 time between frames ( in seconds ) // check controls , move 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 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 our game object game.player = player; })();
it shows image , player, canvas doesn't follow player object, if use background this, though:
(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"; (var x = 0, = 0; < rows; x+=44, i++) { ctx.beginpath(); (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 map adjusted camera map.prototype.draw = function(context, xview, yview){ var sx, sy, dx, dy; var swidth, sheight, dwidth, dheight; // offset point crop image sx = xview; sy = yview; // dimensions of cropped image swidth = context.canvas.width; sheight = context.canvas.height; // if cropped image smaller canvas need change 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; })();
i looked around, did google searches , used javascript checker, no luck. suggestions/advice appreciated.
i'll give shot anyways. so, theoretical part:
what trying achieve simple scene management. scene needs camera, object stores x , y offset , width , height going display (the width , height known projection plane in 3d graphics). in every frame draw scene (or world) offset of camera.
to implementation:
to draw large image onto small canvas, use drawimage() function 9 parameters allready do.
to draw many small images tiles, recommend taking @ scene graphs, wrote more in-depth answer time ago @ collision detection in html5 canvas. optimization too
if draw many objects per frame, note can create canvas objects not in html dom cache draw results, necessary performance. draw call expensive because of render state changes , streaming costs, not because of pixels itself.
finally, draw character on top, need sort of z index, draw loop knows player on top of ground, can via layers or storing z index game objects.
so far, you're on right track!
Comments
Post a Comment