Phaser: Make background screen-width instead of content-width - android

I am making a game using the Phaser Framework for Android. I need to make the canvas fill the entire screen width and then flood it with background color, then put content in the center of screen. Currently, even though I already set the width of the canvas to window width, Phaser still reset it to content width, which is smaller, then filling only the content width with background.
How do I stop Phaser from using content width?
var gameObj = new Phaser.Game($(".parent").width(), 700, Phaser.CANVAS, 'parent');
gameObj.stage.backgroundColor = '#A6E5F5';
gameObj.load.image('prld', 'prl.png');
gameObj.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
gameObj.scale.pageAlignHorizontally = true;
gameObj.scale.pageAlignVertically = true;
gameObj.scale.setScreenSize(true);
gameObj.scale.refresh();
gameObj.stage.backgroundColor = '#A6E5F5';
// Load Content Here
gameObj.load.image('h1', 'res1/h1.png');
gameObj.load.image('h2', 'res1/h2.png');
....
g = gameObj.add.group();
g.create(20, 20, 'h1');
g.create(60, 20, 'h2');
....

You need Phaser 2.2+ for this, but if you want the canvas to fill the entire screen space available you would do:
var game = new Phaser.Game("100%", "100%", Phaser.CANVAS, 'parent');
...
game.scale.scaleMode = Phaser.ScaleManager.RESIZE;
Also you should not use pageAlign if you're using 100% dimensions. You also don't need to call refresh or setScreenSize.
When working in the RESIZE scale mode you can add a function to your States called 'resize'. It will be called whenever the screen dimensions change (orientation event perhaps) and be passed 2 parameters: width and height. Use those to adjust your game content layout.
You may want to get the Phaser Scale Manager book, it covers all this in lots more detail (caveat: I wrote it, but it has a "pay what you want" price, including completely free)

i use this code in my game and it work very nice without changing in position of any elements
var targetWidth = 720; // the width of the game we want
var targetHeight = 480; // the height of the game we want
// additional ratios
//Small – 360x240
//Normal – 480x320
//Large – 720x480
//XLarge – 960x640
//XXLarge – 1440x960
var deviceRatio = (window.innerWidth/window.innerHeight); //device aspect ratio
var newRatio = (targetHeight/targetWidth)*deviceRatio; //new ratio to fit the screen
var newWidth = targetWidth*newRatio;
var newHeight = targetHeight;
var gameWidth = newWidth;
var gameHeight = newHeight;
var gameRendrer = Phaser.AUTO;
and this code for Boot state
game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
game.scale.pageAlignHorizontally = true;
game.scale.pageAlignVertically = true;
game.scale.forceLandscape = true;
game.scale.setScreenSize(true);
this for landscape mode if you want to make it for portrait change width and height like
var targetWidth = 480; // the width of the game we want
var targetHeight = 720; // the height of the game we want
also force it to portrait
this code work well in my games

Related

preview stretches in camera2 apis

Following are the screenshots when using texture view in camera2 apis.In full screen the preview stretches,but it works when using lower resolution(second image).
How to use this preview in full screen without stretching it.
Below answer assumes you are in portrait mode only.
Your question is
How to use the preview in full-screen without stretching it
Let's break it down to 2 things:
You want the preview to fill the screen
The preview cannot be distorted
First you need to know that this is logically impossible without crop, if your device's viewport has a different aspect ratio with any available resolution the camera provides.
So I would assume you accept cropping the preview.
Step 1: Get a list of available resolutions
StreamConfigurationMap map = mCameraCharacteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
throw new IllegalStateException("Failed to get configuration map: " + mCameraId);
}
Size[] sizes = map.getOutputSizes(SurfaceTexture.class);
Now you get a list of available resolutions (Sizes) of your device's camera.
Step 2: Find the best aspect ratio
The idea is to loop the sizes and see which one best fits. You probably need to write your own implementation of "best fits".
I am not going to provide any code here since what I have is quite different from your use case. But ideally, it should be something like this:
Size findBestSize (Size[] sizes) {
//Logic goes here
}
Step 3: Tell the Camera API that you want to use this size
//...
textureView.setBufferSize(bestSize.getWidth(), bestSize.getHeight());
Surface surface = textureView.getSurface();
try {
mPreviewRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mCamera.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
mSessionCallback, null);
} catch (final Exception e) {
//...
}
Step 4: Make your preview extends beyond your viewport
This is then nothing related to the Camera2 API. We "crop" the preview by letting the SurfaceView / TextureView extends beyond device's viewport.
First place your SurfaceView or TextureView in a RelativeLayout.
Use the below to extend it beyond the screen, after you get the aspect ratio from step 2.
Note that in this case you probably need to know this aspect ratio before you even start the camera.
//Suppose this value is obtained from Step 2.
//I simply test here by hardcoding a 3:4 aspect ratio, where my phone has a thinner aspect ratio.
float cameraAspectRatio = (float) 0.75;
//Preparation
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;
int finalWidth = screenWidth;
int finalHeight = screenHeight;
int widthDifference = 0;
int heightDifference = 0;
float screenAspectRatio = (float) screenWidth / screenHeight;
//Determines whether we crop width or crop height
if (screenAspectRatio > cameraAspectRatio) { //Keep width crop height
finalHeight = (int) (screenWidth / cameraAspectRatio);
heightDifference = finalHeight - screenHeight;
} else { //Keep height crop width
finalWidth = (int) (screenHeight * cameraAspectRatio);
widthDifference = finalWidth - screenWidth;
}
//Apply the result to the Preview
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) cameraView.getLayoutParams();
lp.width = finalWidth;
lp.height = finalHeight;
//Below 2 lines are to center the preview, since cropping default occurs at the right and bottom
lp.leftMargin = - (widthDifference / 2);
lp.topMargin = - (heightDifference / 2);
cameraView.setLayoutParams(lp);
If you don't care about the result of Step 2, you can actually ignore Step 1 to Step 3 and simply use a library out there, as long as you can configure its aspect ratio. (It looks like this one is the best, but I haven't tried yet)
I have tested using my forked library. Without modifying any code of my library, I managed to make the preview fullscreen just by using Step 4:
Before using Step 4:
After using Step 4:
And the preview just after taking a photo will not distort as well, because the preview is also extending beyond your screen.
But the output image will include area that you cannot see in the preview, which makes perfect sense.
The code of Step 1 to Step 3 are generally referenced from Google's CameraView.
That's a common problem on some devices. I've noticed it mostly on samsung. You may use a trick with setting transformation on your TextureView to make it centerCrop like ImageView behaviour
I also faced similar situation, but this one line solved my problem
view_finder.preferredImplementationMode = PreviewView.ImplementationMode.TEXTURE_VIEW
in your xml:
<androidx.camera.view.PreviewView
android:id="#+id/view_finder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
For camera implementation using cameraX you can refer
https://github.com/android/camera-samples/tree/master/CameraXBasic
I figured out what was your poroblem. You were probably trying something like this:
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int j) {
cam.startPreview(surfaceTexture, i, j);
cam.takePicture();
}
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { }
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { return false; }
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { }
});

Use x/y coordinates to set bounds of a moving particle

I have two bitmaps that I draw onto the center of a canvas:
One is only a background, it's a spirit level in top view which doesnt move. The second one is a bitmap looking like a "air bubble". When the user tilts the phone, the sensors read the tilt and the air bubble moves according to the sensor values along the x-axis. However, I need to make sure that the air bubble doesnt move too far, e.g out of the background-bitmap.
So I tried to which x coordinate the bubble can travel to,
before I have to set xPos = xPos -1 using trial and error
This works fine on my device.
To clarify: On my phone, the air bubble could move to the coordinate x = 50 from the middle of the screen. This would be the point, where the bitmap is at the very left of the background spirit level.
On a larger phone, the position x = 50 is too far left, and therefore looking like the air bubble travelled out of the water level.
Now I've tried following:
I calculated the area in % in which the air bubble can move. Let's say that
is 70% of the entire width of the bitmap. So I tried to calculate the two x boundary values:
leftBoundary = XmiddlePoint - (backgroundBitmap.getWidth() * 0.35);
rightBoundary = XmiddlePoint + (backgroundBitmap.getWidth() * 0.35);
...which doesnt work when testing with different screen sizes :(
Is it possible to compensate for different screen sizes and densities using absolute coordinates or do I have to rethink my idea?
If you need any information that I forgot about, please let me know. If this question has already been answered, I would appreciate a link :) Thanks in advance!
Edit:
I load my bitmaps like this:
private Bitmap backgroundBitmap;
private static final int BITMAP_WIDTH = 1898;
private static final int BITMAP_HEIGHT = 438;
public class SimulationView extends View implements SensorEventListener{
public SimulationView(Context context){
Bitmap map = BitmapFactory.decodeResource(getResources, R.mipmap.backgroundImage);
backgroundBitmap = Bitmap.createScaledBitmap(map, BITMAP_WIDTH, BITMAP_HEIGHT, true;
}
and draw it like this:
protected void onDraw(Canvas canvas){
canvas.drawBitmap(backgroundBitmap, XmiddlePoint - BITMAP_WIDTH / 2, YmiddlePont - BITMAP_HEIGHT / 2, null);
}
backgroundBitmap.getWidth() and getHeight() prints out the correct sizes.
Calculating like mentioned above would return following boundaries:
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
//which prints out width = 2392
xMiddlePoint = width / 2;
// = 1196
leftBoundary = xMiddlePoint - (BITMAP.getWidth()* 0.35);
// = 531,7
However, when I use trial and error, the right x coordinate seems to be at around 700.
I've come across a great explanation on how to fix my issue here.
As user AgentKnopf explained, you have to scale coordinates or bitmaps like this:
X = (targetScreenWidth / defaultScreenWidth) * defaultXCoordinate
Y = (targetScreenHeight / defaultScreenHeight) * defaultYCoordinate
which, in my case, translates to:
int defaultScreenWidth = 1920;
int defaultXCoordinate = 333;
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
displayWidth = displayMetrics.widthPixels;
leftBoundary = (displayWidth / defaultScreenWidth) * defaultXCoordinates

Action Script External SWF Fill Screen

My AS3 code:
var ldr:Loader = new Loader();
ldr.load(new URLRequest("midos.swf"));
addChild(ldr);
But my swf resolution is 720x460.
And my project resolution 720x480. How i can fill my swf all to project screen?
//assuming that you want to scale it based on your stage. If not, just provide correct value
var targetHeight:Number = stage.stageHeight;
var scale:Number = targetHeight / ldr.height;
ldr.scaleY = scale;
//if you want to scale proportionally
ldr.scaleX = scale;

RelativeLayout for Android?

So I have been experimenting today with making an Android Application, but I have tried the LineairLayout to make a welcom screen for my application, but I cannot get it right..
So I tried RelativeLayout and I saw I can move my ImageViews and buttons to everywhere. So my question is if I will move the items to places like center, bottom left and bottom right. Would this be a problem or all phones since not all phones have the same dimensions?
public class WelcomeActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.welcome_screen_relative);
final ImageView logo = (ImageView) findViewById(R.id.myImageView);
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
int displayHeight = metrics.heightPixels;
int displayWidth = metrics.widthPixels;
float scaledDensity = metrics.scaledDensity;
BitmapFactory.Options dimensions = new BitmapFactory.Options();
dimensions.inJustDecodeBounds = true;
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.log, dimensions);
int imageHeight = dimensions.outHeight;
int imageWidth = dimensions.outWidth;
float percentageToMoveViewDown = (float) 20.0;
float viewY_float = (float) ((displayHeight / 100.0) * percentageToMoveViewDown);
int viewY_int = Math.round(viewY_float);
RelativeLayout.LayoutParams view_Layout_params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view_Layout_params.topMargin = viewY_int;
logo.setLayoutParams(view_Layout_params);
logo.getLayoutParams().height = imageHeight;
logo.getLayoutParams().width = imageWidth;
}
Thats depends. If you give objects a fixed size of course it will. for dp/dpi make sure to test it in Emu or real devices. You can also create density and orientation specific layout to support many screens. Consider that there are not only changes in size but also aspect ration and resolution and DPI.
For most apps RelativeLayout is might be the right approach.
You can read an excelent article about it here: http://developer.android.com/guide/practices/screens_support.html
If the items have fixed sizes you always will have trouble with some phones. For the big ones it may be too small, for the small ones too big...
In my experience Androids small/normal/large screens won't help you much for configuring, since the differences are just too big.
If you want to make sure everything sits where it belongs to, you could get the device metrics. That way you don't even need to rely on center, but you can work with percentages to place everything where you want it to be. Plus you can set the sizes in percentage, which is great. Like you could say I want a button thats width is 50% of the screen, no matter how large the screen is. Its more work (maybe even overkill), but I really like that approach. Once you figured it out its basically just a bit copy paste at the start of your classes.
Example:
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
int displayHeight = metrics.heightPixels;
int displayWidth = metrics.widthPixels;
float scaledDensity = metrics.scaledDensity;
//move some View 20% down:
float percentageToMoveViewDown = (float) 20.0;
float viewY_float = (float) ((displayHeight / 100.0) * percentageToMoveViewDown);
int viewY_int = Math.round(viewY_float);
RelativeLayout.LayoutParams view_Layout_params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
view_Layout_params.topMargin = viewY_int;
view.setLayoutParams(view_Layout_params);
//even works with text size for a TextView:
float percentageToResizeTextViewTextSize = (float) 3.1;
float textViewTextSize_float = (float) ((displayHeight / 100.0) * percentageToResizeTextViewTextSize);
int textViewTextSize_int = Math.round(textViewTextSize_float / scaledDensity);
textView.setTextSize(textViewTextSize_int);
Just a side note for the overkill thing: This should be only necessary if you want to support small devices (they mostly run something like android 2.3, but still are sold as budget phones) and big devices as well, but the trouble with the big ones is not as big as the trouble with the small ones. I personally rather put more effort in it than less, you never know.
Edit: ImageView by code
The easiest way is to do it hybridly, using xml and code. Note that you will have to change width and height if you set it to 0 in xml like in the following example.
Just place it in the xml where you would anyways, somewhere in your RelativeLayout.
In your xml:
<ImageView
android:id="#+id/myImageView"
android:layout_width="0dp"
android:layout_height="0dp" />
In your Code:
ImageView myImageView = (ImageView)findViewById(R.id.myImageView);
You now can work with that myImageView as I did it with view and textView. You can even set the image right here in code.
This imageView with the size of 0,0 is now placed where it would have been before. Now you could set the width to like 50% of the screenwidth and the height to...lets say 40% of the screen height. Then You would need to place it. If you want to center it you know that there must be 25% of the screen on each side, so you can add 25% as left and right margin.
Edit 2: maintain original imagesize
If you want to keep the original size of a image in your drawables, you can get its width and height like this:
BitmapFactory.Options dimensions = new BitmapFactory.Options();
dimensions.inJustDecodeBounds = true;
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.yourImageName, dimensions);
int imageHeight = dimensions.outHeight;
int imageWidth = dimensions.outWidth;
Now that you have that, you could use it to calculate the aspect ratio to keep it.
Now since you know the devices width and height, you can easily calculate how much of the screen this image will need.(imageheight/screenheight*100 = your percentage of the screen you want the imageviews height to be). So the Height you set to the imageview would be displayHeight / 100 * (imageHeight / displayHeight * 100).
How to place that?
Now if you take a Screenheight of 100 and a imageheight of 80 you get 80%. You would now take this percentage and divide it from 100. Divide that /2 and you know how much space you would have as top and bottom margins if you wanted it to be placed in the middle of the screen (you would have to do the same for width).
Caution: If you don't want it to be relative to the screensize but the original size, that percentage approach is kind of pointless. If you do to your image what I just described, it may still be too big for small devices and too small for big ones. Instead you could think about what percentage would look good in proportion to the rest of the stuff on the screen and resize it to that, since it would have that relative size on all devices.
Edit 3:
Since you load the image in original size, it will be small on big devices if it is a small image.
//first you need to know your aspect ratio.
float ratio = imageWidth / imageHeight;
//lets say you wanted the image to be 50% of the screen:
float percentageToResizeImageTo = (float) 50.0;
float imageX_float = (float) ((displayHeight / 100.0) * percentageToResizeImageTo);
int imageX_int = Math.round(imageX_float);
//now you know how much 50% of the screen is
imageWidth = imageX_int;
imageHeight = imageWidth * ratio;
RelativeLayout.LayoutParams view_Layout_params = new RelativeLayout.LayoutParams(imageHeight, imageWidth);
view_Layout_params.topMargin = viewY_int;
logo.setLayoutParams(view_Layout_params);
logo.setScaleType(ImageView.ScaleType.Fit_XY);

RelativeLayout margin shrinks ImageView

I'm trying to dynamically build a layout, so it scales and looks more or less identical on all screen sizes and resolutions. I do this by programmatically placing my views inside a RelativeLayout and scaling everything according to a certain factor.
I noticed something strange when moving an ImageView around though, the bigger the values on margins get, the smaller the ImageView gets. This gets really annoying when trying to get things at right place and size.
private void initializeObjects() {
Display display = getWindowManager().getDefaultDisplay();
Point screenSize = new Point();
display.getSize(screenSize);
float scale = screenSize.x / ( (screenSize.x < screenSize.y) ? 480 : 800 ); // Scale according to Galaxy S II resolution
RelativeLayout screenLayout = (RelativeLayout) findViewById(R.id.main_layout);
mRobotView = new ImageView(getApplicationContext());
mRobotView.setImageResource(R.drawable.soomla_logo_new); // a 743 x 720 png
mRobotView.setScaleX(scale * 100 / 743); // Make sure the image is 100 "units" in size
mRobotView.setScaleY(scale * 100 / 720);
mRobotView.setPivotX(scale * 100 / 743); // reset the image origin according to scale
mRobotView.setPivotY(scale * 100 / 720);
RelativeLayout.LayoutParams robotParams = new RelativeLayout.LayoutParams(743, 720);
robotParams.leftMargin = 0xDEADBEEF; // The bigger these get the smaller the view gets
robotParams.topMargin = 0xDEADBEEF;
screenLayout.addView(mRobotView, robotParams);
}
Any idea what's causing this?
Use
android:layout_height="720px"
android:layout_height="743px"
in the main_layout.xml to have the image not shrinked

Categories

Resources