How to render alternating sprites to achieve infinite background in Libgdx? - android

I am trying to write a program in Libgdx that has a scrolling background.
The way am trying to scroll the background is as follows:
//creating two sprites whose size is the 2*viewportwidth
//this shows half of the sprite on my phone screen
//which I assume that it takes two viewport widths to show the entire sprite
sprite1;
sprite2;
//setting the positions which shows the sprites next to each other
sprite1.setPosition(0f,0f);
sprite2.setPosition(2f*viewportwidth,0);
//on to my render method, I have the following besides the usual:
#Override
public void render(){
//usual stuff here
camera.update
camera.setProjectionMatrix(camera.combined);
batch.begin();
sprite1.draw(batch);
sprite2.draw(batch);
batch.end();
moveCammy();
}
private void moveCammy(){
if(System.currentTimeMillis()-time>1000){
moviX=moviX+0.1*camera.viewportWidth;//moviX is a float
camera.translate(moviX,0f);
time= System.currentTimeMillis();
if(System.currentTimeMillis()-time2>22000){
sprite1.setX(4f*camera.viewportWidth)//since each phone screen width
//represents half of each sprite. It takes two phone screens to show
//one sprite. Since, originally there were two sprites it takes 4 phone
//screens to show them side by side.However, third sprite doesn't appear
//right after the second sprite. I think it should since it's 4 phone
// screens away. I assume the translation of the camera is around the second
//sprite after about 220000 milliseconds.
time2= System.currentTimeMillis();}
}
Everything works in the program, except that the third sprite doesn't appear
at all. My goal is to keep alternating sprite1 and sprite2 infinitely to achieve
an infinite background.
Please advise as to what might be wrong.

Related

After Android OpenGL ES 2.0 animation GLES20.glReadPixels reads the wrong value

I have this one square and when I click on it it stretches so it takes all the screen like shown in these pictures
Before stretching my color picker shows the values real nice
After the stretching when I click just a little below robots legs it gives me value (0,0,255) which is my background color, not the white color I clicked on (255,255,255).
I draw this animation very fast (100 ms) using GLSurfaceView's setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY). The whole animation consists of only 6 frames.
The drawing itself happens from
...
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
do_stretching();
}
}, 0, stretching_frame_delay, TimeUnit.MILLISECONDS);
...
void do_stretching()
{
//change coordinates of white squares vertices kind of "stretching" it
surface_view.requestRenderer();
}
Animation is looking really good and fills all of GLSurfaceView's area but color picker kind of acts like the last frame wouldn't be drawn and reads the background color which indeed was there before the animation completed. I noticed that if I draw this animation slower thus using more frames I can click a little closer to edges of this image and get the right results but still very close to edges there is this bug that GLES20.glReadPixels reads the background color even though its actually not visible after the animation completes. What might be the problem here?

How do I move an image relatively on Android?

I'm creating an app that works like a level for speeds.
If you go fast, my image will go up, and if you go slow, it will go down (Not to the top, the faster the upper and the slower the lower).
Currently, on every onLocationChange I calculate the recommended speed and get the actual value. Then I put move the image like that:
imageView.setY((float) speedvalue);
I have two problems:
setY is in pixels, so it doesn't fit to every screen.
Image moves instantly, I would like it to move like an animation.
How can I solve them?
You can animate the movement of a View like this:
TranslateAnimation animation = new TranslateAnimation(startXCoordinate, finishXCoordinate, startYCoordinate, finishYCoordinate);
animation.setDuration(1000);
view.startAnimation(animation);
Secondly, convert pixels to dps using this code and it will move the same amount on different screens:
int distanceToMove = (int) TypedValue.applyDimension(1, howManyDPsToMove, context.getResources().getDisplayMetrics());

Locking Text in Android Studio using Libgdx

I made a flappy bird clone and the pipes are going forward to the bird, but the text comes with the pipes. I want to lock the text in the middle of the screen.
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(bg, cam.position.x - (cam.viewportWidth / 2), 0);
sb.draw(bird.getTexture(), bird.getPosition().x, bird.getPosition().y);
for (Tube tube : tubes) {
sb.draw(tube.getTopTube(), tube.getPosTopTube().x, tube.getPosTopTube().y);
sb.draw(tube.getBottomTube(), tube.getPosBotTube().x, tube.getPosBotTube().y);
}
sb.draw(ground, groundPos1.x, groundPos1.y);
sb.draw(ground, groundPos2.x, groundPos2.y);
sb.end();
}
I usually use a Scene2D Stage with a static Viewport to display a hud or gui as a overlay on top of the actual game.
In most cases a HUD or GUI should be fixed to the actual screen and should not move therefor to have a movable camera in your game world you have to separate these elements entirely. What is happening in your case is that your current camera is drawing all elements and when it moves position the elements of your GUI will be drawn at a different position on your screen, like your "pipes" do.
If you are just drawing your text using the same batch an easy fix would be to just setup a new camera for this and when you are done drawing your game just input it's combined matrix to the projection matrix of the SpriteBatch, after you end it.
spriteBatch.setProjectionMatrix(movingCam.combined);
spriteBatch.begin();
//... draw stuff that belongs to your game world
spriteBatch.end();
spriteBatch.setProjectionMatrix(staticCam.combined);
spriteBatch.begin();
//... draw stuff that belongs to your GUI
spriteBatch.end();
Anyway, I would still recommend using Scene2D for the purpose of a GUI since it has everything you would need like buttons, tables, labels, etc.
Are you moving the camera to follow the bird? Just use an extra camera for your UI and/or static texts like score counters. And draw them after drawing game objects (on top of them).
See this question and submitted answer.

How to keep the same speed of object when number of object increase?

Im doing a game and I'm using SurfaceView. In the game I have 25 small dots that are moving around. The goal is to make a game where the player draw a circle around some of the dots with the same color. My problem is that while I draw this circle and after I have lift my finger from the screen, all the dots are moving very, very slow! I guess the reason for this is all the line segmets that are being drawn constantly together with all the dots.
Is it possible to have the same moving speed of the dots all the time? I tested with SystemClock.Sleep(1) but it didn't helped much.
// Method to draw objects
private void drawObjects(Canvas canvas) {
SystemClock.sleep(1);
synchronized (this) {
// Clear screen with black color
canvas.drawRGB(0, 0, 0);
// Draw line
if(startDrawLine) {
// Set properties to Paint object
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
// Draw path
path.moveTo(touchDownX, touchDownY);
for(Point point: points) {
path.lineTo(point.x, point.y);
canvas.drawPath(path, paint);
}
path.reset();
}
}
// Call method draw() in CircleManager to draw all circles in list
circleManager.drawCirclesInList(canvas);
}
Slow drawing is caused by to many points in your path.
If you are handling Touch event, you can expect hundreds and thousands of touches (your points) in short period of time.
You need to interpolate your points somehow - take averages, ignore same and close points or something else.
When you animate the "dots" your ANIMATION MUST BE BASED ON TIME, and not on the actual speed of the drawing on hardware.
To base your animation on time, you should calculate time passed since previous frame and use this time in function which calculates new position of the dot.
Here is a great article on the subject:
http://www.koonsolo.com/news/dewitters-gameloop/
EDIT - Response to a comment:
Suppose that your "dot" (I will call it a ball) needs to move horizontally (by X) from left to right at a constant speed of 100 units per second.
If you are doing your calculation WITH ASSUMPTION that your game will be running at 25 FPS, you simply add 4 to X on each frame.
The problem with this approach is that getting constant FPS is very hard to achieve.
On the fast hardware you will be sacrificing smoothness by limiting FPS,
on slow hardware you will be forced to skip drawing (drop) some frames (which can be jumpy with constant FPS).
Timer in Android is not very precise and also thread sleep functions are inaccurate.
In your case, instead of trying to force the constant FPS or calculate current FPS, try to wrap your head around and rethink of your problem
in a context of time.
When you think about time, it does not matter how fast is the game
running (how many FPS) and what happened before.
You just need to ask a question "Where the ball should be in this
moment, right now?"
If you, for example, know that ball movement stared at origin position X0 at origin time T0 then at the current moment TC ball position should be X = (TC - T0) * 100
Second approach is to measure time passed TD since last ball position update. Then the ball position should be updated like this: X = X + TD * 100
Once you get used to this approach, you will see that vast majority of animations is really trivial to implement with a great level of accuracy.

Collision Detection working half the time

I am trying to check collisions between two arrays, one of moving rectangles and the other of stationery boundaries (trying to get the rectangles to bounce off the walls).
The problem is that I wrote a nested for loop that seems to work for 2 out of 4 boundaries. Is my loop not reaching all possible combinations?
Here is my loop:
for(int n=0;n<_f;n++){
for(int m=0;m<_b;m++){
if(farr[n].inter(barr[m]))
farr[n].setD();
}
}
_f counts the moving rectangles (starts at 0 and increases after each one is added) and _b counts the boundaries. The inter() is a method I am using to detect collisions and it has worked in all other parts of my program.
Any help would be greatly appreciated,
Thanks in advace!!!
public boolean inter(Rect rect){
if(Rect.intersects(rect, rec))
return true;
else
return false;
}
The setD() method:
public void setD(){
if(_d==0)
_d=2;
if(_d==1)
_d=3;
if(_d==2)
_d=0;
if(_d==3)
_d=1;
}
The move method where _d is used:
public void moveF(){
if(_d==0){_l+=_s;_r+=_s;}
if(_d==1){_t+=_s;_b+=_s;}
if(_d==2){_l-=_s;_r-=_s;}
if(_d==3){_t-=_s;_b-=_s;}
}
_l is left side, _t is top, _r is right, and _b is bottom, and _s is how many pixels it moves per iteration(set to 1 in all cases)
Assuming _f, _b, farr, and barr do not change during the execution of the loop, your loop checks all combinations exactly once. So how is it that you "check some collisions twice"? Does setD() do something sneaky? Do you mean that once a rectangle collides there is no need to check more boundaries? If so, that can be fixed with a simple break statement. Otherwise, there likely is a problem with your inter() method, independent as to whether or not it appears to work elsewhere. Can you post your inter implementation?
There is a possibility of another problem, that of assuming continuous properties in a discrete space. As my amazing ascii art (titled: ball and wall) skills demonstrate...
Frame 1:
o__|_
Frame 2:
_o_|_
Frame 3:
__o|_
Frame 4:
___|o
Notice that the ball passed through the wall! In no frame did the ball intersect the wall. This happens if your distance moved per frame can be roughly the same or larger than the characteristic size of your moving object. This is difficult to check for with a simple intersection check. You actually need to check the path that the ball occupied between frames.
If your rectangles and barriers are oriented without rotation, this is still a fairly easy check. Use the bounding rectangle of the moving rectangle between the two frames and intersect that with the barriers.
Other ideas:
You are double colliding, switching the direction twice.
Your rectangles are in two different coordinate spaces.
Some other thread is screwing with your rects.
But basically, your code looks good. How many rectangles do you have? Can you make them distinct colors? Then, in your loop, when you collide, call setD and output the color of the rectangle that collided, and where it was. Then, when you notice a problem, kill the code and look at the output. If you see two collisions in a row (causing the rect to switch directions twice), you'll have caught your bug. Outputting the coordinates might also help, on the off chance that you are in two different coordinate spaces.
If it's a threading issue, then it's time to brush up on critical sections.
Found your mistake:
public void setD(){
if(_d==0)
_d=2;
if(_d==1)
_d=3;
if(_d==2)
_d=0;
if(_d==3)
_d=1;
}
Each of these needs to be else if, otherwise you update 0 to become 2 and then 2 to become 0 in the same call.

Categories

Resources