I'm trying to animate all the actors in a stage but FadeOut Action doesn't work
although the other actions work fine
I have the following code
getRoot().setPosition(Gdx.graphics.getWidth(), 0);
getRoot().getColor().a = 0;
SequenceAction sequenceAction = new SequenceAction();
sequenceAction.addAction(Actions.moveTo(0, 0, 3.0f));
sequenceAction.addAction(Actions.fadeOut(3.0f));
getRoot().addAction(sequenceAction);
I also tried another way to animate them by TweenEngine using class GroupAccessor implements TweenAccessor<Group> and All work fine except manipulating alpha value
public class GroupAccessor implements TweenAccessor<Group> {
public static final int ALPHA = 0;
public static final int POS_XY = 1;
#Override
public int getValues(Group target, int tweenType, float[] returnValues) {
switch (tweenType) {
case ALPHA :
returnValues[0] = target.getColor().a;
return 1;
case POS_XY :
returnValues[0] = target.getX();
returnValues[1] = target.getY();
return 2;
default:
assert false;
return -1;
}
}
#Override
public void setValues(Group target, int tweenType, float[] newValues) {
switch (tweenType) {
case ALPHA :
target.setColor(target.getColor().r, target.getColor().g, target.getColor().b,
newValues[0]);
break;
case POS_XY :
target.setPosition(newValues[0], newValues[1]);
break;
default:
assert false;
}
}
}
Animation using TweenEngine
Timeline.createSequence().
push(Tween.set(getRoot(), GroupAccessor.POS_XY).target(Gdx.graphics.getWidth(),0))
.push(Tween.to(getRoot(), GroupAccessor.POS_XY, 3.0f).target(0,0))
.push(Tween.set(getRoot(), GroupAccessor.ALPHA).target(0))
.push(Tween.to(getRoot(), GroupAccessor.ALPHA, 3.0f).target(1)).start(manager);
I have multiple actors and I made arrays of some of these actors. Here are 2 examples of draw() method of 2 actors
public void draw(Batch batch, float parentAlpha) {
batch.draw(wallSprite, 0, 0, Constants.WIDTH, Constants.HEIGHT);
}
public void draw(Batch batch, float parentAlpha) {
batch.draw(gearSprite, getX(), getY(),
gearSprite.getOriginX(), gearSprite.getOriginY(), gearSprite.getWidth(),
gearSprite.getHeight(), gearSprite.getScaleX(), gearSprite.getScaleY()
, gearSprite.getRotation());
try {
batch.draw(permittedCSprite, getX() + gearSprite.getWidth()/2
- permittedCSprite.getWidth()/2, getY() +
gearSprite.getHeight()/2 - permittedCSprite.getHeight()/2,
permittedCSprite.getWidth(), permittedCSprite.getHeight());
}
catch (NullPointerException e) {}
}
The draw method of an Actor absolutely must set a color on the Batch. This is necessary to support fading. Even if you don't care about fading or changing the color of the actor, you would still need to change the color of the Batch to WHITE to ensure what color the actor is drawn with (because there is no guarantee of what color some other actor has left the batch at.
Typically, you would have something like this at the top of your draw method:
public void draw (Batch batch, float parentAlpha) {
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
//...
}
However, if your Actor is drawing a Sprite instead of a TextureRegion, then you must set the color on the Sprite instead. This is because sprites have their own color which they pass on to the batch when you call sprite.draw.
If you are using a Sprite (which I don't recommend with Actors), your draw method should look something like this:
public void draw (Batch batch, float parentAlpha) {
sprite.setColor(getColor());
sprite.draw(batch, parentAlpha);
}
One "gotcha" is that Sprite is a subclass of TextureRegion. Sprite is a TextureRegion that holds information about color, size, orientation, position, etc, so it can be drawn a little bit faster (possibly) than a TextureRegion. It does this at the cost of using more memory. If you are using a Sprite, you should be calling sprite.draw not batch.draw(sprite ...), because the second option treats the sprite as a TextureRegion.
If you want to use Sprite, then you need to apply all the attributes you need to the sprite. For example:
public void draw (Batch batch, float parentAlpha) {
sprite.setColor(getColor());
sprite.setPosition(getX(), getY());
sprite.setSize(getWidth(), getHeight());
//etc. etc. etc. :(
sprite.draw(batch, parentAlpha);
}
For this reason, it really doesn't make sense to use a Sprite in an Actor at all. Way too much redundancy. Just use TextureRegions.
Related
So I am using the libgdx framework and am new to android games development. I have an array of yellow circle objects stored in each index which are shown on the game screen when I run them, all the circle objects are in different x positions but on the same y axis. I want to basically set the visibility of each circle for a given amount of time before the next one becomes visible for say 1000 ms per circle. So for example circle 1 will be visible for 1000 ms then it will become invisible and circle 2 will then become visible for 1000ms so on and so forth, till I reach the end of the list.
public class Spot {
private float x;
private float y;
private float radius;
private Circle spot;
private Circle spotList[];
public Spot(float x, float y, float radius, int amount){
this.x = x;
this.y = y;
this.radius = radius;
spot = new Circle(x,y,radius);
spotList = new Circle[amount];
for(int i = 0; i < spotList.length; i++){
spotList[i] = new Circle(this.x+(i*15), this.y, this.radius);
}
}
public void update(float delta){
}
public Float getX(){
return x;
}
public Float getY(){
return y;
}
public float getRadius(){
return radius;
}
public Circle[] getSpots(){
return spotList;
}
public Circle getSpot(){
return spot;
}
}
The rendering of the shape has been outsourced to a different class I want to be able to handle the visibility of the circles etc in the update method.
Since you're not using Actors (https://github.com/libgdx/libgdx/wiki/Scene2d), you need to keep track of time yourself and make the circles visible/not visible.
You will want to add
private float elapsedTime = 0.0f;
private float currentCircle = 0;
two fields, one for keeping track of elapsed time and one for the currently visible circle.
public void update(float delta){
elapsedTime += delta;
if (elapsedTime >= 1.0f) { // more than one second passed
spot[currentCircle].setVisible(false);
if (currentCircle + 1 < spotList.size()) {
currentCircle++;
spot[currentCircle].setVisible(true);
elapsedTime -= 1.0f; // reset timer (don't just set to 0.0f to avoid time shifts)
}
}
}
In the update method, count elapsedTime and if more then one seconds passed, make old circle not visible and new circle visible. Also make sure that initially the first circle is visible and that the timer is 0.
A possible solution is to use the Universal Tween Engine which works well with the libGDX framework. Visit the link to see how to include it in your project and for documentation.
As a quick demonstration on how to use it:-
Create and instantiate a TweenManager and your array of Spots in your class responsible for rendering.
protected TweenManager tweenManager = new TweenManager();
Spot spots[] = new Spot[...];
...
Create your timer by implementing the TweenCallback()
final int numberOfSpots = 5;
int spotArrayIndex = 0;
float timeDelay = 1000f; /*1000 milliseconds*/
Tween.call(new TweenCallback() {
#Override
public void onEvent(int type, BaseTween<?> source) {
/*set or unset the visibility of your Spot objects here i.e. */
spots[spotArrayIndex++].setVisible(false); /*Set current spot invisible*/
spots[spotArrayIndex].setVisible(true); /*Set next spot to be visible*/
}
}).repeat(numberOfSpots, timeDelay).start(tweenManager);
Update the tweenManager in your render method
public void render(float delta) {
...
tweenManger.update(delta);
...
}
Please check the code for errors if you use it, as I am not sure of the rest of your code.
I have a sprite that is supposed to act like a loadbar. I have tried this by using an example image that has been created like a 9patch-type (http://cdn.dibbus.com/wp-content/uploads/2011/03/btn_black.9.png). It seems okay in the start, but as the width of the sprite increases the sprite starts to look pixeled. Anyone know what the problem could be, or have any solution? The code is shown below.
public Sprite loaded;
public void init()
{
atlas = new TextureAtlas(Gdx.files.
internal("data/misc/menu_button.pack"));
loaded = atlas.createSprite("loadbar");
loaded.setPosition((Misc.WIDTH/2) - unloaded.getWidth()/2,
Misc.HEIGTH - unloaded.getHeight());
}
public void draw_load_bar() //render function
{
if(loaded.getWidth() < 600)
{
loaded.setSize(loaded.getWidth()+ 0.5f, loaded.getHeight());
}
loaded.draw(batch);
}
Dont use a Sprite to stretch it. I'd recommend a real Ninepatch from libgdx for it.
public NinePatch loaded;
private float posX, posY, width, height;
public void init()
{
loaded = new NinePatch(the Texture here,10, 10, 10, 10); //bounds outside
//set right pos here...
}
public void draw_load_bar(SpriteBatch batch) //render function
{
if(loaded.getWidth() < 600)
{
//update the size of it here (guess pos is static)
width++;
}
//need to parse the batch and the right sizes.
loaded.draw(batch, posx, posy, width, height);
}
after that you can handle it like a Sprite or Texture but it does stratch right without issues. If you want to the full Picture to be Stretched simply do net set any bounds at the creation new NinePatch(texture, 0,0,0,0)
I'm new to game development andengine. I want to add ParallaxBackground but I don't know how to change background on player move. I'm using arrow for moving a player. Now my question is where I write the code parallaxBackground.setParallaxValue(5); I was written this line in onAreaTouched method of arrow but it not work. please help me. Thanks.
Code
private Camera mCamera;
private static int CAMERA_WIDTH = 800;
private static int CAMERA_HEIGHT = 480;
private BitmapTextureAtlas bgTexture;
private ITextureRegion bgTextureRegion;
#Override
protected void onCreateResources() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
bgTexture = new BitmapTextureAtlas(getTextureManager(),2160,480,TextureOptions.REPEATING_BILINEAR);
bgTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(bgTexture, this, "background.png", 0, 0);
bgTexture.load();
}
#Override
protected Scene onCreateScene() {
this.getEngine().registerUpdateHandler(new FPSLogger());
Scene scene = new Scene();
scene.setBackground(new Background(Color.BLACK));
final ParallaxBackground parallaxBackground = new ParallaxBackground(0, 0, 0);
final VertexBufferObjectManager vertexBufferObjectManager = this.getVertexBufferObjectManager();
parallaxBackground.attachParallaxEntity(new ParallaxEntity(0.0f, new Sprite(0, CAMERA_HEIGHT - this.bgTextureRegion.getHeight(), this.bgTextureRegion, vertexBufferObjectManager)));
scene.setBackground(parallaxBackground);
Robot robot = new Robot();
// add Player
final AnimatedSprite animatedRobotSprite = new AnimatedSprite(robot.centerX, robot.centerY, 122, 126, (ITiledTextureRegion) robotTextureRegion, getVertexBufferObjectManager());
scene.attachChild(animatedRobotSprite);
animatedRobotSprite.animate(new long[]{1250,50,50});
// add right arrow button
Sprite rightArrowSprite = new Sprite(0, CAMERA_HEIGHT-70, rightArrowTextureRegion, getVertexBufferObjectManager()){
#Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,float pTouchAreaLocalX, float pTouchAreaLocalY) {
switch (pSceneTouchEvent.getAction()) {
case TouchEvent.ACTION_DOWN:
moveRight = true;
parallaxBackground.setParallaxValue(5);
break;
case TouchEvent.ACTION_MOVE:
moveRight = true;
break;
case TouchEvent.ACTION_UP:
moveRight = false;
break;
default:
break;
}
return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
}
};
scene.attachChild(rightArrowSprite);
scene.registerTouchArea(rightArrowSprite);
scene.setTouchAreaBindingOnActionDownEnabled(true);
scene.setTouchAreaBindingOnActionMoveEnabled(true);
scene.registerUpdateHandler(new IUpdateHandler() {
#Override
public void reset() {
}
#Override
public void onUpdate(float pSecondsElapsed) {
if ( moveRight ){
animatedRobotSprite.setPosition(animatedRobotSprite.getX()+speedX, animatedRobotSprite.getY());
}
}
});
return scene;
}
I see at least on possible problem: You have only one ParallaxEntity attached. The visual effect of parallax is created by multiple entities moving at different speeds.
But I think what you are seeing is that your background is not scrolling. If you do not use the AutoParallaxBackground class, you have to update the paralax amount on each update.
Inside the autoparallax class, this is what it does onUpdate():
#Override
public void onUpdate(final float pSecondsElapsed) {
super.onUpdate(pSecondsElapsed);
this.mParallaxValue += this.mParallaxChangePerSecond * pSecondsElapsed;
}
Looking at this you can see that the setParallaxValue() is an absolute number, so to make it continually scroll, you will need to feed it a new number on each update. For example, in you main game update loop, you could feed in your player.getX() into parallaxBackground.setParallaxValue() like so:
parallaxBackground.setParallaxValue(rightArrowSprite.getX());
While this may not be the exact effect you want, you should now see the background moving when your character moves.
There are different modifiers foe updating your entity(AnimatedSprite) you can use them for movement like
final Entity playerEntity = ...;//Get player entity here.
final float jumpDuration = 2;
final float x= playerEntity.getX();
final MoveXModifiermoveModifier = new MoveXModifier(jumpDuration / 2, x+ 100, y);
playerEntity.registerEntityModifier(moveModifier );
It's not necessary to have two background moving at different speeds. With one fixed background and one "moving" background you will notice the effect when the player moves. However, I've tried setting an absolute value in
parallaxBackground.setParallaxValue(10f);
And the effect was not continuous. What it worked for me was a recipe found in Android Cookbook which is based on overriding the onUpdate of the background to change only when the camera has moved.
ParallaxBackground background = new ParallaxBackground(0.3f, 0.3f,0.9f) {
/* We'll use these values to calculate the parallax value of the background*/
float cameraPreviousX = 0;
float parallaxValueOffset = 0;
/* onUpdates to the background, we need to calculate new
* parallax values in order to apply movement to the background
* objects (the hills in this case) */
#Override
public void onUpdate(float pSecondsElapsed) {
/* Obtain the camera's current center X value */
final float cameraCurrentX = mCamera.getCenterX();
/* If the camera's position has changed since last update... */
if (cameraPreviousX != cameraCurrentX) {
/* Calculate the new parallax value offset by subtracting the previous update's camera x coordinate from the current update's camera x coordinate */
parallaxValueOffset += cameraCurrentX - cameraPreviousX;
/* Apply the parallax value offset to the background, which will in-turn offset the positions of entities attached to the background */
this.setParallaxValue(parallaxValueOffset);
/* Update the previous camera X since we're finished with this update */
cameraPreviousX = cameraCurrentX;
}
super.onUpdate(pSecondsElapsed);
}
};
background.attachParallaxEntity(new ParallaxEntity(5, hillFurthest));
Note than depending on the camera configuration, the "5" value included in the "attachParallaxEntity" may need to be negative. Otherwise, the background will move in the opposite direction of the player.
I want to make a small app. You will touch the screen and draw something and it will list points you pass and draw small green 3x3 rectangles for each fifth point. I use onTouchEvent for listing points using TextView and send it to setContentView. However, I have problem in drawing. I checked examples for drawing (onDraw) but I am not able to get it working for both printing point plus drawing green dots. Any help would be great, thanks.
Here you are, a quick sample of drawing on SurfaceView.
public class FunPanel extends SurfaceView {
class Point {
int X;
int Y;
public Point() {
X = Y = -1;
}
}
private ArrayList<Point> mPoints = new ArrayList<Point>();
private Point mCurPoint = new Point();
private Bitmap mBitmap = ....// your desired image
#Override
public void doDraw(Canvas canvas) {
if( !(mPoints.size() % 5) ) {
canvas.drawBitmap(mBitmap, mCurPoint.X, mCurPoint.Y, null);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mCurPoint.X = (int) event.getX() - mBitmap.getWidth() / 2;
mCurPoint.Y = (int) event.getY() - mBitmap.getHeight() / 2;
mPoints.add(mCurPoint);
return super.onTouchEvent(event);
}
}
It's not entirely clear what you're trying to do, but have a look at this It should get you started in the right direction. Basically extend a View and override the onDraw(Canvas) to draw the Rectangles and override the onTouchEvent(MotionEvent) to grab the touch points from the screen.
I'm creating an android app using Andengine. One part of the app requires users to select a few sprites from a group of sprites on the screen, which causes the selected sprites to turn a different color (ie, moving to the next tile). I declared them all as animated sprites and I'm using the same texture for each one. The problem is that once I select a sprite, every sprite moves to the next tile, not just the one I selected. How do I make just the one sprite change?
Here's where I setup the textures and whatnot:
private Texture mGreenTextureAtlas;
private TiledTextureRegion mGreenBallFaceTextureRegion;
#Override
public void onLoadResources() {
/* Textures. */
...
this.mGreenTextureAtlas = new Texture(32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
...
TextureRegionFactory.setAssetBasePath("gfx/");
/* TextureRegions. */
...
this.mGreenBallFaceTextureRegion = TextureRegionFactory.createTiledFromAsset(this.mGreenTextureAtlas, this, "green_ball.png", 0, 16, 2, 1); // 64x32
this.mEngine.getTextureManager().loadTextures(this.mCueTextureAtlas, this.mGreenTextureAtlas , this.mBackgroundTexture, this.mPocketTexture);
}
Here's where I actually create the sprites and apply the textures:
face = new AnimatedSprite(pX, pY, this.mGreenBallFaceTextureRegion);
body = PhysicsFactory.createCircleBody(this.mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
encapsed = new Encapsulator(body, face, Encapsulator.AVOID_BALL, mFaceCount);
ballsList.add(encapsed);
I encapsulate each sprite, it's body, and some other data into an object that I made, and then add that object into an ArrayList.
Here is the onTouch event handler.
#Override
public boolean onAreaTouched( final TouchEvent pSceneTouchEvent, final ITouchArea pTouchArea,final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
if(pSceneTouchEvent.isActionDown()) {
final AnimatedSprite face = (AnimatedSprite) pTouchArea;
for(int i=0; i<ballsList.size(); i++)
{
if(face.equals(ballsList.get(i).animatedFace))
{
ballsList.get(i).toggleType(face);
System.out.println("Ball " + ballsList.get(i).id + " is now " + ballsList.get(i).type);
}
}
return true;
}
return false;
}
Finally, here is the toggleType method in the Encapsulator class that's responsible for moving to the next tile:
public void toggleType(AnimatedSprite face)
{
if(this.type == AVOID_BALL)
{
this.type = HIT_BALL;
face.nextTile();
}
else if(this.type == HIT_BALL)
{
this.type = AVOID_BALL;
face.setCurrentTileIndex(0);
}
}
Sorry if this is a bit long-winded. Any help is appreciated.
I did some more googling and came across a solution. I had to use the textureregion.clone() method when creating the sprites. I found the solution at this link:
http://www.andengine.org/forums/development/two-sprites-sharing-the-same-tiledtextureregion-t4339.html