How can I prevent objects from being fuzzy in canvas? - javascript

Currently, I'm doing a mini game which only has a box and a character.
The character can freely move around. I did so it moves 640px/second. The "formula" I use to get the pixels to move each frame is ((currentFrameTimeMs - lastFrameTimeMs) * pxPerSecond) / 1000. Actual values are ((currentFrameTimeMs - lastFrameTimeMs) * 640) / 1000. This effectively makes my character to move exactly 640px/s.
But the problem is that when moving, I see it as "fuzzy". I've checked out the FPS, and it's very far above 60, yet the image still looks fuzzy.
Is there any technique to remove that blurriness? I've played desktop games which have objects moving pretty fast, and they don't blur, so I suppose there's some trick for that.

Problem solved.
Problem was with FPS, they were under 60. I was using a wrong approach (with requestAnimationFrame, but wrong calculations).

Round the result so your image will always be at an exact pixel index, rather than "between" pixels. If you don't round, the pixels of your image will be "spread" between pixels and might appear blurry.

Related

Smooth SVG Axis Animation

I'm attempting to render a scrolling axis at 60 fps. It was nearly as simple as updating the scale's domain and calling axisGroupElement.call(axis) inside a loop. Unfortunately at different scales that produces some very smooth animations where the ticks and the text will jiggle.
http://jsfiddle.net/langdonx/fTcrU/11/
The jiggling probably depends on the width of the container and the length of the scale's domain... try changing the drop down for different results.
So, I thought I'd be creative and render the axis 3 times the size I needed and transform the entire group for a smoother scroll. That unfortunately produces nearly the same results.
I went a step further and moved the entire SVG element, which is a little smoother, but a huge hack.
There's also a problem where I can't get my own transform scrolling at the same rate the redraw scrolls at. It seems to fall behind over time. I thought I had it nailed down by calculating milliseconds per pixel, but that doesn't appear to be totally correct. It's interesting to see how it certain resolutions it'll tick along at 1px, store the remaining milliseconds, and then some ticks will adjust it 2px.
Is there anything I can do or is scrolling these irregular widths/time spans always going to produce animations that aren't smooth?
TIA!
The axis redraw example looks nicer because it sets the transform values more exactly as floating point numbers, whereas your calculation for transform produces integers.
I've amended your algorithm to produce floats, and now the "Redraw" and "Redraw and Transform" examples look identical.
http://jsfiddle.net/xJJHM/1/
The relevant change is
_left -= msPassed / _msPerPixel;
I tried to do the same with the left-positioning, but it turns out that you need integer values for that.
I found an article/video by Paul Irish which explains this in more detail: http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/

How to snap mouse point to an angle in JavaScript

I've been working on an application with a JavaScript/HTML5 canvas. Here's a JSFiddle with some code to show you kind of what I'm doing: JSFiddle
As you can see on the fiddle, after you create two points the cursor starts snapping to 90° and 180°, respectively. But there's a bug, and I don't know how to fix it. It snaps perfectly to 90°, except when you get too close to the last created point, and then it wobbles a bit. And the 180° snapping is the same, except that it gets wobbly a lot farther away than the 90° does. They both use the same code, so I don't know why they behave differently, and I don't know how to get rid of that wobble either way. So there's the problem, let me try to explain some of my code a bit.
The part that I think is messed up is right at the top, the checkAngle and snapMouseToAngle functions.
checkAngle is pretty straight forward, it takes the last two created points and the point where the mouse cursor is, measures the length of their sides, and measures the current angle using the Law of Cosines (Also, I'm no mathematician, if there's a better way to do this, then please enlighten me).
snapMouseToAngle is a little more complex. First it checks if the current mouse preview is horizontal or vertical. Then it checks the angle, adds 8 pixels (or one foot, as I call it) to the current preview coordinates, and then checks the angle again. Then it goes through the snap function (that huge block of logic), which checks if the mouse is within the angleSnapDistance. If it is, then it subtracts the angle that it's supposed to snap to from the current angle, and puts that value inside of leftOver. leftOver is then divided by the difference, leaving us with a number to subtract from the mouse position.
So what am I doing wrong? I don't know what's causing it to wobble like that, but I sure would be indebted to any of you who could tell me how to fix it. Thanks!
Setting pxPerFoot = 1 removes the wobble. Is the pxPerFoot really necessary? It adds jitter to the observed mouse coordinates. Nice work, though!

HTML5 Canvas Collision Detection "globalCompositeOperation" performance

Morning,
Over the past few months I have been tinkering with the HTML5 Canvas API and have had quite a lot of fun doing so.
I've gradually created a number of small games purely for teaching myself the do's and don'ts of game development. I am at a point where I am able to carry out basic collision detection, i.e. collisions between circles and platforms (fairly simple for most out there but it felt like quite an achievement when you first get it working, and even better when you understand what is actually going on). I know pixel collision detection is not for every game purely because in many scenarios you can achieve good enough results using the methods discussed above and this method is obviously quite expensive on resources.
But I just had a brainwave (It is more than likely somebody else has thought of this and I am way down the field but I've googled it and found nothing)....so here goes....
Would it possible to use/harness the "globalCompositeOperation" feature of canvas. My initial thoughts were to set its method to "xor" and then check the all pixels on the canvas for transparency, if a pixel is found there must be a collision. Right? Obviously at this point you need to work out which objects the pixel in question is occupied by and how to react but you would have to do this for other other techniques.
Saying that is the canvas already doing this collision detection behind the scenes in order to work out when shapes are overlapping? Would it be possible to extend upon this?
Any ideas?
Gary
The canvas doesn't do this automatically (probably b/c it is still in its infancy). easeljs takes this approach for mouse enter/leave events, and it is extremely inefficient. I am using an algorithmic approach to determining bounds. I then use that to see if the mouse is inside or outside of the shape. In theory, to implement hit detection this way, all you have to do is take all the points of both shapes, and see if they are ever in the other shape. If you want to see some of my code, just let me know
However, I will say that, although your way is very inefficient, it is globally applicable to any shape.
I made a demo on codepen which does the collision detection using an off screen canvas with globalCompositeOperation set to xor as you mentioned. The code is short and simple, and should have OK performance with smallish "collision canvases".
http://codepen.io/sakri/pen/nIiBq
if you are using a Xor mode fullscreen ,the second step is to getImageData of the screen, which is a high cost step, and next step is to find out which objects were involved in the collision.
No need to benchmark : it will be too slow.
I'd suggest rather you use the 'classical' bounding box test, then a test on the inner BBOxes of objects, and only after you'd go for pixels, locally.
By inner bounding box, i mean a rectangle for which you're sure to be completely inside your object, the reddish part in this example :
So use this mixed strategy :
- do a test on the bounding boxes of your objects.
- if there's a collision in between 2 BBoxes, perform an inner bounding box test : we are sure there's a collision if the sprite's inner bboxes overlaps.
- then you keep the pixel-perfect test only for the really problematic cases, and you need only to draw both sprites on a temporary canvas that has the size of the bigger sprite. You'll be able to perform a much much faster getImageData. At this step, you know which objects are involved in the collision.
Notice that you can draw the sprites with a scale, on a smaller canvas, to get faster getImageData at the cost of a lower resolution.
Be sure to disable smoothing, and i think that already a 8X8 canvas should be enough (it depends on average sprite speed in fact. If your sprites are slow, increase the resolution).
That way the data is 8 X 8 X 4 = 256 bytes big and you can keep a good frame-rate.
Rq also that, when deciding how you compute the inner BBox, you can allow a given number of empty pixels to get into that inner BBox, trading accuracy for speed.

What is the most processing efficient way to store mouse movement data in JavaScript?

I'm trying to record exactly where the mouse moves on a web page (to the pixel). I have the following code, but there are gaps in the resulting data.
var mouse = new Array();
$("html").mousemove(function(e){
mouse.push(e.pageX + "," + e.pageY);
});
But, when I look at the data that is recorded, this is an example of what I see.
76,2 //start x,y
78,5 //moved right two pixels, down three pixels
78,8 //moved down three pixels
This would preferably look more like:
76,2 //start x,y
77,3 //missing
78,4 //missing
78,5 //moved right two pixels, down three pixels
78,6 //missing
78,7 //missing
78,8 //moved down three pixels
Is there a better way to store pixel by pixel mouse movement data? Are my goals too unrealistic for a web page?
You can only save that information as fast as it's given to you. The mousemove events fires at a rate that is determined by the browser, usually topping at 60hz. Since you can certainly move your pointer faster than 60px/second, you won't be able to fill in the blanks unless you do some kind of interpolation.
That sounds like a good idea to me, imagine the hassle (and performance drag) of having 1920 mousemove events firing at once when you jump the mouse to the other side of the screen - and I don't even think the mouse itself polls fast enough, gaming mice don't go further than 1000hz.
See a live framerate test here: http://jsbin.com/ucevar/
On the interpolation, see this question that implements the Bresenham's line algorithm which you can use to find the missing points. This is a hard problem, the PenUltimate app for the iPad implements some amazing interpolation that makes line drawings look completely natural and fluid, but there is nothing about it on the web.
As for storing the data, just push an array of [x,y] instead of a string. A slow event handler function will also slow down the refresh rate, since events will be dropped when left behind.
The mouse doesn't exist at every pixel when you move it. During the update cycle, it actually jumps from point to point in a smooth manner, so to the eye it looks like it hits every point in between, when in fact it just skips around willy-nilly.
I'd recommend just storing the points where the mouse move event was registered. Each interval between two points creates a line, which can be used for whatever it is you need it for.
And, as far as processing efficiency goes...
Processing efficiency is going to depend on a number of factors. What browser is being used, how much memory the computer has, how well the code is optimized for the data-structure, etc.
Rather than prematurely optimize, write the program and then benchmark the slow parts to find out where your bottlenecks are.
I'd probably create a custom Point object with a bunch of functions on the prototype and see how it performs
if that bogs down too much, I'd switch to using object literals with x and y set.
If that bogs down, I'd switch to using two arrays, one for x and one for y and make sure to always set x and y values together.
If that bogs down, I'd try something new.
goto 4
Is there a better way to store pixel by pixel mouse movement data?
What are your criteria for "better"?
Are my goals too unrealistic for a web page?
If your goal is to store a new point each time the cursor enters a new pixel, yes. Also note that browser pixels don't necessarily map 1:1 to screen pixels, especially in the case of CRT monitors where they almost certainly don't.

Rotating HTML5 canvas slow?

I'm experimenting using rotation on canvas, I have it now so each object has its own rotation. Without them rotating I can get around 400 objects on screen on a very low end computer and nearly 2000 on a normally stocked pc. when I factor in rotation more than 0, the performance drops at least a third!
Why is just changing the rotation slowing it down so much? Is this one of canvases weird hiccups?
I have a global rotation variable and at the beginning of drawing each object I:
ctx.rotate(globRot);
For individual objects cache the rotations. Some of my findings.
Realtime rotation demo
Cached rotations demo (note move up using arrows to find the zombies)
I guess a lot of time might be spent actually creating and multiplying the matrix for the transformation. If you can (find a way to) cache the transformation when it's not changing, that might help. Maybe.

Categories