Pixel art not drawing properly on screen when in motion - libgdx

When camera zoom is 1f
When camera zoom is 1.31f (view is distorted)
The reason it's like this is because I'm using the nearest filter. I have to use nearest filter for pixel art.
I want the map to look properly at different zooms.
in first video, 1 unit equals 4 pixels(world is 320x180, screen is 1280x720) and there is no problem as there is integer scaling.
but since I use zoom it is not possible to always keep the scale at the integer number.
Any ideas on how to properly draw pixel art with libgdx?

Related

libgdx resolution/density scaling assets

Quick question,
I am working on a game in libgdx and have hit a snag. I'm trying to scale my assets and I'm using Gdx.graphics.getDensity() to get the density and then setting my asset size using that as a multiplier. The issue I'm having is that on a tablet that has a 2560x1600 resolution has a density of 2.0, yet the nexus 5 emulator that has 1080x1920 has a density of 2.652... how does the tablet have a smaller density then the smaller phone?
What should I be using to get my multiplier for scaling if density is not reliable based on the android app screen size?
To answer your first question, it's a hardware thing. The Nexus 5 probably has a higher PPI (pixels per inch) ratio than the second, even though the resolution is smaller.
As to your second question, I would propose an alternative to Gdx.graphics.getDensity(): If you are trying to make sure that your asset is the same size relative to the screen (i.e. a 80x80 asset on a 2560x1600 display would be half the size on a 1280x800 display), then I think you want to leave your assets the same size and change the size of your camera instead.
When you create a game in libGDX (or any game engine), you need to keep in mind the difference between three sets of sizes/coordinates in your game:
Viewport size is the size of the space on your screen where your game will draw. It is measured in pixels and defaults to your window size (in a fullscreen game, the size of the screen).
game world size/coordinates are completely arbitrary. They are measured in whatever unit you want (be it meters, inches, bananas, F16s, etc.). You'll know you're working in game world units because you have floats.
camera size is the amount 'world' you can see at one time measured in game units. You can make your camera show a 1280x800 portion of the world or a 3x5 portion of the world or a 137.6x42 portion. The tricky thing is that libGDX's OrthographicCamera class defaults your viewport size, acting as though 1 game unit == 1 pixel.
Hopefully that made sense. Let's look at the implications:
Say I have a 800x600 GU (game unit) asset at 0,0 in my game world. My viewport size is 2560x1600, and my camera is scaled to 2560x1600 as well. My 800x600 GU object will render a 800x600 px image on the screen.
Now suppose I want to port my game to other screen sizes with the same ratio (just to keep things simple for now). I still have a 2560x1600 viewport size, but I change my camera to 8x5 GU and my game object to 2.5x1.875 GU. These sizes will be set explicitely- independent of the viewport size. This makes 1 GU = 320px. The net result is that my game object will still render a 800x600px image on the screen.
Now let's see how this would work on a 1280x800px resolution: My viewport is 1280x800 px, but my camera stays at 8x5 GU and my game object at 2.5x1.875 GU. Because of the size of the camera, 1 GU = 160px, which means my game object renders at 400x300, which means it is proportionally the same size on the smaller screen.
Hopefully that made sense without pictures. When you start using screens with different aspect ratios (i.e. you go from an 8x5 screen to a 3x2 screen), you need a little extra logic to keep the aspect ratio of your viewport the same as your camera (otherwise things get all stretched). Fortunately, libGDX provides some viewports which will do this for you.
You can find an external tutorial by the libGDX community here that talks more about this issue.

html5 Canvas Select an Area and Zoom

I am in the midst of reimplementing an interactive heatmap from svg to canvas in javascript. I was wondering if anyone had any ideas for how allow someone to select an area and have it zoom into that area using html5 canvas and js.
Many thanks,
Tom
Disclaimer: Because you haven't provided any code I am going to stick to Strategy here :)
Method 1: DIY
First thing you will have to decide is what your resolution or cell size in your case is and what happens to a individual cell when you zoom.
Case 1: Your cell size increases, and you just multiply the cellsize by the factor of zoom and clip the area that goes out of bounds of what user selected.
Case 2: You want your heatmap cells to be pixel sized in which case when you zoom in, now each of the previous pixel(or cell) will have to interpolated and you will increase the resolution by the factor of zoom. Of course you will have to re-run heat map function for that region with a greater resolution.
Once you have one of the two strategy figured out, Implementation on JavaScript it actually quite simple.
You hook into drag-event. and let users draw a rectangle to show them the reference area they are zooming into.
Then you calculate you zoom factor based on the ratio of the drawn rectangle, to the original image or the container. This becomes your zoom-factor
Now using the zoom factor you generate a new image, based on Case1 or Case2 depending on which you go with
Finally you replace existing image with old one.
Viola! Zoom!!
Method 2: Use a Library!
Use a awesome library like OpenLayers 3, and just load your heatmap into it. Here's an Heatmap Example done in OpenLayers 3. Zoom pan now come for FREE!
Hope this helps.

Starling move around huge Image

I'm using Starling framework and Flash Builder.
I have big map image(around 5500x4500px) where player is flying around. It is non repeative, not tile based but vector based.
I'm moving camera around following player on each enterFrame event, camera displays approx 800x400 part of map per frame. Camera movemet is simulated by changing X and Y coordinate of maps parent DisplayObject.
What is the best way to draw this and have stable 60fps?
What I have now(attemp with max FPS on mobile):
9 Starling Images with max texture size: 2048x2048(or less on edges). I get 53-60 FPS, but I need stability, I feel like I'm hitting rendering limits already.
What I tried(gives less FPS):
Drawing sprites for each seperate map object(much more than 9 but smaller size)
Using CullingSprite(not rendering itsel when not visible)
Really you only need 4 images the size of your screen which wrap around and sample from the texture atlas. And for a starling implementation movieclips are great because you can just change its contents to a different frame or portion of the texture atlas. This way you aren't deleting and creating new images every time you need to wrap.
Batching is also one way you can improve on it, moving all samples as a single unit.

Working with canvas in different screen sizes

I'm planing to create a simple game using the HTML5 <canvas> tag and compile the code into a native application using Phonegap, but the problem is that canvas use coordinates that are not relative to the size of it, so 20,20 on a 960x640 screen is different on a 480x800 one.
So I want to know how to work with a <canvas> (which will be in fullscreen) on different screen sizes.
So I want to know how to work with a (which will be in fullscreen) on different screen sizes.
This is a common problem that has a pretty easy resolution. Often this is done by separating hard canvas coordinates from what is sometimes called "model" coordinates.
It really depends on how your code is organized, but I assume the game has some height and width to the world that takes up most or all of the screen. The two aspect ratios of the screens you are targeting are 1.5 and 1.666, so you'll want to cater to to the smaller one
So you'll really want to do your game in a set of "model" coordinates that have no bearing on the screen or canvas sizes. Since you are only targeting two screen sizes, your model coordinates can perhaps be 960x640 since that is the smaller of the two aspect ratios. It doesn't have to be. It could be 100x50 for your model coordinates instead. But this example we'll use 960x640 as our model coordinates.
Internally, you never use anything but these model coordinates. You never ever think in any other coordinates when making your game.
When the screen size is 960x640 you won't have to change anything at all since its a 1:1 mapping, which is convenient.
Then when the screen size is actually 800x480, when it comes time to draw to the screen, you'll want to translate all of the model coordinates by (3/4), so the game will be made and internally use 960x480, but it will be drawn in the area of (720x480). You'll also want to take any mouse or touch input and multiply it by (4/3) to turn the screen coordinates into model coordinates.
This translation can be as easy as calling ctx.scale(3/4, 3/4) before you draw everything.
So both platforms will have code that is all written assuming the game is a size of 960x640. The only time that model coordinates become screen coordiantes is when drawing to the canvas (which is a different size) and converting canvas mouse/touch coordinates to model coords.
If that seems confusing to you I can try and make a sample.
Use innerWidth/innerHeight of window object:
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
It'll auto-adjust any screen; you must test for cross platform/screen compatibility!
Also, instead of using pre-defined x,y co-ordinates, use something like this:
var innerWidth = window.innerWidth;
x = innerWidth / 3;
Since you have just 2 screen sizes you can have 2 different canvas (and their logic behind) with different sizes.
If you don't like this solution i think you can only use sizes in % instead of pixel absolute dimension.
The last but not the least, try to set different values in metatag.

Limit filter to visible screen - Actionscript 3

I'm currently working in FlexSDK/AS3 and have a canvas containing many objects. The canvas is large - around 4K x 4K pixels, and I do a lot of scaling/zooming/scrolling about. The viewport is only around 800x450.
I'm trying to apply a blur filter to the canvas - which I have figured out and it works fine, except for this one little bug:
A filter is not applied if the resulting image exceeds the maximum dimensions. In AIR 1.5 and Flash Player 10, the maximum is 8,191 pixels in width or height, and the total number of pixels cannot exceed 16,777,215 pixels. (So, if an image is 8,191 pixels wide, it can only be 2,048 pixels high.) In Flash Player 9 and earlier and AIR 1.1 and earlier, the limitation is 2,880 pixels in height and 2,880 pixels in width. If, for example, you zoom in on a large movie clip with a filter applied, the filter is turned off if the resulting image exceeds the maximum dimensions. -- AS3 docs
When I zoom out my filter works fine. But while zoomed in, the pixel limitation is broken and the filter fails to work.
Since I only need the currently visible section of the screen to blur - the 800x450 slice - is there any way to selectively blur only that portion of the screen?
I don't think you can assign a region of a DisplayObject to apply a filter to. It is all or nothing.
How complex are the contents of the canvas? Are the elements interactive? Can you split them into smaller rectangles and place them into a grid?
If it is just an image or group of images, you could copy the viewable portion into a BitmapData object. You would hide the large canvas and only display the bitmap data using a Bitmap Object. You could add a listener onto zoom and scroll events and then update the BitmapData and Bitmap when necessary.
If it is a group of interactive controls I think your best option is to compose them into a grid. You could then apply a blur to all of the cells in the grid (each being a smaller size).
Be aware that blurring that many pixels will be a real performance hog!