I have a canvas for the game world and a canvas for the display screen. I also have a polygon with nodes V(x,y) to serve as a viewport that follows the player and his rotation. I would like to know how to clip from the game world along the polygon, rotate and draw to the smaller canvas.`
//main looping function
var requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
};
})();
//joystick setup
var leftManager = null;
var rightManager = null;
//precalculated math
var twoPi = Math.PI*2;
var halfPi = Math.PI/2;
var thirdOfCircleInRadians = twoPi/3;
//game canvas setup
var gameCvs = document.getElementById('gameCanvas');
gameCvs.width = 480;
gameCvs.height = 320;
//gameCvs.width - 960;
//gameCvs.height = 640;
var gameCtx = gameCvs.getContext("2d");
//game loop
var lastTime = 0;
function main() {
var now = Date.now();
var dt = lastTime==0? 0.016 : (now - lastTime) / 1000.0;
update(dt);
render(dt);
lastTime = now;
requestAnimFrame(main);
}
//collision class shorthand
var V = SAT.Vector;
var C = SAT.Circle;
var P = SAT.Polygon;
var R = new SAT.Response();
P.prototype.draw = function (ctx,type) {
ctx.save();
switch(type){
case 'van': ctx.fillStyle = "rgba(66, 66, 66, 0.5)"; break;
case 'col': ctx.fillStyle = "rgba(0, 0, 0, 1.0)"; break;
default: ctx.fillStyle = "rgba(0, 0, 0, 1.0)"; break;
}
ctx.translate(this.pos.x, this.pos.y);
ctx.beginPath();
var points = this.calcPoints;
ctx.moveTo(points[0].x, points[0].y);
var i = points.length;
while (i--) ctx.lineTo(points[i].x, points[i].y);
ctx.closePath();
//stroke to see through camera, when camera is not drawn use fill
ctx.stroke();
//ctx.fill();
ctx.restore();
};
//first for collisions, second for vanity. first is black, second is grey
var O = function(colPolygon,vanPolygon){
this.colPolygon = colPolygon;
this.vanPolygon = vanPolygon;
this.visible = false;
};
var objectVendor = function(type,position){
switch(type){
case 'tree':
return new O(new P(position,[
new V(10.5,19.5),
new V(20.5,9.5),
new V(23,-4),
new V(15,-16.5),
new V(-4,-19.5),
new V(-18,-14.5),
new V(-23,-0.5),
new V(-18.5,14.5),
new V(-8,20)
]),new P(position,[
new V(21,39),
new V(41,19),
new V(46,-8),
new V(30,-33),
new V(-8,-39),
new V(-36,-29),
new V(-46,-1),
new V(-37,29),
new V(-16,40)]));
break;
default: return false; break;
}
return false;
}
//Camera and Player Polygons
var cameraPoly = new P(new V(0,0),[
new V(-240,-160),
new V(240,-160),
new V(240,160),
new V(-240,160)
]);
var player = new P(new V(0,0),[
new V(5,2.5),
new V(7.5,2),
new V(7.5,-2),
new V(5,-2.5),
new V(-5,-2.5),
new V(-7.5,-2),
new V(-7.5,2),
new V(-5,2.5)
]);
//players start position on the screen, and starting angle, init velocity
player.pos = new V(240,160);
player.setAngle(1);
//players velocity for movement
player.vel = new V(0,0);
var world = {
objects: [],
visibleObjects: [],
worldCvs: null,
worldCtx: null,
init: function(){
//set up world canvas
this.worldCvs = document.createElement('canvas');
this.worldCvs.width = 480;
this.worldCvs.height = 480;
this.worldCtx = this.worldCvs.getContext("2d");
//populate world with stuff
this.objects.push(objectVendor('tree',new V(100,100)));
this.objects.push(objectVendor('tree',new V(150,200)));
this.objects.push(objectVendor('tree',new V(75,300)));
},
update: function(dt){
this.visibleObjects = [];
cameraPoly.setAngle(player.angle);
//cameraPoly.pos = player.pos;
cameraPoly.pos = new V(player.pos.x+(110*Math.cos(player.angle+halfPi)),player.pos.y+(110*Math.sin(player.angle+halfPi)));
//update objects to mark if they are in view
var i = this.objects.length;
while(i--){
if(SAT.testPolygonPolygon(this.objects[i].vanPolygon, cameraPoly, R)){
this.visibleObjects.push(this.objects[i]);
}
}
//}
},
draw: function(dt){
this.worldCtx.setTransform(1,0,0,1,0,0);
this.worldCtx.clearRect(0,0,this.worldCvs.width,this.worldCvs.height);
player.draw(this.worldCtx);
var i = this.visibleObjects.length;
while(i--){
this.visibleObjects[i].colPolygon.draw(this.worldCtx,'col');
this.visibleObjects[i].vanPolygon.draw(this.worldCtx,'van');
}
//for testing
cameraPoly.draw(this.worldCtx);
/*
this.worldCtx.save();
this.worldCtx.beginPath();
var i = cameraPoly.calcPoints.length;
this.worldCtx.moveTo(cameraPoly.calcPoints[0].x,cameraPoly.calcPoints[0].y);
while(i--){
this.worldCtx.lineTo(cameraPoly.calcPoints[i].x,cameraPoly.calcPoints[i].y);
}
this.worldCtx.clip();
this.worldCtx.restore();
*/
}
}
function render(dt){
gameCtx.setTransform(1,0,0,1,0,0);
gameCtx.clearRect(0,0,gameCvs.width,gameCvs.height);
world.draw();
//gameCtx.save();
//gameCtx.translate(cameraPoly.pos.x,cameraPoly.pos.y);
//gameCtx.translate(gameCtx.width/2,gameCtx.height/2);
//gameCtx.rotate(-player.angle+halfPi);
//gameCtx.translate(-world.worldCvs.width/2,-world.worldCvs.height/2);
gameCtx.drawImage(world.worldCvs,0,0);
//gameCtx.restore();
}
function update(dt){
world.update();
}
function init(){
//joystick setup
leftManager = nipplejs.create({
zone:document.getElementById("leftJoystick"),
color:"black",
size:75,
threshold:1.0,
position:{
top:"50%",
left:"50%"
},
mode:"static",
restOpacity:0.75,
});
rightManager = nipplejs.create({
zone:document.getElementById("rightJoystick"),
color:"black",
size:75,
threshold:1.0,
position:{
top:"50%",
right:"50%"
},
mode:"static",
restOpacity:0.75,
});
//joystick event setup
leftManager.get().on('move end', function(evt,data){
//console.log(evt);
//console.log(data);
});
rightManager.get().on('move end', function(evt,data){
//console.log(evt);
//console.log(data);
});
world.init();
main();
}
init();
` I'm using libraries SAT.js and nipplejs.js currently.
Changing the render function to the following will solve the problem, just rushing myself and didn't think things through very well. `
function render(dt){
gameCtx.setTransform(1,0,0,1,0,0);
gameCtx.clearRect(0,0,gameCvs.width,gameCvs.height);
world.draw();
gameCtx.translate(gameCvs.width/2,gameCvs.height/2);
gameCtx.rotate(-player.angle+Math.PI);
gameCtx.translate(-cameraPoly.pos.x,-cameraPoly.pos.y);
gameCtx.drawImage(world.worldCvs,0,0);
}`
What this is doing is resetting any transformations on the context, clearing it for a new redrawing, creating the world canvas, translating to display center, rotating by the proper amount for reference point, translating to reference center point on negative axis to move game canvas proper amount so that drawing at 0,0 is in the correct location. Thank you for the reference material!