Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

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: /><br />
<br />
So far I have the display of what's on the other side of the portal working, but I had to do it using a bit of a hack:<br />
<br />
<pre class= 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.

1 decade ago by Graphikos

The issue you have is the portal could be outside the view of the current game screen so I think you are more or less on the right track with the drawing to a canvas for an alternate location.

If impact was less efficient and drew the entire level all at once then you could potentially cache that each frame and then draw out any section of it. Then you are rendering once and able to draw as many different views as you want from where-ever you want. This would also be perfect for games that require multiple view points (thinking like a two player racing game or something).

I suppose, in theory, you could inject to suppress the checks to see if objects are off-screen and therefore don't draw as well as change what canvas it is drawing to. I would think just subbing in your own canvas context for ig.system.context during the draw would work for that.

If you could achieve that then drawing different views and rotating them and whatnot should be pretty simple. You can also get the irregular shape with canvas clip() method. Sounds like you more or less have that part figured out.

I'm sure I'm missing something crucial in my thinking and there is the also issue of performance to consider. It might be a very uphill battle doing what you are trying to do.

1 decade ago by KirbySaysHi

Quote from Graphikos
I suppose, in theory, you could inject to suppress the checks to see if objects are off-screen and therefore don't draw as well as change what canvas it is drawing to. I would think just subbing in your own canvas context for ig.system.context during the draw would work for that.


That's a good point, I hadn't thought about the auto culling that's going on. But I think if I adjust ig.game.screen && ig.game._rscreen before my draw() (I will have to look into _rscreen, but I am currently adjusting screen), I can overcome that.

Quote from Graphikos
I'm sure I'm missing something crucial in my thinking and there is the also issue of performance to consider. It might be a very uphill battle doing what you are trying to do.


Performance is another concern, but I think if I'm able to draw once to a buffer, and then just manipulate that (instead of once to the buffer and once to the main screen, like now), it might be alright..

Maybe what I'll do is create methods in my subclass of ig.game that can handle moving the screen using a stack, similar to how canvas' context works: if you move the screen, you can pop() the last state off to return it to its previous state (position, scale, etc). Then provide methods for creating a buffer of arbitrary size, and "properly" injecting it into ig.system.context, accounting for buffer size vs actual system screen size and such. And then finally, methods that let you draw either the maps + entities, just maps, just entities, or some other combination to an arbitrary buffer.

For this particular usage, I think the following process would work:

during portal traversal
  do not draw as usual
  draw 
    backgrounds, entities except player (including portal effects!?), to a*sqrt(2) width and height buffer
  rotate system screen accordingly
  draw buffer to system screen
  unrotate system screen
  draw player as usual

But that process implies being able to:

Draw arbitrary parts of the level+entities onto another arbitrarily-sized buffer
Draw effects (the portal cones/views) onto an arbitrary buffer

I'm not sure how, but this feels like something that could benefit Impact as well... just not sure where to hook it.
Page 1 of 1
« first « previous next › last »