I want to move some sprites from left to right with a constant slow speed. I have first tried RatioResolutionPolicy but I saw sprites were flickering a lot. Then I have changed resolutionpolicy to FixedResolutionPolicy, defined sprite textures as bitmap, scaled them and made sprites by these textures (for more detail: click here). This is better than first method but not completely good. I use setx() for moving sprites. When I change x positon for example by 2 pixels for each frame there is no problem. But for different devices that have different resolutions I must multiply 2 by a ratio. In this case sprites are flickering again, not much but it is annoying for me.
code for camera is below
#Override
public EngineOptions onCreateEngineOptions() {
WindowManager w = getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
Point size = new Point();
w.getDefaultDisplay().getSize(size);
V.CAMERA_WIDTH = size.x;
V.CAMERA_HEIGHT = size.y;
} else {
Display d = w.getDefaultDisplay();
V.CAMERA_WIDTH = d.getWidth();
V.CAMERA_HEIGHT = d.getHeight();
}
if (V.CAMERA_HEIGHT/V.CAMERA_WIDTH>480f/860f){
V.CAMERA_HEIGHT=V.CAMERA_WIDTH*480f/860f;
}
else {
V.CAMERA_WIDTH=V.CAMERA_HEIGHT*860f/480f;
}
V.ratio=V.CAMERA_HEIGHT/480f;
this.mCamera = new Camera(0, 0, V.CAMERA_WIDTH, V.CAMERA_HEIGHT);
final EngineOptions engineOptions = new EngineOptions(true,
ScreenOrientation.LANDSCAPE_FIXED, new FixedResolutionPolicy((int)V.CAMERA_WIDTH, (int)V.CAMERA_HEIGHT),
this.mCamera);
return engineOptions;
}
for moving sprites:
this.wallPosX -= this.speed;
this.setX(Math.round(this.wallPosX));
speed is a floating point varibale and it gets 4.4651165 for 1280x720 screen resolution. If I set it as an integer than there is no flickering, but this time sprite speed differs from device to device.
There are too many screen sizes and screen ratio's for android phones.
Use the Cropped Resolution Policy created by jgibbs. Follow Martin Varga's tutorial to get an understanding on how it works and how to implement it.
It works wonders.
Original from jgibbs
I recommend Martin's Tutorial
You shouldn't be worried about micro managing entities positional co-ordinates to suit every and any possible screen size.
I'm not sure this will fix the flickering though, that may be some other problem not related to your camera
I have noticed that this wasn't about Andengine, it was about opengl. Solution for this problem is this wonderful tool:
https://github.com/gemserk/imageprocessing
Related
Good night friends.
I'm having trouble drawing a fixed point on the screen when the screen is rotated. I used the method "rotateAround" from the position of the player.
It seems to me. I have to rotate this fixed point also from the position of the player. I use this stretch learned here in stackoverflow.
public void rotate(Vector3 position, Vector3 centerPoint){
this.cosTemp = MathUtils.cosDeg(this.anguloAtual);
this.senTemp = MathUtils.sinDeg(this.anguloAtual);
this.xTemp = centerPoint.x + ((position.x - centerPoint.x) * this.cosTemp) - ((position.y - centerPoint.y) * this.senTemp);
this.yTemp = centerPoint.y + ((position.y - centerPoint.y) * this.cosTemp) + ((position.x - centerPoint.x) * this.senTemp);
position.set(this.xTemp, this.yTemp, 0);
}
In the drawing that the player on the screen. I used the position of the player, then called "camera.project" then the method "rotate". The fixed point appears, however it is not exactly fixed.
I used the example of a fixed point slightly ahead of the player.
public void meDesenhar(SpriteBatch spriteBatch) {
spriteBatch.begin();
this.spritePlayer.setPosition(this.positionPlayer.x - (this.spritePlayer.getWidth() / 2),
this.positionPlayer.y - this.spritePlayer.getHeight() / 2);
this.spritePlayer.draw(spriteBatch);
spriteBatch.end();
originPosition.set(positionPlayer, 0);
fixedPosition.set(positionPlayer.x, positionPlayer.y + 10, 0);
cameraTemp.project(fixedPosition);
cameraTemp.project(originPosition);
cameraManagerTemp.rotate(fixedPosition, originPosition);
Debugagem.drawPointInScreen(Color.BLUE, fixedPosition);
}
My questions:
1 - I am doing something wrong, or just it is a result of rounding? I realized when debugging. The position of the player changed a little every rotation after the "camera.project". Example position (540, 320) turned (539.99, 320.013)
2 - I tried using and enjoying the SpriteBatch the draw method to perform the rotation however, could not make the rotation from the player. I would arrive at the same result.
3 - Can I use two cameras? Each camera would be a layer. A camera at the map and the player would be. The other for fixed point. It's viable? I could not find any example that works with more than one camera at the same time. Anyone know any examples please. I'm not talking about huds or cameras to stage.
Video follows.
https://www.youtube.com/watch?v=1Vg8haN5ULE
Thank you.
It can be result of rounding because its moving a pixel.
You can calculate rotation from the player but its not necessary.
Of course you can use multiple cameras in your game and you should also in this case.
Its few screenshot from my old projects that i used multiple cameras
As you can see you can even use different type of cameras like ortho and perspective both 2D and 3D.
Just create new camera like first one and change projection matrix
camrotate = new OrthographicCamera(540, 960);
//...
camfixed = new OrthographicCamera(540, 960);
//...
And in render method
batch.setProjectionMatrix(camrotate.combined);
batch.begin();
//draw in camrotate now
//...
//...
batch.end();
batch.setProjectionMatrix(camfixed.combined);
batch.begin();
//draw fixed elements now
//...
//...
batch.end();
//add one more camera if you need
Edit:
Change projection matrix outside of batch.begin()/end() otherwise the current batch will flushed.
I've searched all around google and this website for infos about this problem, but cannot solve it..
I'm a newbie in game development and LibGDX, and cannot find a solution well explained on how to port my game to all the various screen sizes..
Would you kindly help me?
Thanx
When using the newest libgdx version, you will find the Viewport class...
The viewport describes the transformation of the coordinate system of the screen (being the pixels from 0,0 in the lower left corner to e.g. 1280,768 in the upper right corner (depending on the device)) to the coordinate system of your game and scene.
The Viewport class has different possibilities on how to do that transformation. It can either stretch your scene coordinate system to exactly fit the screen coordinate system, which might change the aspect ratio and for example "stretch" your images or buttons.
It's also possible to fit the scene viewport with its aspect ratio into the viewport, which might produce a black border. E.g. when you have developed the game for 4:3 screens and now embed it into 16:10 displays.
The (in my opinion) best option is through fitting the scene viewport into the screen by matching either the longest or shortest edge.
This way, you can have a screen/window coordinate system from (0,0) to (1280,768) and create your game coordinate system maybe from (0,0) to (16,10) in landscape mode. When matching the longest edge, this means that the lower left corner of the screen will be (0,0), the lower right will be (16,0)... On devices that don't have the same aspect ratio, the y-values on the upper corners might differ a bit.
Or when matching the shortest edge, this means your scene coordinates will always be shown from (x,0) to (x,10) ... But the right edge might not exactly have and x value of 16, since device resolutions differ...
When using that method, you might have to reposition some buttons or UI elements, when they are supposed to be rendered on the top or the right edges...
Hope it helps...
Once me too suffered from this problem but at end i got the working solution, for drawing anything using SpriteBatch or Stage in libgdx. Using OrthographicCamera we can do this.
first choose one constant resolution which is best for game. Here i have taken 1280*720 (landscape).
class ScreenTest implements Screen {
final float appWidth = 1280, screenWidth = Gdx.graphics.getWidth();
final float appHeight = 720, screenHeight = Gdx.graphics.getHeight();
OrthographicCamera camera;
SpriteBatch batch;
Stage stage;
Texture img1;
Image img2;
public ScreenTest() {
camera = new OrthographicCamera();
camera.setToOrtho(false, appWidth, appHeight);
batch = new SpriteBatch();
batch.setProjectionMatrix(camera.combined);
img1 = new Texture("your_image1.png");
img2 = new Image(new Texture("your_image2.png"));
img2.setPosition(0, 0); // drawing from (0,0)
stage = new Stage(new StretchViewport(appWidth, appHeight, camera));
stage.addActor(img2);
}
#Override
public void render(float delta) {
batch.begin();
batch.draw(img, 0, 0);
batch.end();
stage.act();
stage.act(delta);
stage.draw();
// Also You can get touch input according to your Screen.
if (Gdx.input.isTouched()) {
System.out.println(" X " + Gdx.input.getX() * (appWidth / screenWidth));
System.out.println(" Y " + Gdx.input.getY() * (appHeight / screenHeight));
}
}
// ...
}
run this code in any type of resolution it will going to adjust in that resolution without any disturbance.
OK so I'm really confused I've rotated sprites before and had no problem such as rotating a boat as it moves through an ocean, but for some reason I'm having a really big problem this time. So I create a texture in an assets file, but not static textures. I load the texture using the following:
class Assets{
Texture img;
public Assets(){
img = new Texture(Gdx.files.internal("images/PNG.png")
And then I call the assets in the main class by calling:
Assets assets = new Assets()
And then I have a class that is an animator just for this main character because his animation is so different and varied from other characters.
class Animations{
Guy MYGUY;
Texture firstTexture;
ArrayList<Texture> running;
Sprite CurrentSprite;
public Animations(Texture standingStill, Guy myGuy){
MYGUY = myGuy;
firstTexture = standingStill;
running = new ArrayList<Texture>();
running.add(firstTexture);
CurrentSprite = new Sprite(firstTexture);
public void update (int direction, int state){
CurrentSprite.setPosition(MYGUY.X, MYGUY.Y)
// I have a switch here, but it does nothing yet because I haven't added in different actions for the character.
//However I do have a switch for direction, because that is important right now
switch(state){
case Guy.LEFT:
CurrentSprite.set rotation(180);
//yes there are more, but even rotating 180 won't work correctly
}
Then I have a renderer class to draw everything, i have the object MyGuy in an object for the world called myLand and I draw it with:
myLand.GUY.animation.CurrentSprite(batch);
So my problem arises on the rotation, whenever it rotates 180 degrees it seems to always rotate around the coordinates (0, 0) instead of the center of the sprite. So it usually ends up where I move like five to the right, but then if I try to go left it does double the distance backwards, but the camera position stays the same, and the guy usually disappears off the left or right side of the screen.
Try use rotate(...)method instead of setRotation(...).
With setOrigin(widthSprite\2, heightSprite\2)
That action rotate sprite itself.
Try
sprite.setOriginCenter();
This should help
Instead of rotating the sprite, just flip it with this single line:
CurrentSprite.flip(true, false);
the first boolean is X flip (that's what you want to set as true when going left) and the second is the Y flip.
Few days ago I figured out how to do some scrolling in LibGdx. Now I'm triying to do something related. I want to repeat the background. My scrolling follows a ship (Is an s[ace ship game). In the background there is a space photo loaded as a Texture. When the ship reach the end of the backgorund, It keeps going and there's no background anymore. I have read about wrap but I don't really understand How It works. I did that:
px=new Pixmap(Gdx.files.internal("fondo.jpg"));
background=new Texture(px);
background.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
And then, in my render method
spriteBatch.begin();
spriteBatch.draw(background,0,0,500,50);
drawShip();
spriteBatch.end();
Of course It doesn't work, It only draws the background once. I don't know how make this wrap method work. Any help?
SOLUTION
I figured It out. It's not a nice code but It works.
First I declare two Textures with the same image
bck1=new Texture(Gdx.files.internal("fondo.jpg"));
bck2=new Texture(Gdx.files.internal("fondo.jpg"));
Also I declare two variables like this to specify the X value of the position of each bck
int posXBck1=0,posXBck2=0;
Then I use that in Render()
public void calculoPosicionFondos(){
posXBck2=posXBck1+ANCHODEFONDO;
if(cam.position.x>=posXBck2+cam.viewportWidth/2){
posXBck1=posXBck2;
}
}
Where:
ANCHODEFONDO is the width of my background
Cam is an OtrhoCam.
So I said that if the cam is in bck2 (wich means that you can't see bck1 anymore) It change positions, giving bck1 de position of bck2 and, in the next render loop, recalculating bck2
Then just paint both bck in your render mode.
Like Teitus said, do not load your texture multiple times, ever! Anyway, you where on the right track with the wrapper:
texture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
Now you can just use the draw method with the source location. The source location is the area you choose to draw on the texture.
batch.draw(texture, x, y, srcX, srcY, srcWidth, srcHeight)
To scroll your texture from right to left all you have to do is increase srcX incrementally. So create a int that increments in the update/render method.
int sourceX = 0;
//render() method
//Increment the variable where to draw from on the image.
sourceX += 10;
//Simply draw it using that variable in the srcX.
batch.draw(YourTexture, 0, 0, sourceX, 0, screenWidth, screenHeight);
Because you are wrapping the texture it will wrap/loop and scroll indefinitely. There might be a issue with the sourceX int if the game runs for a very long time because a int can only hold 2147483647. It takes a while but you can fix it by subtracting the image width each time the number goes over the total image width.
Don't to this, please:
bck1=new Texture(Gdx.files.internal("fondo.jpg"));
bck2=new Texture(Gdx.files.internal("fondo.jpg"));
That will load your big background texture twice. That's a complete waste. If you want to keep your solution at least do:
bck1=new Texture(Gdx.files.internal("fondo.jpg"));
bck2=bkg1;
Regarding the texture Wrapping. If your texture is 500px wide, and you draw a 500px sprite, you won't see any repetition. If you want it repeated 2 times, draw it 1000px wide with 0-2 texture coordinates.
I'm not sure how spriteBatch handles the call you posted, you could try that one, or may be use the overload that uses a texture region and set your region manually.
I see this is a pretty old question, but I think there is an easier way to accomplish background scrolling. Just use the Sprite class. Here is a snippet I use for layered background images that scroll from right to left.
public class LevelLayer
{
public float speedScalar = 1;
private List<Sprite> backgroundSprites = new ArrayList<Sprite>();
public LevelLayer()
{
}
public void addSpriteLayer(Texture texture, float startingPointX, float y, int repeats)
{
for (int k = 0; k < repeats; k++)
{
Sprite s = new Sprite(texture);
s.setX(startingPointX + (k*texture.getWidth()));
s.setY(y);
backgroundSprites.add(s);
}
}
public void render(SpriteBatch spriteBatch, float speed)
{
for (Sprite s : backgroundSprites)
{
float delta = s.getX() - (speed * speedScalar);
s.setX(delta);
s.draw(spriteBatch);
}
}
}
Then you can use the same texture or series of textures like so:
someLayer.addSpriteLayer(sideWalkTexture1, 0, 0, 15);
someLayer.addSpriteLayer(sideWalkTexture2, 15 * sideWalkTexture1.getWidth(), 0, 7);
I change background repeating sections randomly in code and make new ones or reset existing sets when they go off screen. All the layers go to a pool and get pulled randomly when a new one is needed.
SOLUTION
I figured It out. It's not a nice code but It works.
First I declare two Textures with the same image
bck1=new Texture(Gdx.files.internal("fondo.jpg"));
bck2=new Texture(Gdx.files.internal("fondo.jpg"));
Also I declare two variables like this to specify the X value of the position of each bck
int posXBck1=0,posXBck2=0;
Then I use that in Render()
public void calculoPosicionFondos(){
posXBck2=posXBck1+ANCHODEFONDO;
if(cam.position.x>=posXBck2+cam.viewportWidth/2){
posXBck1=posXBck2;
}
}
Where:
ANCHODEFONDO is the width of my background
Cam is an OtrhoCam.
So I said that if the cam is in bck2 (wich means that you can't see bck1 anymore) It change positions, giving bck1 de position of bck2 and, in the next render loop, recalculating bck2
Then just draw both bck in your render()
I am writing a game for Android using AndEngine GLES 2. Everything was working properly - I had a background image, there were sprites moving around and even some music - until recently I tried something new (I wanted to be able to switch between two different scenes) when the display turned black.
I could still execute the game and there were no error shown. All log entries I made during the game were shown, even the music was playing so I knew the game was running "properly", but I couldn't see any image. Nothing. All black.
So I thought, changing everything back to before this "error" appeared, would do the trick. But still the screen is black.
I even tried commenting everything out but the background image - nothing.
Now if it is not too much to ask, could anyone please look over this short piece of code and tell me what is wrong there?
This are the variables I use:
private SmoothCamera camera;
private BitmapTextureAtlas bitmapTextureAtlas;
private Scene scene;
private Sprite background;
The EngineOptions I never changed, so they should be alright.
#Override
public EngineOptions onCreateEngineOptions() {
float positionX = 80f; // horizontal (x) position of the camera
float positionY = 280f; // vertical (y) position of the camera
float velocityX = 200f; // velocity of the horizontal camera movement
float velocityY = 200f; // velocity of the vertical camera movement
float zoomFactor = 1f; // the camera's zoom Factor (standard := 1)
this.camera = new SmoothCamera(positionX, positionY, this.getWindowManager().getDefaultDisplay().getWidth(), this.getWindowManager().getDefaultDisplay().getHeight(), velocityX, velocityY, zoomFactor);
EngineOptions options = new EngineOptions(true, ScreenOrientation.LANDSCAPE_SENSOR, new RatioResolutionPolicy(this.camera.getWidth(), this.camera.getHeight()), this.camera);
return options;
}
Here I create the TextureAtlas and load a background image.
#Override
protected void onCreateResources() {
// create the TextureAtlas
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
this.bitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 1024, 1600, TextureOptions.NEAREST);
// background
this.background = new Sprite(0, 0, BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.bitmapTextureAtlas, this, "background.png", 0, 0, 1, 1), this.getVertexBufferObjectManager());
this.mEngine.getTextureManager().loadTexture(this.bitmapTextureAtlas);
}
And finally the Scene is instantiated and the background gets attached.
#Override
protected Scene onCreateScene() {
this.scene = new Scene();
this.scene.attachChild(this.background);
return this.scene;
}
Now why would this small Activity not show? I forgot: its a SimpleBaseGameActivity.
Well, since AndEngine GLES2 is not running on the emulator, I have to use my phone (Samsung Galaxy GIO) and can't test the app on another machine.
Did anyone stumble upon a similar problem?
Any help is really much appreciated and thank you for your time !
Christoph
I think the problem is here:
this.bitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 1024, 1600, TextureOptions.NEAREST);
The dimensions of the Atlas are supposed to be powers of 2.