Java: Two backgrounds with same speed are overlapping each other - java

This is my first question and I'll try to make it as clear as possible. Please forgive me if someone asked a similar question before (I checked but found nothing).
I'm trying to create my first android application in java. It's a small game with a character on the left side of the screen (landscape mode) and a background which goes from right to left giving the impression of movement. The speed of the background is meant to be constant.
I used a Background class which looks like this:
public class Background {
int x=0, y=0;
Bitmap background;
Background(int screenX, int screenY, Resources res){
background = BitmapFactory.decodeResource(res, R.drawable.background);
background = Bitmap.createScaledBitmap(background, screenX, screenY, false);
}
}
then in the GameView Class I create 2 background objects
private Background background1, background2;
and in the constructor:
background1 = new Background(screenX, screenY, getResources());
background2 = new Background(screenX, screenY, getResources());
//both backgrounds are the same picture
background2.x = screenX;
paint= new Paint();
finally:
private void update(){
background1.x -=2 * screenRatioX;
background2.x -=2 * screenRatioX;
//both have the same speed
if (background1.x + background1.background.getWidth()<0){
background1.x = screenX;
// to make it reappear on the right side when it vanishes on the left side
}
if (background2.x + background2.background.getWidth()<0){
background2.x = screenX;
}
}
I hope it's clear and that someone will be able to help me.

Edit: I actually solved it by giving background2 a x position relative to the position of background1
private void update(){
background1.x =(int)(background1.x - (2 * screenRatioX));
if(background1.x < background2.x) {
background2.x = background1.x + background1.background.getWidth();}
//(int)(background2.x - (2 * screenRatioX));
else {background2.x =background1.x-background1.background.getWidth();
}
if (background1.x + background1.background.getWidth()<0){
background1.x = background2.x + background2.background.getWidth();
}
if (background2.x + background2.background.getWidth()<0){
background2.x = background1.x+background1.background.getWidth();
}
I'm still interested in understanding why this happened before. Thank you all

Related

Android: Moving an ImageView from updating Values in a Thread

I am trying to make the ImageView missile1 to spawn at a random y-coordinate on the right edge of the screen and then move it left across the screen until it is off the screen, and finally move it back to a random y-coordinate on the right edge of the screen to repeat the process in an infinite loop. The code I have spawns the image at a totally random x and y coordinate location whenever the activity is restarted, but it doesn't move. Can anybody see why it doesn't move and give a solution to my problem? Some example code will be appreciated.
The thread that generates x and y coordinate values:
public class Missiles extends Thread {
private int height, width, currentscore;
private ImageView missile1, missile2, missile3, missile4, missile5;
Handler updatemissile = new Handler();
int min = 100;
RelativeLayout layout;
int setx1, sety1, setx2, sety2, setx3, sety3, setx4, sety4, setx5, sety5;
private Random rand = new Random();
TextView x, y;
Missiles(int screenheight, int screenwidth, ImageView missile01, ImageView missile02, ImageView missile03,
ImageView missile04, ImageView missile05, RelativeLayout rl, TextView xtext, TextView ytext) {
missile1 = missile01;
missile2 = missile02;
missile3 = missile03;
missile4 = missile04;
missile5 = missile05;
height = screenheight;
width = screenwidth;
layout = rl;
x = xtext;
y = ytext;
}
public void updatevalue(int value) {
currentscore = value;
}
public void run() {
SetMissilePosition position = new SetMissilePosition(missile1, layout, x, y);
updatemissile.post(position);
//width is the width of the screen as height is the height of the screen
while (true) {
setx1 = width;
position.updateX(setx1);
int randomNum = rand.nextInt((height - min) + 1) + min;
sety1 = randomNum;
position.updateY(sety1);
while (setx1 > -50) {
setx1 = setx1 - 1;
position.updateX(setx1);
}
setx1 = width;
position.updateX(setx1);
}
}
}
The Runnable Class:
public class SetMissilePosition implements Runnable{
int x1,y1, updateindicator;
ImageView missile1;
RelativeLayout layout;
TextView x,y;
SetMissilePosition(ImageView missile01, RelativeLayout relativeLayout, TextView xtext, TextView ytext) {
missile1 = missile01;
layout = relativeLayout;
x = xtext;
y = ytext;
}
public void updateX( int setx1) {
x1 = setx1;
updateindicator = 1;
}
public void updateY(int sety1) {
y1 = sety1;
updateindicator = 1;
}
public void run() {
missile1.setImageResource(R.drawable.missileanim);
layout.addView(missile1);
if(updateindicator == 1) {
missile1.setX(x1);
missile1.setY(y1);
x.setText(Integer.toString(x1));
y.setText(Integer.toString(y1));
updateindicator = 0;
}
}
}
If I am being unclear in any way or you need more code such as my MainActivity, please ask. Thanks in advance!
It sounds like you're trying to update the UI thread from off of the UI thread.
If that's the route you want to go, I'd encourage you to take a look at the 'run on ui thread' operation. Essentially, when you want to update layout positions, you can just call getContext().runOnUiThread([runnable]) and that will update your position. See here for more information: https://developer.android.com/training/multiple-threads/communicate-ui.html Some things to bear in mind:
Android runs at 60fps, so you need to make sure you're updating every 16ms or so in order to match in sync with your framerate. Otherwise your speed will be off.
Instead of doing that, why not use a Translate animation: https://developer.android.com/reference/android/view/animation/TranslateAnimation.html
You can set starting and ending x and y coordinates, you can even use them as percentages of screenwidth and length, and set the animation to repeat infinitely. If repeating infinitely won't work because you want to pick new X (or Y) values each time, you can hook something up on the end of the animation to pick new values and restart.
I found the answer myself through lots of trial end error. What I did was Created an activity that extended surface view, added a bitmap to it, updated the images coordinates in a thread, and finally passed the coordinates into another thread which updated the screen 30 times a second.

Move camera without lag in libgdx

I just started a small project with libgdx and I noticed that the camera is lagging behind the mouse a bit. I am moving it like that: (I have cut out everything else)
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
screenXlast = screenX;
screenYlast = screenY;
if (button == Input.Buttons.RIGHT || pointer > 0) {
rightMouseKlicked = true;
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (button == Input.Buttons.RIGHT) {
rightMouseKlicked = false;
}
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
if (rightMouseKlicked) {
gamecam.translate((screenXlast - screenX) * gamecam.zoom, (screenY -
screenYlast) * gamecam.zoom);
}
screenXlast = screenX;
screenYlast = screenY;
return false;
}
The game runs at 60fps but it seems like the output is delayed by a few frames. (the mouse cursor does not stay at the same position on the map while moving it around)
Is there an other way of doing it, so that the camera stays up with the mouse?
As far as I know, events in libgdx go into a stack. It is possible to receive the event a few ms after it actually happened.
You can see that if you draw an actor or a texture of the position of the touch dragged event - if you drag fast you will see that the drawn texture is always behind your mouse (or finder on phones).
As #Jankapunkt said, you can try multiplying the position by the delta time (Gdx.graphics.getDeltaTime()) but I am not sure that it will help
You are calculating the screen pixels moved, but not scaling to the size of your camera's viewport. Modify it as shown:
public boolean touchDragged(int screenX, int screenY, int pointer) {
if (rightMouseKlicked) {
float scale = gamecam.zoom * gamecam.viewportWidth / (float)(Gdx.graphics.getWidth);
gamecam.translate((screenXlast - screenX) * scale , (screenY -
screenYlast) * scale );
}
screenXlast = screenX;
screenYlast = screenY;
return false;
}
Also keep in mind that a typical mouse's update rate is pretty low (about 10 FPS I think). If you find camera movement too jerky, you'll have to calculate mouse movement speed and extrapolate the mouse's position and add a smoothing algorithm on top of that. See here for discussion (3D but still generally applies).

Image's border in libgdx

Since I'm pretty new in Libgdx development, I would like to ask if it is possible to make image borders (to mark it up as selected) using it? I've read that one solution is to make 2 separate images: one with border and one without. However pretty all of my images are the same size and there are many of them so don't know if it's the best idea. Are there any other options?
EDIT
So i have chosen 2nd idea ( 1x1 image ) but there is some problem with it. First of all i can't make that borderImage to be under clicked element. Another problem is size of borderImage ( it's not same ). When i click in the center of button its smaller ( about couple pixels ) than when i click on the edge. Do u know what can cause these problems and how to fix them?
Code :
public void create(){
stage = new Stage();
Gdx.input.setInputProcessor(stage);
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
Texture borderTexture = new Texture(Gdx.files.internal("data/select.png") );
final Image borderImage = new Image( borderTexture );
TextButton exitButton = new TextButton("Exit",skin);
exitButton.addListener(new ClickListener(){
public void clicked(InputEvent event, float x, float y)
{
borderImage.setSize( event.getTarget().getWidth() + 1 * 2, event.getTarget().getHeight() + 1 * 2);
Vector2 loc = new Vector2(0, 0);
Vector2 stageLoc = event.getTarget().localToStageCoordinates(loc);
borderImage.setPosition( stageLoc.x, stageLoc.y);
System.out.println("" + event.getTarget().getWidth() + " " +event.getTarget().getHeight() + " " + event.getTarget().getX() +
" " + event.getTarget().getY() + " " + stageLoc.x + " " + stageLoc.y);
stage.addActor(borderImage);
}
}
);
Table table = new Table();
table.add(exitButton).colspan(3);
table.setFillParent(true);
stage.addActor(table);
}
And the output i have :
29.0 25.0 4.0 1.0 466.0 257.0 // clicked in the center of button
37.0 27.0 462.0 256.0 462.0 256.0 // clicked on the edge of button
If you are using Scene2D and its Image class the simpliest idea is to keep a small texture of color you want the border to has. The texture can be like 1px x 1px size. It should has Nearest filtering due to avoid blending borders effect.
When click on image you can create an Image of size of the image plus border width and place it where the image is achieving border effect. On touch up you need to remove the border-actor
Texture borderTexture = new Texture( Gdx.files.internal("border.png") );
Image borderImage = new Image( borderTexture );
...
//in the clickListener
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
borderImage.setSize( event.getTarget().getWidth() + BORDER_WIDTH * 2, event.getTarget().getHeight() + BORDER_WIDTH * 2);
borderImage.setPosition( event.getTarget().getX() - BORDER_WIDTH, event.getTarget.getY() - BORDER_WIDTH);
stage.addActor( borderImage );
event.getTarget().toFront(); //to move the original image over the border
return true;
}
public void touchUp(InputEvent event, float x, float y, int pointer, int button)
{
borderImage.remove();
}
If not using the Scene2D you can achieve same effect by rendering Sprite of size of the image + border width and manage a flag saying if render the border or not
Sprite image, border;
...
//in the input processor
public boolean touchDown (int x, int y, int pointer, int button)
{
border.setSize( image.getWidth() + BORDER_WIDTH * 2 , image.getHeight() + BORDER_WIDTH * 2 );
border.setPosition( image.getX() - BORDER_WIDTH, image.getY() - BORDER_WIDTH);
renderBorder = true;
return true;
}
public boolean touchUp (int x, int y, int pointer, int button)
{
renderBorder = false;
return false;
}
//in the render method
if(renderBorder)
{
border.draw(batch);
}
image.draw(batch);
here what i'll do if it was for me :
i will use one border image for all my images (instead of image border for each one of my images)
let assume that on the left is your image and on right is the border image
when a Click event occured on the image you draw the border on the image (your image border is transparent inside you can easly do it with editor like gimp) on top of the image and you will have something like this
if the size is different you can change it and fix the same size before drawing the image at same position
Hope this will help !

Java applet crashes when I try to crop a picture

I've been trying to chop up a larger picture and use it as tiles for a game. I had the program working using fillRect() to simulate the image. However, when I replace the fillRect code, it crashes. Here is what I've been using:
buffer.drawImage(section[i][j].getSectionImage(i, j),
sectionSize * i + OFFSETx,
sectionSize * j + OFFSETy,
this);
public class Section{
private static ImageIcon ii;
private static Image mainImage;
private Image sectionImage;
public Section(){
if (ii == null){
ii = new ImageIcon(this.getClass().getResource("images/Mossy_rocks.png"));
mainImage = ii.getImage();
}
}
public Image getSectionImage(int x, int y){
sectionImage = createImage(new FilteredImageSource(mainImage.getSource(),
new CropImageFilter(1,1,20,20))); //test values
return sectionImage;
}
}
I tried "extends JApplet/JFrame/JComponent" for the Section Class, but it didn't seem to help.
Edit: I would also like to mention that if I would just return mainImage from getSectionImage(), I get the image. I think the biggest problem is the rest of that function... but I'm not sure, so I included everything I needed to add when replacing fillRect().
I found a much better way to crop this image. Here is how I did it:
screenImage.drawImage(Image sprite,
int (x position on screen),
int (y position on screen),
int (x position on screen + width),
int (y position on screen + height),
int (x position from sprite),
int (y position from sprite),
int (x position from sprite + width),
int (y position from sprite + height),
null);

Why isn't my image scaling correctly?

I'm trying to have an image scale to a certain size depending on the horizontal size sent to an update function, but the following code doesnt seem to size the image correctly.
EDIT: The code:
public class GlassesView extends View {
private Paint paint;
private BitmapFactory.Options options;
private Bitmap bitmapOrg;
private Bitmap target;
private Bitmap bitmapRev;
private Bitmap resizedBitmap;
private int currY;
public int glassesX;
public int glassesY;
public float glassesSizeX;
public float glassesSizeY;
private boolean drawGlasses;
private boolean glassesMirrored;
public GlassesView(Context context) {
super(context);
paint = new Paint();
paint.setDither(false);
paint.setAntiAlias(false);
options = new BitmapFactory.Options();
options.inDither = false;
options.inScaled = false;
bitmapOrg = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),
R.drawable.micro_glasses, options), 32, 5, false);
bitmapRev = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),
R.drawable.glasses_reverse, options), 32, 5, false);
drawGlasses = false;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(target, 0, 0, paint);
boolean moving = currY < glassesY;
if (moving) {
currY++;
}
if (drawGlasses) {
int newWidth = resizedBitmap.getWidth();
int newHeight = resizedBitmap.getHeight();
Paint bluey = new Paint();
bluey.setColor(Color.argb(64, 0, 0, 255));
canvas.drawRect(new Rect(glassesX, currY, glassesX + newWidth,
currY + newHeight), bluey);
canvas.drawBitmap(resizedBitmap, glassesX, currY, paint);
}
if (moving) {
invalidate();
}
}
public void drawGlasses(int x1, int x2, int y, boolean mirror) {
drawGlasses = true;
glassesMirrored = mirror;
if (!mirror) {
glassesSizeX = (float) (x2 - x1) / (float) (25 - 16);
glassesSizeY = glassesSizeX;
glassesY = y - (int)(1*glassesSizeX);
glassesX = (int) (x1 - (glassesSizeX * 16));
} else {
glassesSizeX = (float) (x1 - x2) / (float) (25 - 16);
glassesSizeY = glassesSizeX;
glassesY = y - (int)(1*glassesSizeX);
glassesX = (int) (x1 - (glassesSizeX * 16));
}
currY = -1;
if (!glassesMirrored) {
resizedBitmap = Bitmap.createScaledBitmap(bitmapOrg,
(int) (bitmapOrg.getWidth() * glassesSizeX),
(int) (bitmapOrg.getHeight() * glassesSizeY), false);
} else {
resizedBitmap = Bitmap.createScaledBitmap(bitmapRev,
(int) (bitmapRev.getWidth() * glassesSizeX),
(int) (bitmapRev.getHeight() * glassesSizeY), false);
}
}
public void setTargetPic(Bitmap targetPic) {
target = targetPic;
}
}
The result. (The blue rectangle being the bounding box of the image's intended size)
Which part am I going wrong at?
EDIT 2:
Here are the glasses:
EDIT 3:
Out of curiousity, I ran it on my actual phone, and got a much different result, the image was stretched passed the intended blue box.
EDIT 4:
I tried running the app on a few emulators to see if it was an Android version incompatibility thing, but they all seemed to work perfectly. The scaling issue only occurs on my phone (Vibrant, rooted, CM7) and my cousin's (Droid, also rooted). These are the only physical devices I have tested on, but they both seem to have the same issue.
I'd really appreciate if someone could help me out here, this is a huge roadblock in my project and no other forums or message groups are responding.
EDIT 5:
I should mention that in update 4, the code changed a bit, which fixed the problem in the emulators as I stated, but doesn't work on physical devices. Changes are updated in the code above. *desperate for help* :P
EDIT 6:
Yet another update, I tested the same code on my old G1, and it works perfectly as expected. I have absolutely no clue now.
have you been using the /res/drawable-nodpi/ directory to store your images?
Apparently if you use the /drawable-ldpi/, /drawable-mdpi/ or /drawable-hdpi/ folders, Android will apply scaling to the image when you load it depending on the device. The reason your G1 may work is that it may not require any scaling depending on the folder you used.
Also, your IMGUR links are broken... also your code doesn't seem correct... you call DrawGlasses with no arguments.
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, glassesWidth,
glassesHeight, matrix, false);
Change the last parameter from false to true.
you can have a try.
The follow is i used zoom in method by scale:
private void small() {
int bmpWidth=bmp.getWidth();
int bmpHeight=bmp.getHeight();
Log.i(TAG, "bmpWidth = " + bmpWidth + ", bmpHeight = " + bmpHeight);
/* 设置图片缩小的比例 */
double scale=0.8;
/* 计算出这次要缩小的比例 */
scaleWidth=(float) (scaleWidth*scale);
scaleHeight=(float) (scaleHeight*scale);
/* 产生reSize后的Bitmap对象 */
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizeBmp = Bitmap.createBitmap(bmp,0,0,bmpWidth,
bmpHeight,matrix,true);
Found what was wrong. The image has to be in a folder called "drawable-nodpi", otherwise it will be scaled depending on DPI.

Categories

Resources