I am working on my first side-scroller game and am trying to achieve a neverending background effect and it's nearly working as i would expect but there are little glitches.
I have 2 instances of the background (each fills the screen width), with one placed at the bottom left corner of the screen and one off the screen to the right. I am then moving my camera each frame to the right and when the first background instance is completely offscreen to the left i reset its X to the right of the camera so that it is now (relative to the camera) off the right of the screen. this is working a lot of the time, but every now and again it seems the method to reset its x position is getting called a few frames late and results in a gap in the background.
the update code i am using in the main game is -
private void update(float delta){
//update camera and world
camera.position.set(camera.position.x+scrollSpeed, camera.position.y, 0);
camera.update();
world.step(step, velocityIterations, positionIterations);
if(gameInProgress){
//backgrounds (array holds the 2 instances of the background)
for(int i=0; i< bgFillArray.size; i++){
bgFillArray.get(i).update();
}
}
stage.act(delta);
tweenManager.update(delta);
}
the update method in the BgFill class -
public void update(){
float currentXPos = getX();
float leftBoundary = camera.position.x-1200;
float rightOfScreen = camera.position.x+400;
if(active){
//check to see if the camera has gone past this instance. if so then move to right
if(currentXPos <= leftBoundary){
setX(rightOfScreen);
}
}
}
Firstly, is this the usual way (or even close) to do a continuous scrolling background?
if it is, what am I doing wrong?
Related
I'm creating a game like flappy bird where the bird flaps his wings only when the screen is touched, but I'm having a problem activating the animation when the screen is touched.
batch.draw(animation.getKeyFrame(myTimeState, false), x, y); //the myTimeState is 0 to render the 1st frame only.
Then when the screen is touched I do this:
//myTimeStep is just basically a controllable timeState for the animation only
if(Gdx.input.justTouched){
myTimeState = timeState;
}else if(Gdx.input.justTouched == false && animation.isAnimationFinished(timeState)){
myTimeState = 0;
}
I don't think the animation is able to play all the frames because myTimeStep become 0 immediately after finishing to touch the screen. Also I don't think this is the right way of doing it, if you guys have better ideas or solution please help. Thanks in advance.
There are probably several ways to achieve this. You'll need to increment your timeState, of course, and also it depends how long your animation is and if you want it to loop.
If you've created your animation to play only once, and then stop (until the screen is touched again), you could simply set your myTimeState to 0 when the screen is touched, and then increment it every frame. The animation will run through and then "stop" on its own when it reaches the end (as you said no loop). The next time someone touches the screen, your myTimeState is set back to 0 and the animation starts again.
Firstly, you have to ensure your animation's playmode is set to Animation.PlayMode.NORMAL. It's a default setting, but if you set it somewhere to LOOPED, nothing would work as expected.
Secondly, I wouldn't use Input.justTouched() in this case. Instead, a listener in your input processor would be a great fit. Here's an example with Stage. If you have no idea what input processor is, here's tutorial on event handling and class documentation.
stage.addListener(new ClickListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if(button == Input.Buttons.LEFT) {
timeState = 0;
}
return super.touchDown(event, x, y, pointer, button);
}
});
You can pick what's going to be displayed (animation's keyframe or sprite) based on result of animation.isAnimationFinished()
if(animation.isAnimationFinished(timeState)) {
//draw some sprite
} else {
//draw animation keyframe
}
I haven't checked it but there's a possibility, that this could lead to the last frame being cut out, because as soon as it gets displayed, animation.isAnimationFinished() will return true. I may be wrong, so you'll have to check it. If it becomes an issue, you can add your sprite as the last frame of your animation. When animation ends, it frezzes on the last frame, which would be your static sprite.
In both cases you'll get your animation played at the beginning of game because timeStep equal to 0. I see 2 solutions, I advise you to take the second:
Set timeStep to a large number, that is for sure larger than your animation's duration. Animation.isAnimationFinished() will then return true.
Introduce boolean variable isAnimationPlayed that:
is initialized with false,
gets set to true in your click listener,
gets set to false during isAnimationFinished(), which is called each frame only when isAnimationPlayed is true,
is used in draw() method to determine what to display.
You could just set your timeState to the duration of the animation.
I have a camera which I control using WASD, but I'm stuck on moving it left and right. I've been looking all over the internet and it says to find a vector perpendicular to another you change the x and y round and times one of them by -1. I've tried this in the code below:
void camstrafe (String dir) {
Vector3 direction = camera.direction.nor();
Vector3 old = direction;
direction.set(-old.z, 0, old.x);
camera.translate(direction.scl(0.18f));
}
I have moving forwards working fine, and actually turning the camera round, but for some reason this doesn't work, and to be honest I'm not sure what it really does because when I press a or d (they call this function) the camera just goes crazy and starts turning round really quickly and sometimes going forwards or like a million miles sideways. Anyway, does anyone know how I could do this properly? By the way I've also tried getting the forward direction of the camera and using the .rotate() function rotating it 90 degrees right/left then translating it that way but that does the same thing. I'm thinking maybe cameras don't work the same was as other things do when translating them sideways/backwards.
To archive camera movement between 2 vectors use the camera lerp:
public class myclass {
[...]
private OrthographicCamera camera;
public Vector3 posCameraDesired;
[...]
private void processCameraMovement(){
/// make some camera movement
posCameraDesired.x+=100.0f * Gdx.graphics.getDeltaTime();
posCameraDesired.y+=100.0f * Gdx.graphics.getDeltaTime();
}
[...]
//render method
public void draw(){
[...]
processCameraMovement();
camera.position.lerp(posCameraDesired,0.1f);//vector of the camera desired position and smoothness of the movement
[...]
}
First, in your class, you must have an Animations object, lets call it Anim. In your class instanciation, you must create an OrthographicCamera object, that will be your camera instance. You have to give it a value, such as :
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
This camera coordonates can be set up the first time you use it, and you can do it with the method .translate() :
camera.translate(camera.viewportWidth / 2, camera.viewportHeight);
Otherwise the positio will be set at 0;0.
In your render() method, you have to use a method from the camera object called update(), like bellow :
#Override
public void render(float delta) {
anim.load();
camera.update();
....
game();
....
}
This method is always running during the game/app you develop. So every time the method runs, the camera is updated, and its position too.
Then, in your game() method, or in an other method (depending on your architecture), where you are dealing with the inputs of the user, you move the position of the camera, and modify the camera.position in it. like bellow :
public void game() {
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) { // or A
moveBack(anim); // The method to move back
camera.position.x -= 3; // if conditions are ok, move the camera back.
} else if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { or D
moveForward(anim); // The method to move forward
camera.position.x += 3; // if conditions are ok, move the camera to the front.
}
When the user is moving, the method to move is called, and the camera position is modified. Each time the method render() is called, the camera is updated with its new position.
so I'm working on a game where I would like to have the camera in game centered on the middle of the screen for all device lengths. I hope this picture can better explain what I'm trying to achieve. I have tried setting the position of the camera but that hasn't worked for me.
scrnHeight = Gdx.graphics.getHeight();
if (scrnHeight <= HEIGHT) {
cam.setToOrtho(false, 480, 800);
} else {
cam.setToOrtho(false, 480, scrnHeight);
}
//This is the part that seems to be giving me all the issues
cam.position.set(cam.viewportWidth/2,cam.viewportHeight/2, 0);
cam.update();
Gdx.input.setInputProcessor(this);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
gsm.update(Gdx.graphics.getDeltaTime());
gsm.render(batch);
batch.begin();
batch.draw(border, -(border.getWidth() - WIDTH) / 2, -(border.getHeight() / 4));
batch.end();
I don't know if I'm giving it the wrong coordinates when I'm setting the position or what is happening that causes the lack of vertical centering. Any help would be much appreciated.
The orthographic camera position in LibGDX means position in-game, not on the device screen, therefore changing it won't actually move the game screen on the device.
Therefore, you use the camera position to move and position the camera in-game.
For example, in response to player input movement:
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
cam.translate(-3, 0, 0); // Moves the camera to the left.
}
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
cam.translate(3, 0, 0); // Moves the camera to the right.
}
As you can see, we are moving the camera in-game, left and right according to the player's input.
However, your code has a few more issues like not setting the batch projection matrix:
batch.setProjectionMatrix(cam.combined);
And resetting the camera position to the center of the viewport each frame:
// Don't run this each frame, it resets the camera position!
cam.position.set(cam.viewportWidth/2,cam.viewportHeight/2, 0);
cam.update(); // <- However, you must run this line each frame.
Finally, centering the LibGDX app on the device screen should be done outside of Libgdx, otherwise, if you intend to use the spare screen for the same LibGDX app, then you should create another camera to work full screen and render it before the actual game camera, usually used for HUD and such...
I am developing a 2d game; I am currently developing a system of movement of the camera on the map, I used the following method: my camera has own coordinates - x,y;
I have ArrayList with all my sprites for map with their coords from 0 to mapSize, every sprite has a Draw function, which looks simply like
g2d.drawImage(texture, getX(), getY(), getX() + getSizeX(), y + getSizeY(), 0, 0, getSizeX(), getSizeY(), null);
I'm always drawing all my sprites, without checking are they visible or not;
Whether there is a load on the computer at this drawing (when drawing textures that very far away from screen size)?
Do I need to check whether the object is visible before rendering?
My main DrawAll function contains():
public void DrawAll(graphics2D g2d){
g2d.translate(-playerCamera.getX(), -playerCamera.getY());
for (int i = 0; i < mapSprites.size(); i++) {
mapSprites.get(i).Draw(g2d);
}
g2d.translate(-playerCamera.getX(), -playerCamera.getY());
drawSomeStrings, etc....
}
This is not very good, because lines that were drawn after second translate may twitch when moving the screen.
Should I give translate up and do the offset coordinates manually in each object\sprite's Draw function?
graphics2D will clip your drawing. So it does not impact too much. If you have a lot of sprites, you should consider using a SpatialIndex to select which Sprite is in the screen. (https://github.com/aled/jsi)
I got this code that gets x,y positions from a motion sensor tracking a hand. The app draws a circle in the middle of the screen and then detects whether the hand is outside the circle. While the hand is outside the circle, a function checks the distance of the hand from the center of the circle. I'm attempting to store the distance data while the hand is outside of the circle in a linked list.
I need to get both the top 5 largest values and the duration for each time the hand is outside the circle.
Here's my code thus far; I've left out a bunch of the code for setting up the motion sensor just for simplicity, so this is semi-pseudo code. In any case, my main issue is getting the values I need from the list. I have the circle class included as well. I do the outside of the circle calculation and how far outside of calculation inside of my circle class.
Please let me know if this makes sense! The motion sensor is reading in data at 200 fps, so efficiency is factor here. On top of that, I am only expecting the hand, going back and forth, to be outside of the circle for a few seconds at a time.
import java.util.*;
LinkedList<Integer> values;
public void setup()
{
size(800, 300);
values = new LinkedList<Integer>();
HandPosition = new PVector(0, 0); //This is getting x,y values from motion sensor
aCircle = new Circle(); //my class just draws a circle to center of screen
aCircle.draw();
}
public void draw()
{
if (aCircle.isOut(HandPosition)) /* detects if movement is outside of circle. Would it make more sense for this to be a while loop? I also need to start a timer as soon as this happens but that shouldn't be hard */
{
values.add(aCircle.GetDistance(HandPosition)); //gets how far the hand is from center of circle and adds it to linked list. Allegedly at least, I think this will work.
/*So I need to get the 5 largest value from inside of my linked list here.
I also need to start a timer*/
}
}
class Circle {
PVector mCenter;
int mRadius;
Circle()
{
// initialize the center position vector
mCenter = new PVector(0,0);
mRadius = 150;
mCenter.set((width/2),(height/2));
}
boolean isOut(PVector Position) //detects if hand position is outside of circle
{
return mCenter.dist(Position) <= mRadius;
}
float GetDistance(PVector Position) //detects how far the hand is from the center of circle
{
return mCenter.dist(Position);
}
void draw() {
ellipse(mCenter.x, mCenter.y, mRadius, mRadius);
}
}
I'm new to Processing as well so don't hold back if any of this works.
You can use Collections.sort(List); here, then take last five element from the list.
Collection.Sort()