2017-06-29 6 views
4

In meinem Top-Down-Spiel habe ich einen Feinddetektor, um den Feind in der Nähe zu erkennen.Mein Problem ist, wie kann ich meine Meterleiste mit Übergang animieren? Ich bin zu diesem Rahmen neu. Danke und VorausWie man feindlichen Meter Detektor in libgdx machen?

Wenn der Spieler die Gegner in der Nähe erkennt, wird der Zähler Bar animiert ebenso wie das Bild Screenshot unten

When enemy is near the player

Ohne Feind

Without enemy enter image description here

Mein Code:

//detector 
    meter_bar = new Texture("meter_bar.png"); 
    myTextureRegion = new TextureRegion(meter_bar); 
    myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion); 
    actormeter_bar = new Image(myTexRegionDrawable); 
    actormeter_bar.setPosition(200,1005); 
    stage.addActor(actormeter_bar); 

    meter = new Texture("meter.png"); 
    myTextureRegion = new TextureRegion(meter); 
    myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion); 
    actormetter = new Image(myTexRegionDrawable); 
    actormetter.setPosition(190,990); 
    stage.addActor(actormetter); 

Spieler Bewegung (vorwärts):

//right_control 
    right_paw = new Texture(Gdx.files.internal("right_paw.png")); 
    myTextureRegion = new TextureRegion(right_paw); 
    myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion); 
    moveForward = new ImageButton(myTexRegionDrawable); //Set the button up 
    moveForward.getStyle().imageUp = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("right_paw.png")))); 
    //the hover 
    moveForward.getStyle().imageDown = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("right_paw-hover.png")))); 
    moveForward.setPosition(520,110); 
    stage.addActor(moveForward); //Add the button to the stage to perform rendering and take input. 
    Gdx.input.setInputProcessor(stage); 
    moveForward.addListener(new InputListener(){ 
     @Override 
     public void touchUp (InputEvent event, float x, float y, int pointer, int button) { 
      System.out.println("Right Button Pressed"); 
      progressKnobX = progressKnobX + 4; 

      actorprogressknob.setX(progressKnobX); // x-position to move to 
      if(progressKnobX > 418) progressKnobX= 418 ; 
      music.play(); 
      motionState=MotionState.NONE; 
     } 
     @Override 
     public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) { 
      motionState=MotionState.UP; 
      return true; 
     } 
    }); 
    stage.addActor(moveForward); 

EnemySprite Bewegung:

zombie = new Texture(Gdx.files.internal("enemy/ZombieSprite.png")); 
    zombiesprite = new Sprite(zombie); 
    zombieenemy = new Rectangle(); 
    zombieenemy.setWidth(zombiesprite.getWidth()); 

    zombieenemy = zombiesprite.getBoundingRectangle(); 
    zombieenemy.x = zombieX; 
    zombieenemy.y = zombieY; 
    TextureRegion[][] zom = TextureRegion.split(zombie, zombie.getWidth()/Zombie_FRAME_COLS, zombie.getHeight()/Zombie_FRAME_ROWS); 
    TextureRegion[] zwalkFrames = new TextureRegion[Zombie_FRAME_COLS * Zombie_FRAME_ROWS]; 
    index = 0; 
    for (int i = 0; i < Zombie_FRAME_ROWS; i++) { 
     for (int j = 0; j < Zombie_FRAME_COLS; j++) { 
      zwalkFrames[index++] = zom[i][j]; 
     } 
    } 
    zombiewalkAnimation = new Animation<TextureRegion>(0.120f, zwalkFrames); 

MoveForward Button Funktion:

//button functions 
MotionState motionState=MotionState.NONE; 
enum MotionState { 
    NONE { 
     @Override 
     public boolean update(Rectangle player) { 
      return true; 
     } 
    }, 
    UP { 
     @Override 
     public boolean update(Rectangle player) { 
      player.y += 300 * Gdx.graphics.getDeltaTime(); 
      return false; 
     } 
    }, 
    DOWN{ 
     @Override 
     public boolean update(Rectangle player) { 
      player.y -= 300 * Gdx.graphics.getDeltaTime(); 
      return false; 
     } 
    }, 
    LEFT{ 
     @Override 
     public boolean update(Rectangle player) { 
      player.x -= 100 * Gdx.graphics.getDeltaTime(); 
      return false; 
     } 
    }, 
    RIGHT{ 
     @Override 
     public boolean update(Rectangle player) { 
      player.x += 100 * Gdx.graphics.getDeltaTime(); 
      return false; 
     } 
    }; 
    public abstract boolean update(Rectangle player); 
} 

if(Gdx.input.isKeyPressed(Input.Keys.DOWN)) motionState = MotionState.DOWN; 
    if(Gdx.input.isKeyPressed(Input.Keys.UP)) motionState=MotionState.UP; 
    if(Gdx.input.isKeyPressed(Input.Keys.LEFT)) motionState=MotionState.LEFT; 
    if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)) motionState=MotionState.RIGHT; 

    if(motionState.update(player)) motionState=MotionState.NONE; 


    if(player.y> 1910){ 
     zombieenemy.y -= 60 * Gdx.graphics.getDeltaTime(); 
    } 

Antwort

3

Render Bevor ich Ihre erste Frage zu beantworten, würde ich Sie Libgdx extension Ashley, weil die Art und Weise Dinge wie sehr unordentlich aussehen verwenden lernen vorschlagen, ist und wird für Sie schwer zu halten.

Meine Antwort:

hält ein Arraylist <> oder ähnliches Datenmodell mit allen Spielen Feind im Innern, dann werden wir durch jeden laufen und bekommen es Position ist und berechnen Abstand zum Spieler.

Enemy closestEnemy = null; 
float closestEnemyDist = -1; 

for(Enemy enemy : ListOfEnemies){ 
    /* here we find the distance to the player */ 
    float distToPlayer = Math.sqrt((enemy.y-player.x)^2 + (enemy.y-player.y)^2); 

    /* initiate closestEnemyDist for the first time */ 
    if(closestEnemyDist == -1){ 
     closestEnemyDist = distToPlayer; 
    } 

    /* we find the closest distance to the player */ 
    float minDist = Math.min(closestEnemyDist, distToPlayer); 

    /* we make sure it is the closest and save the closest enemy as well */ 
    if(minDist <= closestEnemyDist){ 
     closestEnemyDist = minDist; 
     closestEnemy = enemy; 
    } 
} 

Dies gibt Ihnen den nächsten Feind und seinen Abstand, können Sie eine Methode daraus machen oder einfach nur den Abstand, wenn Sie möchten, können Sie diesen Code jedes Spiel Update ausführen können.

Der Entfernungsmesser:

hier Gonna wir eine kleine Mathematik tun, lassen Sie uns Ihr Messgerät zeigt Prozent sagen ... von 0% bis 100%, die maximale Entfernung wählen müssen Ihr Messgerät hält 0% (was bedeutet, der Feind ist sehr weit nennen Sie maxDistance), für Sie leicht zu verstehen, stellen Sie sich vor, dass die Entfernung 100 ist und schauen Sie sich diese Methode an.

public int calcMeter(float closestEnemyDist, float maxDistance) { 
    int meter = 0; 

    /* calculate only if enemy is in range */ 
    if(closestEnemyDist < maxDistance){ 
     /* using rounding and multiply by 100f because we wanted 
     * values from 0 - 100, you can can modify this to work just 
     * with float from 0 - 1f 
     */ 
     meter = Math.round(
      /* 
      * here we flip the percentage so if the enemy is very 
      * close then your meter will be higher 
      */ 
      (1f - (closestEnemyDist/maxDistance)) * 100f 
     ); 
    } 
    return meter; 
} 

Hoffnung, dies hilft Ihnen, viel Glück :)

+0

Danke Sir @Ariel Yust, wil ich Ihren Code und die Libgdx ashley api – jaZzZ

+0

@jaZzZ, Glad versuchen, Ihnen zu helfen! Wenn dies Ihr Problem löst, markieren Sie es als Antwort und halten Sie uns auf dem Laufenden, wenn Sie erfolgreich sind. –

0

Ich benutze die Stack-Klasse das Messgerät Klasse zu erstellen. Das Meterbild muss transparent sein und das Balkenbild muss eine Animation sein. Stack Actor kann die Bilder überlappen und sie übereinander rendern.Hier ist die Meter-Klasse:

public class Meter extends Stack { 

    private Animation<Drawable> animation; 
    private Image bar; 

    public Meter(Skin skin){ 

     Array<Drawable> drawables = new Array<Drawable>(); 

     for (int i = 0; i < TestScreen.LENGTH; ++i){ 
      drawables.add(skin.getDrawable(TestScreen.BAR + Integer.toString(i))); 
     } 

     animation = new Animation<Drawable>(1f, drawables); 
     bar = new Image(animation.getKeyFrame(0f)); 
     addActor(bar); 
     addActor(new Image(skin.getDrawable(TestScreen.METER))); 
     setTouchable(Touchable.disabled); 
    } 

    /** 
    * Set the "hotness" of the meter. 
    * @param value float between 0 and 1 
    */ 
    public void setValue(float value){ 

     // actions are the default way to animate simple effects to the actors 
     // this is just to add a pop in effect when you have a really smooth animation this isn't really necessary 
     bar.addAction(Actions.sequence(
      Actions.alpha(0), 
      Actions.fadeIn(0.01f, Interpolation.smooth) 
     )); 

     // set the new image to the value percentage 
     bar.setDrawable(animation.getKeyFrame(value * animation.getAnimationDuration())); 
     bar.setSize(bar.getPrefWidth(), bar.getPrefHeight()); 
    } 
} 

Bühnenklasse, die Haut verwendet, um die Akteure zu setzen.

Best Practice ist es, eine Haut zu erstellen und alle UI-Ressourcen in dort zu setzen. Laden Sie aus einer Datei in ein TextureAtlas-Objekt und übergeben Sie dieses Objekt an die Skin. Ich habe eine einfache Animation erstellt, die nicht korrekt skaliert ist, nur als Beispiel. Im Bildobjekt oder Spielobjekt:

private MyStage myStage; 

@Override 
public void show(){ 

    Skin skin = new Skin(); 
    skin.add(METER, new TextureRegionDrawable(new TextureRegion(meter_texture)), Drawable.class); 

    float w = meter_bar_texture.getWidth()/(float) LENGTH; 

    for (int i = 0; i < LENGTH; ++i){ 
     TextureRegion region = new TextureRegion(meter_bar_texture, 0, 0, (int)(i * w), meter_bar_texture.getHeight()); 

     skin.add(BAR + Integer.toString(i), new TextureRegionDrawable(region), Drawable.class); 
    } 

    this.myStage = new MyStage(skin); 
} 

@Override 
public void hide() { 

    super.hide(); 

    this.meter_bar_texture.dispose(); 
    this.meter_texture.dispose(); 
} 

@Override 
public void update(float delta) { 

    if (dangerIncreased() && value < 100){ 
     danger += 5; 

     this.myStage.meter.setValue(danger/100f); 
    } else if (dangerDecreased() && danger > 0){ 
     danger -= 5; 

     this.myStage.meter.setValue(danger/100f); 
    } 

    this.myStage.act(delta); 
} 

public static final String METER = "meter"; 
public static final String BAR = "bar"; 
public static final int LENGTH = 10;