I wanna set My Scene Background but I don't know how! I had read a lot about this, but I can't make this works. Is my start with Andengine, and is hard found precise information for my problem, all is subjective.
Well, I have implemented the splash screen in a scene, and while load all resources and scenes. (https://sites.google.com/site/matimdevelopment/splash-screen---easy-way)
Then, I have to set a Background to my menuScene, I think that I need a TextureRegion and a BitmapTextureAtlas to create each backgroud. I do this:
Declared textures:
//Fondo escenas
private TextureRegion menuBgTexture;
private BitmapTextureAtlas menuBackgroundTexture;
Load Resources and Load scenes (They are called by onPopulateScene when Splash ends)
public void loadResources()
{
//FondoMenu
menuBackgroundTexture = new BitmapTextureAtlas(null, 480, 320, TextureOptions.DEFAULT);
menuBgTexture = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.menuBackgroundTexture, this, "menubg.png", 0, 0);
//Cargamos los fondos
mEngine.getTextureManager().loadTexture(this.menuBackgroundTexture);
}
private void loadScenes()
{
//MenĂº
menuScene = new Scene();
final float centerX = (CAMERA_WIDTH - menuBgTexture.getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT - menuBgTexture.getHeight()) / 2;
SpriteBackground bg = new SpriteBackground(new Sprite(centerX, centerY, menuBgTexture));
menuScene.setBackground(bg);
//menuScene.setBackground(new Background(50, 0, 0));
//Options
optionsScene = new Scene();
//Juego
gameScene = new Scene();
//Pausa
pauseScene = new Scene();
//Gameover
gameOverScene = new Scene();
}
load Resource not shows error, but loadScenes, Line:
SpriteBackground bg = new SpriteBackground(new Sprite(centerX, centerY, menuBgTexture));
Says me that I have to set a new attribute (ISpriteVertexBufferObject), well, what is this?
for the VBOManager object, use
this.getVertexBufferObjectManager();
I also had the same issue with my game. The solution is to have a background image that is of the same dimensions as the camera. For example, if your camera is 800X480, the image should be of the same dimensions as well. Also, make the dimensions of the BitmapTextureAtlas factors of two. In your case, it should be 512px by 512 px. Hope that helps.
Cheers!!
Related
I have a body with a polygonshape created using .setasbox but when I run my game the box is a bit bigger than my sprite.
I know setasbox uses half height and half width, I used my scaling constant to convert meters to pixels and I know the sprite has the origin of the axis on the bottom left as well. Despite of that I still have a box with a width a bit larger than the sprite and this gap is the same however I change the size of the box...
This is the code I use to create my box (160 is the constant to scale meters to pixels):
public Block(World w, float halfWidth, float halfHeight, Vector2 position, Texture tex){
world = w;
bodyd = new BodyDef();
bodyd.type = BodyDef.BodyType.KinematicBody;
bodyd.gravityScale = 0;
shape = new PolygonShape();
shape.setAsBox(halfWidth, halfHeight);
fixtured = new FixtureDef();
fixtured.shape = shape;
fixtured.density = DENS;
fixtured.friction = FRIC;
fixtured.restitution = REST;
bodyd.position.set(new Vector2(position.x, position.y));
body = world.createBody(bodyd);
fixture = body.createFixture(fixtured);
body.setUserData(this);
texture = tex;
sprite = new Sprite(texture);
sprite.setSize(halfWidth * 2 * 160, halfHeight*2*160);
sprite.setPosition((body.getPosition().x - halfWidth) * 160, (body.getPosition().y - halfHeight) * 160);
}
can you try using Box2DSprite? its very easy..
https://bitbucket.org/dermetfan/libgdx-utils/wiki/net.dermetfan.gdx.graphics.g2d.Box2DSprite
http://www.java-gaming.org/index.php?topic=29843.0
I don't see anything wrong with your code
did you consider that the size that you put for your sprite is the size of the full sprite not the size of the block inside your sprite
I think this is why your brick sprite is smaller than your brick physic :
unless the your brick has the full size of the sprite then may be the problem is related to something else
hope that was helpful !
I am having 3 different screens which contains splash screen, after menu screen and game screen. Splash > Menu > Gamestarts.
How can i add an image button ??
I want to implement 3 buttons inside Menu screen, Not getting any idea where to start.
public class MenuScreen implements Screen {
private Spacegame game;
private SpriteBatch batch;
private Sprite sprite;
private Texture texture;
TextureRegion bg,play,spacegamelogo,button;
OrthographicCamera camera;
Vector3 touchPoint;
private Skin buttonskin;
public MenuScreen(Spacegame game)
{
touchPoint = new Vector3();
this.game=game;
batch=new SpriteBatch();
bg=AssetLoader.bg;
spacedebrislogo=AssetLoader.spacedebrislogo;
button=AssetLoader.button;
}
#Override
public void show() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(1, h / w);
sprite = new Sprite(bg);
sprite.flip(false, true);
sprite.setSize(1.0f,
1.0f * sprite.getHeight() / sprite.getWidth() );
sprite.setOrigin(sprite.getWidth() / 2,
sprite.getHeight() / 2);
sprite.setPosition(-sprite.getWidth() / 2,
-sprite.getHeight() / 2);
}
#Override
public void render(float delta) {
batch.setProjectionMatrix(camera.combined);
batch.begin();
sprite.draw(batch);
batch.draw(spacedebrislogo, 33, 54, 50, 40);
batch.end();
if (Gdx.input.isTouched()) {
game.setScreen(new GameScreen());
dispose();
}
}
THere are a lot of methods to do it..
I will tell you the way I do.
First I create my button image, add it to the assets folder and load the texture region.
Now I make a sprite out of it.
Sprite button1=new Sprite(myTextureRegion);
To check if the button is touched I can use the rectangle from the sprite to check if you touched the image.
In your touchUp method you will do something like
if(button1.getBoundingRectangle.contains(screenX,screenY))
// do your thing
To make my game more interesting i like to add some rotation or scaling of my sprite when is clicked, so it looks better, you can play with it, or you can make 2 textures, one for touched down and one for touched up.
Using AndEngine for Android, I would like to have my scene look like this:
The red box is the world which must be limited to a given size, say 2000px*450px.
The blue box is the Camera, which is limited as well (as usual), for example to 750px*450px.
For the whole scene, I have a background image that is exactly 450px high. So my Camera can be scaled to whatever size is appropriate, but the background must exactly fit to the height. The width of the Camera may be variable.
The player (circle) must always be in the center (horizontally) but may not leave the world's boundaries.
To achieve this, I've tried adding two types of sizes:
camera size (CAMERA_WIDTH, CAMERA_HEIGHT)
world size (WORLD_WIDTH, WORLD_HEIGHT)
And this function was to add boundaries to the world so that the physics engine prevents the player from leaving those boundaries:
private void createWorldBoundaries() {
Body body;
final Rectangle wall_top = new Rectangle(0, WORLD_HEIGHT-5, WORLD_WIDTH, 10, mVertexManager);
final Rectangle wall_bottom = new Rectangle(0, 5, WORLD_WIDTH, 10, mVertexManager);
final Rectangle wall_left = new Rectangle(5, 0, 10, WORLD_HEIGHT, mVertexManager);
final Rectangle wall_right = new Rectangle(WORLD_WIDTH-5, 0, 10, WORLD_HEIGHT, mVertexManager);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_top, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_top.setUserData(body);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_bottom, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_bottom.setUserData(body);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_left, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_left.setUserData(body);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_right, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_right.setUserData(body);
attachChild(wall_top);
attachChild(wall_bottom);
attachChild(wall_left);
attachChild(wall_right);
}
But this is not working, unfortunately. (see edit)
Setting the camera to chase the player has the wrong result for me: The player does really stay in the center of the screen all time, but I want the player only to stay in the center horizontally, not vertically.
What am I doing wrong and what can I change? And the basic question is: How can I make the world wider than the camera view, while the height is equal to the camera view. The result should be that you can horizontally walk through your world (moving camera) and you can always see the full height.
Edit:
As you define the coordinates of the Rectangle's center and not its top-left corner, you have to do it like this, it seems:
final Rectangle wall_top = new Rectangle(WORLD_WIDTH/2, WORLD_HEIGHT-1, WORLD_WIDTH, 2, mVertexManager);
final Rectangle wall_bottom = new Rectangle(WORLD_WIDTH/2, FIELD_BASELINE_Y+1, WORLD_WIDTH, 2, mVertexManager);
final Rectangle wall_left = new Rectangle(1, WORLD_HEIGHT/2, 2, WORLD_HEIGHT, mVertexManager);
final Rectangle wall_right = new Rectangle(WORLD_WIDTH-1, WORLD_HEIGHT/2, 2, WORLD_HEIGHT, mVertexManager);
However, I had found the other solution in several tutorials. Are these authors not testing their code before writing the tutorials or did the behaviour change from GLES1 to GLES2 or with any recent version?
i think your question about the world boundaries is self answered, isn't it?
PhysicsWorld Boundaries
for further research you can download nicolas' AndEngine Examples App from the Play Store and look up the different examples here (GLES_2, didn't look for AnchorCenter yet): https://github.com/nicolasgramlich/AndEngineExamples/tree/GLES2/src/org/andengine/examples
Taken from the PhysicsExample, the code for the rectangles should look like this, if the bounds are set to the camera bounds. in your case, you can extend width like you want (3 times CAMERA_WIDTH?)
final Rectangle ground = new Rectangle(0, CAMERA_HEIGHT - 2, WORLD_WIDTH, 2, vertexBufferObjectManager);
final Rectangle roof = new Rectangle(0, 0, WORLD_WIDTH, 2, vertexBufferObjectManager);
final Rectangle left = new Rectangle(0, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
final Rectangle right = new Rectangle(WORLD_WIDTH - 2, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
Camera following player
for the Camera to follow your player, you can lookup the code of the BoundCameraExample https://github.com/nicolasgramlich/AndEngineExamples/blob/GLES2/src/org/andengine/examples/BoundCameraExample.java
the interesting part for you should be the addFace method at the bottom
private void addFace(final float pX, final float pY) {
final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);
final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager()).animate(100);
final Body body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, face, BodyType.DynamicBody, objectFixtureDef);
this.mScene.attachChild(face);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face, body, true, true));
this.mBoundChaseCamera.setChaseEntity(face);
}
this method creates a physics body + sprite for "your player" (in this case, a boxed face) and sets the sprite as a chaseEntity for the camera to follow. Since the camera has bounds, that it can't exceed and your camera will have the height of your PhysicWorld boundaries, you can use this to let your camera follow the player in x, but not in y direction.
if you (i don't know why) don't want to use these boundaries, you can overwrite the onUpdate method of your Sprite and re-locate your camera only in x-direction, instead of xy coords
face.registerUpdateHandler(new IUpdateHandler() {
#Override
public void onUpdate(final float pSecondsElapsed) {
float[] coord = face.getSceneCenterCoordinates();
this.mBoundChaseCamera.setCenter(sceneCenterCoordinates[0], CAMERA_Y_POSITION);
}
}
where the CAMERA_Y_POSITION is a static final field with the y-position.
I hope this answers your question(s). :-)
edit: oops, i forgot to mention, how to achieve the camera to be bound and i will edit the world width above:
this.mBoundChaseCamera.setBounds(0, 0,
WORLD_WIDTH, CAMERA_HEIGHT);
all settings are like your image given (except the exact position of the face, that has to be given to the addFace(px, py))
Edit: Difference between scene boundaries in Andengine GLES2 vs GLES2-AnchorCenter
As far as i understood the question, i thought you would use GLES2, i thought of the (older) default GLES2 branch of AndEngine and posted the boundaries. As you found out yourself before and stated in the comments, you use another approach to set the rectangles - where you need to set the rectangles center as pX and pY. The reason for this is in fact, that with the AnchorCenter branch, you won't set the upper left position of an entity anymore and instead use it's center position.
I'm trying out AndEngine (GLES2) in the last couple of days.
I'm having a problem with the SpriteExample from the Examples project.
In the SpriteExample in the example project the face_box.png sprite looks nice and sharp.
However when I copy the same code and the face_box.png file to my own separate project, the sprite looks pixelated.
Since the code is just the same I guess the problem is with some configuration settings, however I could not figure it out.
I'm running on Galaxy S2 with ICS.
Does anyone have any idea on what might cause the problem?
This is the code if anyone wondered -
public class AndEngineMapActivity extends SimpleBaseGameActivity implements OnClickListener {
// ===========================================================
// Constants
// ===========================================================
private static final int CAMERA_WIDTH = 800;
private static final int CAMERA_HEIGHT = 480;
// ===========================================================
// Fields
// ===========================================================
private ITexture mTexture;
private ITextureRegion mFaceTextureRegion;
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
#Override
public EngineOptions onCreateEngineOptions() {
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_SENSOR, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}
#Override
public void onCreateResources() {
try {
this.mTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
#Override
public InputStream open() throws IOException {
return getAssets().open("gfx/face_box.png");
}
});
this.mTexture.load();
this.mFaceTextureRegion = TextureRegionFactory.extractFromTexture(this.mTexture);
} catch (IOException e) {
Debug.e(e);
}
}
#Override
public Scene onCreateScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
scene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));
/* Calculate the coordinates for the face, so its centered on the camera. */
final float centerX = (CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2;
/* Create the face and add it to the scene. */
final Sprite face = new Sprite(centerX, centerY, this.mFaceTextureRegion, this.getVertexBufferObjectManager());
scene.attachChild(face);
return scene;
}
#Override
public void onClick(final ButtonSprite pButtonSprite, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(AndEngineMapActivity.this, "Clicked", Toast.LENGTH_LONG).show();
}
});
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
**Update: ** Following to JoenEye's advice I tried loading the texture differently with
#Override
public void onCreateResources() {
try {
this.mTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
#Override
public InputStream open() throws IOException {
return getAssets().open("gfx/face_box.png");
}
}, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mTexture.load();
this.mFaceTextureRegion = TextureRegionFactory.extractFromTexture(this.mTexture);
} catch (IOException e) {
Debug.e(e);
}
}
The results have improved and the smiley face picture looks a bit better, but it's still not as sharp as in the Example's project.
****Another Update: ****
These are the images of the results I get.
-
This is the one from the original example project (best result)
This is the one from my project without the TextureOptions.BILINEAR_PREMULTIPLYALPHA
This is the one from my project with the TextureOptions.BILINEAR_PREMULTIPLYALPHA (current result
By the way way - Interesting result, once I created another empty project with only this class in it and it worked flawlessly and looked good.
So I guess it must be some kind of a configuration problem with my own project.
I'd be glad to get any more ideas!
Thanks!
I'll guess that the difference between the example project and the one with the bad result is either the subpixel location of the sprite or it being stretched/skewed slightly. Are you careful to draw the sprite exactly on a pixel boundry?
The issue is when a fragment is drawn, if the fragment is not perfectly lined up with the texture it is sampling, then it must generate a color that is not exactly what is in the texture. For example if you have a 10x10 pixel texture, and you draw it at screen coordinates (0.5, 0.5), then each pixel either needs to just pick the nearest texel (NEAREST sampling), or blend together nearby texels (LINEAR or BILINEAR sampling). NEAREST can have rounding problems here if two texels are equal distances from the sample point (which might explain the slightly ugly image in the first bad result). If you use LINEAR sampling, then it just blends together the nearest texels, which may give the slightly blurred image you see in the second result.
So to remedy this for small images with tiny features, you want to always make sure to draw the image so that it lines up exactly with a pixel boundry. Can you check if you are doing this in your application?
For more information I would do some google searches for 'pixel perfect sampling/rendering`, which will give you more information.
EDIT, I also noticed this, which may explain:
final float centerX = (CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2;
You're doing integer division here, which could cause you to get the value of 'center' off by a half pixel if the image width/height is an odd number. Then when you pass this value to AndEngine your center is incorrect by a half pixel, explaining the subpixel problems.
Try using the standard way of loading images unless the method you use is necessary for some reason.
mTexture = new BitmapTexture(1024, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
BitmapTextureRegionFactory.createFromAsset(mTexture, this, "face_box.png", 0, 0);
You will probably end up using buildable textures that place the images on the texture automatically, but this could help you determine where the problem is.
Eventually I decided to just open up a new project and move all my code to the new project.
It works.
I know it's a bad solution, but it solved the problem.
If I'll ever come up with this problem again, and find a real solution, I would update it in here.
I can't seem to get TiledSprite to work as I expect. There are no manuals, and the examples in AndEngineExamples is of no help.
Consider this code:
#Override
public void onLoadResources() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
mBlockAtlas = new BitmapTextureAtlas(512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
mBlockTexture = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mBlockAtlas, getApplicationContext(), "num_plasma.png", 0, 0, 3, 3);
getTextureManager().loadTexture(mBlockAtlas);
}
This loads a 512x512 texture that I've - manually - divided into 3x3 tiles just for testing purposes. Now, doing this:
public Scene onLoadScene() {
mScene = new Scene();
mScene.setBackground(new ColorBackground(0.5f, 0.1f, 0.6f));
TiledSprite foo, foo2;
foo = new TiledSprite(0, 0, mBlockTexture);
foo.setCurrentTileIndex(1);
foo2 = new TiledSprite(0, 200, mBlockTexture);
foo2.setCurrentTileIndex(5);
mScene.attachChild(foo);
mScene.attachChild(foo2);
return mScene;
}
This puts up two sprites on the screen (as expected), but they both shows the same tile (5)!
How are one supposed to do if you have a bunch of sprites using the same texture but showing different tiles?
I think you need to deepCopy() the Texture when you are creating the Sprites, like
foo2 = new TiledSprite(0, 200, mBlockTexture.deepCopy());