【问题标题】:How to make enemy meter detector in libgdx?如何在 libgdx 中制作敌人仪表检测器?
【发布时间】:2017-06-29 07:43:11
【问题描述】:

在我的自上而下的游戏中,我有一个敌人探测器来检测附近的敌人。我的问题是如何创建带有过渡的仪表条动画?我是这个框架的新手。感谢并提前

当玩家发现附近有敌人时,仪表条会像下面的图像屏幕截图一样动画

没有敌人

我的代码:

    //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 运动:

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

前进按钮功能:

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

【问题讨论】:

    标签: android libgdx transitions detect


    【解决方案1】:

    在我回答你最初的问题之前,我想建议你学习使用Libgdx extension Ashley,因为事情看起来很混乱,而且你很难维护。

    我的回答:

    持有一个ArrayList或类似的数据模型,里面包含你所有的游戏敌人,然后我们将遍历每一个并获取它的位置并计算到玩家的距离。

    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% 的最大距离(意味着敌人很远,称之为 maxDistance),让您轻松理解这个假设距离为 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;
    }
    

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

    【讨论】:

    • 谢谢@Ariel Yust 先生,我会试试你的代码和 libgdx ashley api
    • @jaZzZ,很高兴为您提供帮助!如果这解决了您的问题,请将其标记为答案,并在您成功时通知我们:)
    【解决方案2】:

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

    使用皮肤设置演员的舞台类。

    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;
    

    【讨论】:

      猜你喜欢
      • 2019-04-21
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2015-04-28
      • 1970-01-01
      • 2020-12-30
      相关资源
      最近更新 更多