I don't seem to understand the actor origin in scene2d of Libgdx correctly.
My understanding is as follows:
If I setX of an actor to 0, its left edge is going to be rendered at corrdination 0. Now if I set its origin's X to 5, the fifth pixel of the actor is going to be at corrdination 0, in other words, the left edge of the actor is going to be at -5.
Some how my experience shows otherwise. If I set origin to 5, the left edge somehow is rendered on coordination 5.
Can someone please help me understand this issue.
the origin is used only for scaling and rotation.
That means, that if the origin is P(0,0) (the default), the Actor will be rotated and scaled arround his lower left corner.
If you instead set it's origin to the center (P(width/2, height/2)), he will rotate and scale arround his center.
The position instead is always relative to the lower, left corner and is not affected by the origin.
If you want to set the Actors position relative to his origin, you need to use the origin as offset:
actor.setX(newPosX - actor.getOriginX());
actor.setY(newPosY - actor.setOriginY());
Also remember, that setting an x-origin of 5, like in your example, does not need to set the Actors origin to it's 5th pixel, but to it's 5th unit.
If you use a Viewport, you don't need to calculate things in pixels, which is really important, as you can support different resolutions and aspect ratios.
Related
I made an interface for a game, using extended viewport and when i resize the screen the aspect ratio changes and every element in scene is scales, but when this happens this is what i get :
This is the most annoying issue i dealt with, any advice ? I tried making the tower n times bigger and then just setting bigger world size for the viewport but same thing happens, idk what is this extra pixels on images..
I'm loading image from atlas
new TextureRegion(skin.getAtlas().findRegion("tower0"));
the atlas looks like this:
skin.png
size: 1024,1024
format: RGBA8888
filter: Nearest,Nearest
repeat: none
tower0
rotate: false
xy: 657, 855
size: 43, 45
orig: 43, 45
offset: 0, 0
index: -1
In the third picture, you are drawing your source image just slightly bigger than it's actual size in screen pixels. So there are some boundaries where extra pixels have to be filled in to make it fill its full on-screen size. Here are some ways to fix this.
Use linear filtering. For the best appearance, use MipMapLinearLinear for the min filter. This is a quick and dirty fix. The results might look slightly blurry.
Draw your game to a FrameBuffer that is sized to the same aspect ratio as you screen, but shrunk down to a size where your sprites will be drawn pixel perfect to their original scale. Then draw that FrameBuffer to the screen using an upsampling shader. There are some good ones you can find by searching for pixel upscale shaders.
The best looking option is to write a custom Viewport class that sizes your world width and height such that you will be always be drawing the sprites pixel perfect or at a whole number multiple. The downside here is that your world size will be inconsistent across devices. Some devices will see more of the scene at once. I've used this method in a game where the player is always traveling in the same direction, so I position the camera to show the same amount of space in front of the character regardless of world size, which keeps it fair.
Edit:
I looked up my code where I did option 3. As a shortcut, rather than writing a custom Viewport class, I used a StretchViewport, and simply changed its world width and height right before updating it in the game's resize() method. Like this:
int pixelScale = Math.min(
height / MIN_WORLD_HEIGHT,
width / MIN_WORLD_WIDTH);
int worldWidth = width / pixelScale;
int worldHeight = height / pixelScale;
stretchViewport.setWorldWidth(worldWidth);
stretchViewport.setWorldHeight(worldHeight);
stretchViewport.update(width, height, true);
Now you may still have rounding artifacts if your pixel scale becomes something that isn't cleanly divisible for both the screen width and height. You might want to do a bit more in your calculations, like round pixelScale off to the nearest common integer factor between screen width and height. The tricky part is picking a value that won't result in a huge variation in amounts of "zoom" between different phone dimensions, but you can quickly test this by experimenting with resizing a desktop window.
In my case, I merged options 2 and 3. I rounded worldWidth and worldHeight up to the nearest even number and used that size for my FrameBuffer. Then I draw the FrameBuffer to the screen at just the right size to crop off any extra from the rounding. This eliminates the possibility of variations in common factors. Quite a bit more complicated, though. Maybe someday I'll clean up that code and publish it.
my question is: how can I resize an ObjectContainer3D instance (as it doesn't have "width", "height" and "depth" properties)?
Maybe you can use 'scaleX', 'scaleY', 'scaleZ', or 'scale'.
Note that this will chance the size of the objects in the ObjectContainer3D within the 3D space. Not sure if that's what you're trying to do, given that 3D objects have width, height & depth.
In 3D space there is no concept of pixels. Usually the size is in "units". What you are looking for is a way to render pixel perfect textures. So a pixel mapped onto the 3D object renders as a pixel on screen. This is usually achieved by moving the object at a specific distance from the camera.
Here's a link to a blog post I found on the subject that should point you in the right direction.
In the end the size of the actual 3D object doesn't matter. What matter is the scale and mainly the aspect ratio to render texture as needed. To render a 400px by 200px texture on screen, the 3D plane can be 4 units by 2 units. After that positioning it correctly in front of the camera will produce a 400px by 200px image on screen.
hth.
J.
I've implemented a zoom and crop on the HTML5 Canvas. Zoom is actually increasing the height and width of the Canvas so that it looks zoomed. For crop, I wrote an algorithm to select a rectangular area using mouse and then crop it. Now, if I want to crop when the image is zoomed in or out, while selecting the crop area I have to consider the top and left position displacement caused due to the zoom , which works fine.
So I'm now implementing a rotate (using css3 transform: rotate). The problem is, when I rotate the image by a certain angle, the selection appears a little away from the actual mouse position. This used to happen for the zoom effect as well, but since I used to subtract the added left and top distance from the x and y position resp., I was able to draw the selection even when the image was zoomed. I don't understand how I should do it for a rotated image!
The following image might help you understand my problem a little more clearly:
There's a div around the canvas, reflecting the canvas. It'll have the same width, height, top, left properties as the canvas. This is done on purpose since I can't add the selection, which is absolute, as the child of the canvas. Now this cover, when selected in FireBug, still shows as a rectangle with increased width and height and changed top and left positions.
I understand I have to calculate the displacement like I'm already doing for zoom, but I don't know how to do it! I have spent a lot of time trying out stuff like Pythagoras algorithm and rotational matrix and blah blah!
Please help me out!
You can rotate each of the vertices using this function where "pnt" is a vertex, "pivot" is the point you're rotating around and "angle" is the angle in radians
function rotatePoint(pnt, pivot, angle){
var data = figureAngle(pivot, pnt),
theta = data.angle + angle,
rise = Math.sin(theta) * data.length,
run = Math.cos(theta) * data.length;
return {
x: pivot.x + run,
y: pivot.y + rise
}
}
function figureAngle(start, end){
var rise = (end.y - start.y),
run = (end.x - start.x),
length = Math.sqrt(Math.pow(rise, 2) + Math.pow(run, 2));
return {length: length, angle: Math.atan2(-rise, -run) + Math.PI};
}
Then your horizontal shift is going to be the smallest x of the 4 new vertices, and your vertical shift is going to be the smallest y.
EDIT: this assumes your top left coordinate is [0, 0] before you rotate. If not you need to subtract your starting coordinates from the results i.e. if your top-left corner starts at [50, 100], your horizontal shift would be xMin - 50, and your vertical would be yMin - 100
Having trouble scaling with . It seems to make sense to code up a drawing in canvas to a fixed size (ie 800x600) then scale it for specific locations - but sizing occurs in 4 places: 1) in the context definition (ie ctx.width = 800 2) with ctx.scale; 3) in html with
I can scale it with ctx.scale(0.25,0.25) and use but this doesn't appear right - it seems to want the scale to be proportional.
css sizing simply makes it fuzzy so not a good way to go. Any ideas?
Actually, you can resize a canvas using stylesheets. The results may vary across browsers as HTML5 is still in the process of being finalized.
There is no width or height property for a drawing context, only for canvas. A context's scale is used to resize the unit step size in x or y dimensions and it doesn't have to be proportional. For example,
context.scale(5, 1);
changes the x unit size to 5, and y's to 1. If we draw a 30x30 square now, it will actually come out to be 150x30 as x has been scaled 5 times while y remains the same. If you want the logo to be larger, increase the context scale before drawing your logo.
Mozilla has a good tutorial on scaling and transformations in general.
Edit: In response to your comment, the logo's size and canvas dimensions will determine what should be the scaling factor for enlarging the image. If the logo is 100x100 px in size and the canvas is 800x600, then you are limited by canvas height (600) as its smaller. So the maximum scaling that you can do without clipping part of the logo outside canvas will be 600/100 = 6
context.scale(6, 6)
These numbers will vary and you can do your own calculations to find the optimal size.
You could convert the logo to svg and let the browser do the scaling for you, with or without adding css mediaqueries.
Check out Andreas Bovens' presentation and examples.
You can resize the image when you draw it
imageobject=new Image();
imageobject.src="imagefile";
imageobject.onload=function(){
context.drawImage(imageobject,0,0,imageobject.width,imageobject.height,0,0,800,600);
}
The last 2 arguments are the width an height to resize the image
http://www.w3.org/TR/html5/the-canvas-element.html#dom-context-2d-drawimage
If you set the element.style.width and element.style.height attributes (assuming element is a canvas element) you are stretching the contents of the canvas. If you set the element.width and element.height you are resizing the canvas itself not the content. The ctx.scale is for dynamic resizing whenever you drawing something with javascript and gives you the same stretching effect as element.style.
I have a mask i'm using for a continuous scroll type thingy, and notice that when my masked sprite gets past a certain pixel size in height (2878) the mask does not mask. Has anyone experienced this? is this a bug?
to reproduce:
create a sprite over 2878 px in height and apply mask, mask breaks
create a sprite 2877 px in height and apply mask, mask works
I can't verify if that is a hard limit, but there are a bunch of similar size limits for bitmaps in Flash that crop up in various areas. One potential solution would be to use the scrollRect property of your content display object. When you set scrollRect you are essentially creating a rectangular mask and I'm almost positive I've done it with 5000+ pixel wide sprites in the past.