Libgdx游戏编程之角色技能战斗场景

本教程将实现角色技能攻击释放和NPC受到攻击掉血的效果。

来看下效果:

预先准备NPC、技能和字体素材,位图字体准备两种效果,字体大的可以显示暴击掉血效果

 场景代码

package com.mygdx.game.battle.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.mygdx.game.battle.BattleDemo;

import java.util.Random;

public class BattleScreen implements Screen {
    private BattleDemo game;
    private OrthographicCamera camera;
    private Viewport viewport;
    private TextureAtlas atlas;
    private TextureAtlas spriteAtlas;
    private Animation<TextureAtlas.AtlasRegion> wolfWalkAnim;
    private Animation<TextureAtlas.AtlasRegion> wolfAttackAnim;
    private Animation<TextureAtlas.AtlasRegion> wolfSkillAnim;
    private Animation<TextureAtlas.AtlasRegion> pigWalkAnim;
    private TextureAtlas.AtlasRegion pigScaredRegion;
    private TextureAtlas.AtlasRegion pigDeadRegion;
    private Rectangle pigRect;
    private Rectangle skillRect;
    private BitmapFont bitmapFont;
    private BitmapFont bigBitmapFont;
    private float wolfStateTime = 0;
    private float wolfAttackStateTime = 0;
    private float wolfSkillStateTime = 0;
    private float pigStateTime = 0;
    private float pigScaredTime = 0;
    private float bloodDisplayTime = 0;

    private boolean isAttacking = false;
    private boolean isPigBeingAttack = false;
    private boolean debug = false;

    private Random random = new Random();
    private int bloodReduce;

    public BattleScreen(BattleDemo game){
        this.game = game;
        atlas = new TextureAtlas(Gdx.files.internal("battle/battle.atlas"));
        spriteAtlas = new TextureAtlas(Gdx.files.internal("battle/sprites.atlas"));
        bitmapFont = new BitmapFont(Gdx.files.internal("bitmapfont.fnt"), false);
        bigBitmapFont = new BitmapFont(Gdx.files.internal("bitmapfont_big.fnt"), false);

        camera = new OrthographicCamera();
        viewport = new FitViewport(BattleDemo.V_WIDTH, BattleDemo.V_HEIGHT, camera);

        //wolf walking
        Array<TextureAtlas.AtlasRegion> wolfRegions = atlas.findRegions("wolf");
        Array<TextureAtlas.AtlasRegion> frames = new Array<>();
        for (int i = 0; i < 4; i++) {
            frames.add(wolfRegions.get(i));
        }
        wolfWalkAnim = new Animation(0.2f, frames, Animation.PlayMode.LOOP);

        //wolf attack
        frames.clear();
        for (int i = 7; i < 9; i++) {
            frames.add(wolfRegions.get(i));
        }
        wolfAttackAnim = new Animation(0.2f, frames, Animation.PlayMode.NORMAL);

        //skill
        Array<TextureAtlas.AtlasRegion> skillRegions = atlas.findRegions("effect_n");
        skillRegions.reverse();
        wolfSkillAnim = new Animation(0.1f, skillRegions, Animation.PlayMode.NORMAL);

        //pig
        Array<TextureAtlas.AtlasRegion> pigRegions = spriteAtlas.findRegions("pig");
        frames.clear();
        for (int i = 0; i < 3; i++) {
            frames.add(pigRegions.get(i));
        }
        pigWalkAnim = new Animation(0.2f, frames, Animation.PlayMode.LOOP);
        pigScaredRegion = pigRegions.get(3);
        pigDeadRegion = pigRegions.get(4);

    }
    @Override
    public void show() {
    }

    private void handleInput() {
        //按J键攻击
        if(Gdx.input.isKeyJustPressed(Input.Keys.J)){
            attack();
        }
    }

    private boolean handleCollision(Rectangle rectangle1, Rectangle rectangle2) {
        //简单使用判断矩形是否重叠来做碰撞检测
        if(rectangle1 == null || rectangle2 == null){
            return false;
        }
        return rectangle1.overlaps(rectangle2);
    }

    public void attack(){
        isAttacking = true;
    }

    @Override
    public void render(float delta) {
        ScreenUtils.clear(Color.BLACK);
        camera.update();
        handleInput();
        game.batch.begin();

        if(isAttacking){
            //狼NPC攻击动作
            wolfAttackStateTime += delta;
            TextureAtlas.AtlasRegion keyFrame = wolfAttackAnim.getKeyFrame(wolfAttackStateTime);
            if(!keyFrame.isFlipX()){
                keyFrame.flip(true, false);
            }
            game.batch.draw(keyFrame, 0, 0);
            if(debug)
                drawDebug(0, 0, keyFrame.getRegionWidth(), keyFrame.getRegionHeight());
            //攻击动作完后显示技能效果
            if(wolfAttackAnim.isAnimationFinished(wolfAttackStateTime)){
                wolfSkillStateTime += delta;
                TextureAtlas.AtlasRegion skillRegion = wolfSkillAnim.getKeyFrame(wolfSkillStateTime);
                if(!skillRegion.isFlipX()){
                    skillRegion.flip(true, false);
                }
                //技能随时间向右位移一段距离
                Float x = 40 + wolfSkillStateTime * 1000;
                game.batch.draw(skillRegion, x, 15);
                //获取技能帧图矩形,用以和猪做碰撞检测
                skillRect = new Rectangle(x, 15, skillRegion.getRegionWidth(), skillRegion.getRegionHeight());

                if(handleCollision(pigRect, skillRect)){
                    pigScaredTime = 0;
                    isPigBeingAttack = true;
                    //一旦和猪发生碰撞,将矩形设置为null防止多次触发碰撞事件
                    pigRect = null;
                    skillRect = null;
                    //随机产生掉血值
                    bloodReduce = random.nextInt(1000) + 100;
                }
                if(debug)
                    drawDebug(x.intValue(), 15, skillRegion.getRegionWidth(), skillRegion.getRegionHeight());
            }
        }else{
            //狼不攻击的时候默认播放行走动作
            wolfStateTime += delta;
            TextureAtlas.AtlasRegion keyFrame = wolfWalkAnim.getKeyFrame(wolfStateTime);
            //狼的纹理默认是面向左边的,因此需要翻转
            if(!keyFrame.isFlipX()){
                keyFrame.flip(true, false);
            }
            game.batch.draw(keyFrame, 0, 0);
            if(debug)
                drawDebug(0, 0, keyFrame.getRegionWidth(), keyFrame.getRegionHeight());
        }

        //pig
        if(isPigBeingAttack){
            //播放猪收到攻击的纹理帧
            game.batch.draw(pigScaredRegion, 350, 0);
            pigScaredTime += delta;

            if(debug)
                drawDebug(350, 0, pigScaredRegion.getRegionWidth(), pigScaredRegion.getRegionHeight());
        }else{
            //猪默认播放行走动作
            pigStateTime += delta;
            TextureAtlas.AtlasRegion pigRegion = pigWalkAnim.getKeyFrame(pigStateTime);
            game.batch.draw(pigRegion, 350, 0);
            pigRect = new Rectangle(350, 0, pigRegion.getRegionWidth(), pigRegion.getRegionHeight());
            //fot debug
            if(debug)
                drawDebug(350, 0, pigRegion.getRegionWidth(), pigRegion.getRegionHeight());
        }

        //display blood reduce effect
        if(isPigBeingAttack){
            //猪受到攻击显示掉血效果
            float alpha = (100 - bloodDisplayTime * 100) / 100;
            bitmapFont.setColor(1, 1, 1, alpha);
            float y = pigScaredRegion.getRegionHeight() + 20 + bloodDisplayTime * 100;
            //模拟暴击掉血效果
            if(bloodReduce > 600){
                bigBitmapFont.draw(game.batch, "" + bloodReduce, 340, y);
            }else{
                bitmapFont.draw(game.batch, "" + bloodReduce, 340, y);
            }
            bloodDisplayTime += delta;
        }else{
            bloodDisplayTime = 0;
        }

        game.batch.end();

        if(pigScaredTime > 0.5){
            isPigBeingAttack = false;
        }
        //技能播放完后重置变量值
        if(wolfSkillAnim.isAnimationFinished(wolfSkillStateTime)){
            isAttacking = false;
            wolfAttackStateTime = 0;
            wolfSkillStateTime = 0;
        }
    }

    //绘制DEBUG矩形框
    private void drawDebug(int x, int y, int width, int height){
        Pixmap pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888);
        pixmap.setColor(Color.GREEN);
        pixmap.drawRectangle(0, 0, width, height);
        //TODO need to dispose
        game.batch.draw(new Texture(pixmap), x, y);
    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {

    }

    @Override
    public void dispose() {
        atlas.dispose();
        spriteAtlas.dispose();
        bitmapFont.dispose();
    }
}

游戏入口类

package com.mygdx.game.battle;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.mygdx.game.battle.screens.BattleScreen;

public class BattleDemo extends Game {
    public static final int V_WIDTH = 800;
    public static final int V_HEIGHT = 400;

    public SpriteBatch batch;
    @Override
    public void create() {
        batch = new SpriteBatch();
        setScreen(new BattleScreen(this));
    }

    @Override
    public void render() {
        super.render();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dyyaries

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值