Parallax scrolling in Sprite LibGDX - scroll

I want to parallax scroll a Texture behind a Sprite with fixed width and height.
The problem is i need to just scroll the Texture in a given width and height and not to the end of the screen. I need something like a window view on this texture.
i could overlay the rest of the screen with black areas but there has to be a better solution i guess ;-)
currently im doing this
sprite.setX(sprite.getX() + (OVERLAY_ANIMATION_SPEED * delta));
sprite2.setX(sprite2.getX() + (OVERLAY_ANIMATION_SPEED * delta));
and reset the sprite where x is bigger than the screen width. But i have a smaller area inside the screen in which the scrolling should appear not from the beginng to the end of the screen.
Hope somebody has a hint for me how to achive this.

I'm using a glViewport to achieve something similar:
public void setViewPort(float dx, float dy, float sx, float sy)
{
Gdx.gl.glViewport((int) (screenWidth * dx), (int) (screenHeight * dy),
(int) (screenWidth * sx), (int) (screenHeight * sy));
}
So:
setViewPort(0, 0, 1, 1);
would render fullscreen and:
setViewPort(0.2f, 0.2f, 0.6f, 0.6f);
would render a 60% sized 'sub'window-viewport at 20% position
(thus centered), nothing is rendered outside that window (clipped by OpenGL). Hope this helps someone!

Related

Unity3d UI issue with Xiaomi

In Xiaomi devices, there are drawn an image outside of camera's letterbox
In other devices everything is correct
I attached both sumsung and xiaomi images, the screenshot that looks ugly is xiaomi, and good look in samsung
float targetaspect = 750f / 1334f;
// determine the game window's current aspect ratio
float windowaspect = (float)Screen.width / (float)Screen.height;
// current viewport height should be scaled by this amount
float scaleheight = windowaspect / targetaspect;
// obtain camera component so we can modify its viewport
Camera camera = GetComponent<Camera>();
// if scaled height is less than current height, add letterbox
if (scaleheight < 1.0f)
{
Rect rect = camera.rect;
rect.width = 1.0f;
rect.height = scaleheight;
rect.x = 0;
rect.y = (1.0f - scaleheight) / 2.0f;
camera.rect = rect;
}
try setting the image to clamp instead of repeat.
this will give the result of black borders but you won't have that weird texture
I don't know what caused that problem, however i solved it in a tricky way. I just added second camera to display black background. Only My main camera's viewport is letterboxed, but not second camera. So it made display to look good

UI Elements not scaling while using Canvas Scaler

I'm trying to make my UI elements work and remain the same for every different resolution. I added a Canvas Scaler to my Canvas and played around with the settings until it looked finished.
I then tried building the game and running it at few different resolutions to confirm that it was working. However, the Canvas Scaler doesn't seems to work.
http://prntscr.com/d1afz6
Above is some random resolution but that's how big my editor screen is and that's what I'm using as my reference resolution. That's also the hierarchy for this specific Canvas http://prntscr.com/d1aggx. It takes almost the whole screen when ran at 640x480. I have no clue why this is not working. I've read most of the unity guides on that but none of them seem to have that problem.
Ok, to fit something no matter the size of the screen, you have to use a separate coordinate system than Unity's absolute system. One of Unity's models is the View. The View is coordinates 0,0 at the top left, and 1,1 at the bottom right. Creating a basic Rect that handles that, is the following.
using UnityEngine;
namespace SeaRisen.nGUI
{
public class RectAnchored
{
public float x, y, width, height;
public RectAnchored(float x, float y, float width, float height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public static implicit operator Rect(RectAnchored r)
{
return new Rect
{
x = r.x * Screen.width,
y = r.y * Screen.height,
width = r.width * Screen.width,
height = r.height * Screen.height
};
}
}
}
Here, we take the normal Rect floats, the x,y coordinates along with a width and height. But these are in the values [0..1]. I don't clamp it, so it can be tweened on and off the screen with animation, if desired.
The following is a simple script that create's a button in the lower right corner of the screen, and resizes as the screen grows or shrinks.
void MoveMe()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, -Vector3.up, out hit, float.MaxValue)
|| Physics.Raycast(transform.position, Vector3.up, out hit, float.MaxValue))
transform.position = hit.point + Vector3.up * 2;
}
void OnGUI()
{
if (GUI.Button(new RectAnchored(.9f, .9f, .1f, .1f), "Fix me"))
{
MoveMe();
}
}
The X is .9 to the right and Y .9 from the top, and width and height of .1, so the button is 1/10th of the screen in height and width, positioned in the bottom 1/10th of the screen.
Since OnGUI is rendered every frame (or so), the button rect updates with the screen resize automatically. The same would work in a typical UI, if you are using Update() to render your windows.
I hope this explains the difference between what I meant with absolute coordinates. Setting say the previous example (using absolutes) in 640x480, it'd be something like new Rect(576, 432, 64, 48) and it wouldn't scale. By using new RectAnchored(.9f, .9f, .1f, .1f) and have it rendered into UI space based on Screen size, then it scales automatically.

Flip image with different size width smooth transition

I'm trying to flip some animations in LibGDX, but because they are of different width, the animation plays weird. Here's the problem:
(the red dot marks the X/Y coordinate {0,0})
As you can see, when the animation plays "left" when you punch, the feet starts way behind than were it was, but when you punch right, the animations plays fine because the origin of both animations is the left corner, so the transition is smooth.
The only way I think of achieving what I want is to see what animation is playing and adjust the coordinates accordingly.
This is the code:
public static float draw(Batch batch, Animation animation, float animationState,
float delta,
int posX, int posY, boolean flip) {
animationState += delta;
TextureRegion r = animation.getKeyFrame(animationState, true);
float width = r.getRegionWidth() * SCALE;
float height = r.getRegionHeight() * SCALE;
if (flip) {
batch.draw(r, posX + width, posY, -width, height);
} else {
batch.draw(r, posX, posY, width, height);
}
return animationState;
}
Any suggestion is welcome as how to approach this.
Use some other batch.draw option (with other parameters). You can set "origin" parameters. It's like a hot spot...center of the image... So if you i.e. rotate, rotation will be done around that hot spot.
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/Batch.html
I didn't use it for flipping, but it should work the same way. But if it doesn't then you have to adjust coordinates on your own, make some list with X offset for every frame and add it for flipped images.
Other solution would be to have wider frame images and keep center of the character always match the center of the image. That way your images will be wider then they have to - you'll have some empty space, but for sane number of frame it's acceptable.

How to get the title bar height and width for aero and basic design

I am using GetSystemMetrics(SM_CXSIZEFRAME) for the width of the border, it works with the basic design, but not with aero, how can I improve it, so it works with aero?
I am using GetSystemMetrics(SM_CYCAPTION) for the height of the title bar but the value is too small for both, basic and aero design, what am I doing wrong here?
In unthemed Windows, GetSystemMetrics(SM_CYCAPTION) is the height of the text in the title bar; you need to add in the size of the frame and border padding (GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYEDGE) * 2).
For themed Windows (which is the default these days), GetThemeSysSize is most likely the function you're looking for; in particular, GetThemeSysSize(SM_CXBORDER) for the border width, and GetThemeSysSize(SM_CYSIZE) + GetThemeSysSize(SM_CXPADDEDBORDER) * 2 for the title bar.
I had a similar problem, where I needed to subtract the title bar height from the mouse Y to render a cursor in the window.
After looking around, and looking at functions like GetSystemMetrics, I ended up just using GetWindowRect and ClientToScreen.
I got the screen position of the client area using ClientToScreen with point 0,0.
Then subtracted that from the window top retrieved through GetWindowRect. Result is the distance from the top of the window to the inside of the window. Or the titlebar height.
int getWindowHeadSize()
{
RECT Rect;
GetWindowRect(hWnd, &Rect);
POINT point = { 0, 0 };
ClientToScreen(hWnd, &point);
return point.y - Rect.top + GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYEDGE) * 2;
}

Convert from 1280x720 to UIView dimensions

I have an app that finds QR finder marks from the AVCaptureDevice sample buffer delegate. Now I am trying to put boxes on the screen to cover the QR marks. However, I am having trouble converting between 1280x720 pixel resolution and the cameraView size.
I'm trying to write a method that converts a CGRect based on these parameters (and the fact that the view coordinate system is upside-down), but it won't work. It might have something to do with the orientation of the camera device as well. Here is my code for the converting method:
-(CGRect) convertRect:(CGRect) oldRect From90DegreeRotatedCameraSize1280x720ToUIViewSize:(CGSize) viewSize
{
//remember that we are using a gravity of resize aspect fill
double xScale = viewSize.width / 720;
double yScale = viewSize.height / 1280;
if (xScale < yScale)
return CGRectMake(oldRect.origin.x * xScale, viewSize.height - oldRect.origin.y * xScale, oldRect.size.height * xScale, oldRect.size.width * xScale);
else
return CGRectMake(oldRect.origin.x * yScale, viewSize.height - oldRect.origin.y * yScale, oldRect.size.height * yScale, oldRect.size.width * yScale);
}
Anyone got an elegant to solution to this relatively simple spacial coordinate problem?
EDIT -
I did a NSLog of the connection video orientation and it turns out that it never changes from 1 (which I think is enum'ed to portrait orientation.) From this, it should be easier to find a solution because the coordinates do not change in different orientations.
Any ideas, coder community?
Figured it out:
When iOS fills a view, it centers it so that the both sides are cut off. In order to transition between view coordinates, you need to scale and THEN translate in the direction that was cut off:
return CGRectMake(oldRect.origin.x * xScale, oldRect.origin.y * xScale - (1280 * xScale - viewSize.height) / 2, oldRect.size.height * xScale, oldRect.size.width * yScale);

Resources