如何在libgdx中制作敌方仪表探测器?

时间:2017-06-29 07:43:11

标签: android libgdx transitions detect

在我自上而下的游戏中,我有一个敌人探测器来探测敌人是否在附近。我的问题是我如何创建动态我的仪表栏的过渡?我是这个框架的新手。谢谢和进步

当玩家检测到附近的敌人时,仪表栏将像下面的图像屏幕一样动画

When enemy is near the player

没有敌人

Without enemy    enter image description here

我的代码:

    //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);

玩家移动(前进):

//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 Movement:

 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 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();
    }

2 个答案:

答案 0 :(得分:3)

在我回答您的初步问题之前,我建议您学习使用Libgdx extension Ashley,因为事情看起来非常混乱,难以维持。

我的回答:

持有一个 ArrayList&lt;&gt; 或类似的数据模型与你内部的所有游戏敌人,然后我们将遍历每一个并获得它的位置并计算与玩家的距离。< / p>

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;
    }
}

这可以为您提供最接近的敌人及其距离,您可以根据自己的需要制定方法或获得距离,您可以在每次游戏更新时运行此代码。

距离计:

这里我们要做一个小数学,让我们说你的仪表显示百分比......从0%到100%,你必须选择你的仪表认为0%的最大距离(意味着敌人是非常远的电话它maxReistance),让你轻松理解这个想象距离是100并看看这个方法。

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;
}

希望这对你有所帮助,祝你好运:)

答案 1 :(得分:0)

我使用Stack类创建Meter类。仪表图像需要是透明的,条形图像需要是动画。 Stack Actor可以重叠图像并将它们呈现在彼此之上。这是Meter类:

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() );
    }
}

使用皮肤设置actor的舞台类。

public class MyStage extends Stage {

    public Meter meter;

    public MyStage( Skin skin ){

        super();

        meter = new Meter( skin );

        Table table = new Table( skin );
        table.setFillParent( true );
        table.setOrigin( Align.top );
        table.add( meter ).width( (1/10f) * Gdx.graphics.getWidth() );

        addActor( table );
    }
}

最佳做法是创建一个皮肤并将所有ui资源放在那里。从TextureAtlas对象中的文件加载并将该对象传递到外观中。我创建了一个简单的动画,它不能正确缩放它的例子。在屏幕对象或游戏对象中:

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;