简体   繁体   English

设置HTML Canvas 2D上下文的X和Y(屏幕抖动)

[英]Setting An X and Y of a HTML Canvas 2D Context (Screen Shake)

I'm trying to make a screen shake in a game every time you shoot. 每次拍摄时,我都试图在游戏中晃动屏幕。 I recall in Actionscript 3 you could set the x and y of your stage with the following: 我记得在Actionscript 3中,您可以使用以下命令设置舞台的x和y:

stage.x = stx

I was wondering if there is a way to do this with an HTML Canvas 2D Context. 我想知道是否有一种方法可以使用HTML Canvas 2D上下文。 I'm currently using the following: 我目前正在使用以下内容:

ctx.save();
ctx.translate(0, shakeAmt); 
ctx.restore();

(ctx is my HTML Canvas 2D Context) (ctx是我的HTML Canvas 2D上下文)

This method isn't working for me due to the fact that resetting the canvas every time isn't as smooth as I'd want it to be. 这种方法对我不起作用,原因是每次重置画布都不如我希望的那样平滑。 Along with this if a shake is called while another shake is running, the canvas will save and restore halfway through a shake. 与此同时,如果在进行另一次摇晃时调用了摇晃,则画布将在摇晃中途保存并恢复。

Is there a JavaScript alternative to stage.x? 是否有JavaScript替代stage.x? If not, how could I go about this? 如果没有,我该怎么办?

In this case I would recommend apply camera-shake (or machine gun shake perhaps?) to the element itself (which sort of represents the stage). 在这种情况下,我建议您将摄影机震动(也许是机枪震动?)应用于元素本身(哪种代表舞台)。 This is because any transform to canvas context does only affect future drawing which means you will have redraw each frame, do-able but require an extra full draw-op per frame while using DOM can update the "stage" in the same cycle. 这是因为对画布上下文的任何转换只会影响将来的绘制,这意味着您将重新绘制每帧,可以执行,但是每帧需要额外的完整绘制,而使用DOM可以在同一周期内更新“阶段”。

The problem with shaking the element on the other hand, is that it will move in the view-port, however, you can camouflage this by wrapping it in a div which has overflow set to hidden as well as applying a slight amount of scaling to the canvas element during the shake. 另一方面,摇动元素的问题在于它会在视口中移动,但是,您可以通过将其包装在div(已将其overflow设置为hidden中并对其进行少量缩放来伪装它摇动期间的canvas元素。 You can additionally incorporate an overlap by using a slightly bigger canvas that is offset inside the div. 您还可以通过使用稍稍大于div内部偏移的画布来合并重叠。

Conceptual Demo 概念演示

Click on the image to apply camera shake. 单击图像以应用相机震动。

 var style = img.style; // cache style object var amp = 7; // diameter of shake var t = 0; // current shake [0, 1] var step = 0.03; // progress step for each frame img.onclick = function() { if (t) t = 1; // continue loop, but reset else {t = 1; shake()} // start loop } function shake() { var a = (Math.random() * 2 - 1) * t; // random angle var x = (Math.random() * amp * 2 - amp) * t; // random position, bias on x var y = (Math.random() * amp - amp*0.5) * t; var s = Math.max(1, 1.05 * t); // scale to compens. for movement var b = 2 * t; // blur amount // build transform for element var tr = "rotate(" + a + "deg) translate(" + x + "px," + y + "px) scale(" + s + ")"; style.transform = style.webkitTransform = tr; style.filter = "blur(" + b + "px)"; t -= step; if (t > 0) requestAnimationFrame(shake); else { t = 0; style.transform = "matrix(1,0,0,1,0,0)"; // reset transforms style.filter = "blur(0)"; // remove blur } } 
 div { display:block; position:relative; overflow:hidden; width:600px; height:340px; background:rgba(121, 115, 117, 0.2); } #img { position:absolute; left:-5px; top:-5px; width:620px; height:auto; } 
 <div><img id=img src="//i.stack.imgur.com/XmnSd.jpg"></div> 

Using more than one canvas. 使用多个画布。

You can create a stage by rendering to an offscreen canvas. 您可以通过渲染到屏幕外的画布来创建舞台。 Though I am ignorant of Actionscripts stage abstraction, having presentation and render canvases separate is a common technique when you need full page post render effects (like shake). 尽管我对Actionscripts舞台抽象一无所知,但是当您需要整页的后期渲染效果(例如震动)时,将演示文稿和渲染画布分开是一种常见的技术。

To implement just create 2 canvases, one for the page (presentation canvas) and the offscreen render canvas. 要实现仅创建2个画布,一个用于页面(演示画布),另一个用于屏幕外渲染画布。

Render to the render canvas as normal, then at the end of frame draw the offscreen canvas onto the presentation canvas. 照常渲染到渲染画布,然后在帧结束时将屏幕外画布绘制到演示画布上。

var rCanvas = document.createElement("canvas"); // render canvas
rCanvas.width = ?
rCanvas.height = ?
var pCanvas = rCanvas.cloneNode(); // presentation canvas
document.body.appendChild(pCanvas); // add to DOM 
var ctx = rCanvas.getContext("2d");  
var pCtx = rCanvas.getContext("2d"); // presentation context

Then render to the render canvas as normal, once the frame has been rendered you can change the position by rendering it offset onto the presentation canvas 然后正常渲染到渲染画布,一旦渲染了框架,您可以通过将其偏移渲染到演示画布上来更改位置

pCtx.drawImage(rCanvas,x,y); // present canvas at x, and y

Depending on the type of game you may want to extend the render canvas's size so that when it shakes you do not lose pixels around the edge. 根据游戏类型的不同,您可能需要扩展渲染画布的大小,以使其在摇动时不会丢失边缘周围的像素。

More than just shake. 不仅仅是摇晃。

Using offscreen canvases is not limited to just one. 使用屏外画布不仅限于一种。 I convert all images, sprite sheets, UI panels, whatnot to canvases. 我将所有图像,精灵表,UI面板等转换为画布。 Then present them to the onscreen canvas each frame. 然后将它们呈现给屏幕上每一帧的画布。 This opens up many extra FX not available if just using one canvas, and also reducing the render load, as I only need to re-render only what has changed per frame. 如果只使用一个画布,这将打开许多无法使用的FX,并且还减少了渲染负载,因为我只需要重新渲染每帧更改的内容。

So for example if you have a UI panel separate from the playfield render you can give each a slightly different shake amount, adding a bit of depth to the display. 因此,例如,如果您有一个与游戏场渲染分开的UI面板,则可以给每个晃动量稍有不同,从而增加显示的深度。 You can brighten the whole play field as well by just rendering the playfield again with pCtx.globalCompositeOperation = "lighter" and pCtx.globalAlpha = amount` to control the level. 您也可以通过使用pCtx.globalCompositeOperation = "lighter"和pCtx.globalAlpha = amount来再次渲染游戏场来控制整个关卡,从而使整个游戏场变亮。 The flash will add to the shake FX giving a more immersive experience. 闪光灯将添加到摇动FX中,从而提供更身临其境的体验。

You may even have the final presentation canvas as a webGL context opening up unlimited FX possibilities not possible using the DOM while still allowing you to use the 2D API for the main rendering of the game. 您甚至可能拥有最终的演示画布作为webGL上下文,从而打开了使用DOM不可能实现的无限FX可能性,同时仍然允许您将2D API用于游戏的主要渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Javascript / html5 2d画布上下文-相对于画布获取X,Y(与转换后的对象相对) - Javascript/html5 2d Canvas Context - Getting X, Y relative to canvas (opposed to transformed object) 使用HTML Canvas和Greasemonkey的问题无法在2D上下文上使用drawImage() - Problems using HTML Canvas & Greasemonkey not able to drawImage() on 2D context 为了获得良好的性能,是否需要清除HTML5中的canvas [2D上下文]? - Is clearing canvas [ 2D Context ] in HTML5 necessary for good performance? 从HTML Canvas 2D上下文获取内部图像 - Get inner image from HTML Canvas 2D Context 使用2D渲染上下文的HTML5 Canvas转换问题 - HTML5 Canvas transformation issue using 2D rendering context 如何获得画布html5中的上下文X和Y位置 - How to get the context X and Y position within a canvas html5 HTML5 Canvas 2D相机,仅在屏幕上渲染东西吗? - HTML5 Canvas 2D Camera and only rendering things on the screen? 使用2d上下文时,什么决定了HTML5画布上context.fillRect的原点? - What determines the origin point for context.fillRect on an HTML5 canvas when using 2d context? 我无法使多个2d对象从画布x和y反弹 - I'm unable to make multiple 2d objects bounce off a canvas x and y Chrome和Firefox中的canvas.getContext(“ 2d”)。getImageData(x,y,1,1).data问题 - Issues with canvas.getContext(“2d”).getImageData(x,y,1,1).data in chrome and firefox
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM