1 decade ago by KirbySaysHi
I'm working on a demo that uses portals, which can be played in its current state here: impact-portals.
I want to be able to draw what one portal is "seeing" through the other portal, to give the illusion to the player that when you traverse the portal, you're not actually teleporting, but that the transition is just seamless.
An animation that shows what I'm trying to do: ig.module( 'game.portal-backgroundMap' ) .requires( 'impact.background-map' ) .defines(function(){ ig.VBuffer = ig.Class.extend({ canvas: null ,context: null ,rotation: 0 ,debugVBuffer: false ,init: function(){ this.canvas = ig.$new('canvas'); this.canvas.width = ig.system.realWidth; this.canvas.height = ig.system.realHeight; this.context = this.canvas.getContext('2d'); this.half = { x: this.canvas.width / 2, y: this.canvas.height / 2 } this.size = { x: this.canvas.width, y: this.canvas.height } if( this.debugVBuffer ){ this.canvas.style.position = 'relative'; this.canvas.style.zIndex = 9000; document.body.appendChild(this.canvas); } } ,clear: function( color ){ if( color ){ this.context.fillStyle = color; this.context.fillRect( 0, 0, ig.system.realWidth, ig.system.realHeight ); } else { this.context.clearRect( 0, 0, ig.system.realWidth, ig.system.realHeight ); } } }) ig.PortalBackgroundMap = ig.BackgroundMap.inject({ renderChunksToBuffer: function( vbuffer, centerX, centerY ){ // store original globals, to replace later var oldValues = { scroll: { x: this.scroll.x, y: this.scroll.y } ,system: { context: ig.system.context } ,game: { screen: { x: ig.game.screen.x ,y: ig.game.screen.y } } }; this.setScreenPos( centerX - (ig.system.width / 2), centerY - (ig.system.height / 2) ); ig.system.context = vbuffer.context; this.draw(); // and now undo the damage this.scroll.x = oldValues.scroll.x; this.scroll.y = oldValues.scroll.y; ig.system.context = oldValues.system.context; } }); });
There is a lot of room for optimization here, I know.
I create another canvas on load, called a vbuffer.
Then, each step, inject the vbuffer into ig.system.context, move the map to wherever I want to draw, call draw(), and then replace the vbuffer with the original system context. Then, I take the contents of that vbuffer, manually line everything up via rotate/translate (not shown here), and then ig.system.context.drawImage().
There are two next steps:
1) Allow the vbuffer to be a different size than the main system context, to allow for effects which might require more of the map to be rendered...
2) Someone create an effect that shows the current map and entities rotating around the player (which will not rotate).
So my question then, is:
Is there a better way to provide the effect (rotate the background map) as shown in my animated gif above?
At this point, I'm effectively drawing the background maps twice, because I want to be able to use the tile/chunk logic. So if there were a way to inject double buffering into a more core part of the Impact, that might help with effects. I could see this eventually enable Mode7-like effects...
Any ideas? Please let me know if something doesn't make sense.
I want to be able to draw what one portal is "seeing" through the other portal, to give the illusion to the player that when you traverse the portal, you're not actually teleporting, but that the transition is just seamless.
An animation that shows what I'm trying to do: ig.module( 'game.portal-backgroundMap' ) .requires( 'impact.background-map' ) .defines(function(){ ig.VBuffer = ig.Class.extend({ canvas: null ,context: null ,rotation: 0 ,debugVBuffer: false ,init: function(){ this.canvas = ig.$new('canvas'); this.canvas.width = ig.system.realWidth; this.canvas.height = ig.system.realHeight; this.context = this.canvas.getContext('2d'); this.half = { x: this.canvas.width / 2, y: this.canvas.height / 2 } this.size = { x: this.canvas.width, y: this.canvas.height } if( this.debugVBuffer ){ this.canvas.style.position = 'relative'; this.canvas.style.zIndex = 9000; document.body.appendChild(this.canvas); } } ,clear: function( color ){ if( color ){ this.context.fillStyle = color; this.context.fillRect( 0, 0, ig.system.realWidth, ig.system.realHeight ); } else { this.context.clearRect( 0, 0, ig.system.realWidth, ig.system.realHeight ); } } }) ig.PortalBackgroundMap = ig.BackgroundMap.inject({ renderChunksToBuffer: function( vbuffer, centerX, centerY ){ // store original globals, to replace later var oldValues = { scroll: { x: this.scroll.x, y: this.scroll.y } ,system: { context: ig.system.context } ,game: { screen: { x: ig.game.screen.x ,y: ig.game.screen.y } } }; this.setScreenPos( centerX - (ig.system.width / 2), centerY - (ig.system.height / 2) ); ig.system.context = vbuffer.context; this.draw(); // and now undo the damage this.scroll.x = oldValues.scroll.x; this.scroll.y = oldValues.scroll.y; ig.system.context = oldValues.system.context; } }); });
There is a lot of room for optimization here, I know.
I create another canvas on load, called a vbuffer.
Then, each step, inject the vbuffer into ig.system.context, move the map to wherever I want to draw, call draw(), and then replace the vbuffer with the original system context. Then, I take the contents of that vbuffer, manually line everything up via rotate/translate (not shown here), and then ig.system.context.drawImage().
There are two next steps:
1) Allow the vbuffer to be a different size than the main system context, to allow for effects which might require more of the map to be rendered...
2) Someone create an effect that shows the current map and entities rotating around the player (which will not rotate).
So my question then, is:
Is there a better way to provide the effect (rotate the background map) as shown in my animated gif above?
At this point, I'm effectively drawing the background maps twice, because I want to be able to use the tile/chunk logic. So if there were a way to inject double buffering into a more core part of the Impact, that might help with effects. I could see this eventually enable Mode7-like effects...
Any ideas? Please let me know if something doesn't make sense.