libgdx [Collision]

本文详细介绍使用LibGDX框架进行2D游戏开发的过程,包括游戏初始化设置、地图加载渲染、角色动画处理及屏幕间平滑过渡等核心功能实现。

MyGdxGame.java:

package com.mygdx.game;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
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.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.maps.MapLayer;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.MapObjects;
import com.badlogic.gdx.maps.MapProperties;
import com.badlogic.gdx.maps.objects.EllipseMapObject;
import com.badlogic.gdx.maps.objects.PolygonMapObject;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapRenderer;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.objects.TiledMapTileMapObject;
import com.badlogic.gdx.maps.tiled.renderers.IsometricTiledMapRenderer;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.maps.tiled.tiles.AnimatedTiledMapTile;
import com.badlogic.gdx.math.Ellipse;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Polygon;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.badlogic.gdx.utils.viewport.Viewport;

import org.w3c.dom.css.Rect;

public class MyGdxGame extends ApplicationAdapter {
    private static final float SCALE = 0.5926f;
    private static final int VIRTUAL_WIDTH = (int)(960 * SCALE);
    private static final int VIRTUAL_HEIGHT = (int)(540 * SCALE);

    private static final float CAMERA_SPEED = 100.0f;

    private OrthographicCamera camera;
    private Viewport viewport;
    private SpriteBatch batch;

    private TiledMap map;
    private TmxMapLoader loader;
    private OrthogonalTiledMapRenderer renderer;

    private Vector2 direction;

    private Array<Sprite> triggers;

    private Music song;

    Stage stage;
    Major major;

    @Override
    public void create() {

        int screenWidth = Gdx.graphics.getWidth();
        int screenHeight = Gdx.graphics.getHeight();
        Gdx.app.log("MyGdxGame", "create screenWidth:"+screenWidth+" screenHeight:"+screenHeight);
        Gdx.app.log("MyGdxGame", "create Gdx.app.getType():"+Gdx.app.getType()+" Application.ApplicationType.Desktop:"+Application.ApplicationType.Desktop);

        camera = new OrthographicCamera();
        //camera.setToOrtho(false, 480, 336);
        viewport = new FitViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, camera);
        batch = new SpriteBatch();
        loader = new TmxMapLoader();
        map = loader.load("data/maps/tiled/tiles.tmx");
        renderer = new OrthogonalTiledMapRenderer(map, batch);
        direction = new Vector2();

        stage = new Stage(viewport);//new ScreenViewport());
        Gdx.input.setInputProcessor(stage);

        major = new Major(this, 0, 0, SCALE, map);
        stage.addActor(major);
        stage.addActor(major.buttonL);
        stage.addActor(major.buttonR);

        processMapMetadata();
    }

    @Override
    public void dispose() {
        map.dispose();
        renderer.dispose();
        stage.dispose();
        batch.dispose();
        if(song != null)
        song.dispose();
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        updateCamera();

        renderer.setView(camera);
        renderer.render();

        stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
        stage.draw();

    }

    @Override
    public void resize(int width, int height) {
        //viewport.update(width, height);
        stage.getViewport().update(width, height, true);
    }

    int screenPage = -1;
    int moveDir = 0;
    public void updateCameraExtenal(int page, int dir){
        if(screenPage != page)
            screenPage = page;
        moveDir = dir;
    }

    private void updateCamera() {
        direction.set(0.0f, 0.0f);

        int mouseX = Gdx.input.getX();
        int mouseY = Gdx.input.getY();
        int width = Gdx.graphics.getWidth();
        int height = Gdx.graphics.getHeight();

        if (Gdx.input.isKeyPressed(Input.Keys.LEFT) || (Gdx.input.isTouched() && mouseX < width * 0.25f && mouseY < height * 1.0f)) {
            direction.x = -20;
        }
        else if (Gdx.input.isKeyPressed(Input.Keys.RIGHT) || (Gdx.input.isTouched() && mouseX > width * 0.75f && mouseY < height * 1.0f)) {
            direction.x = 20;
        }
        int offset = 0;
        if(moveDir == 1)
            offset = 10;
        else if(moveDir == -1)
            offset = -10;
        if(screenPage == 2){
            if(moveDir == 1) {
                if (camera.position.x < 864)
                    direction.x = offset;
                else
                    screenPage = -1;
            }else if(moveDir == -1) {
                if (camera.position.x > 864)
                    direction.x = offset;
                else
                    screenPage = -1;
            }
        }else if(screenPage == 3){
            if(moveDir == 1) {
                if (camera.position.x < 1824)
                    direction.x = offset;
                else
                    screenPage = -1;
            }else if(moveDir == -1) {
                if (camera.position.x > 1824)
                    direction.x = offset;
                else
                    screenPage = -1;
            }
        }else if(screenPage == 1){
            if(moveDir == 1) {
                if (camera.position.x < 0)
                    direction.x = offset;
                else
                    screenPage = -1;
            }else if(moveDir == -1) {
                if (camera.position.x > 0)
                    direction.x = offset;
                else
                    screenPage = -1;
            }
        }

        //direction.nor().scl(CAMERA_SPEED).scl(Gdx.graphics.getDeltaTime());;

        camera.position.x += direction.x;
        camera.position.y += direction.y;
        //Gdx.app.log("MyGdxGame", "updateCamera camera.position.x:"+camera.position.x);

        TiledMapTileLayer layer = (TiledMapTileLayer)map.getLayers().get(0);

        float cameraMinX = viewport.getWorldWidth() * 0.5f;
        float cameraMinY = viewport.getWorldHeight() * 0.5f;
        float cameraMaxX = layer.getWidth() * layer.getTileWidth() - cameraMinX;
        float cameraMaxY = layer.getHeight() * layer.getTileHeight() - cameraMinY;

        camera.position.x = MathUtils.clamp(camera.position.x, cameraMinX, cameraMaxX);
        camera.position.y= MathUtils.clamp(camera.position.y, cameraMinY, cameraMaxY);

        major.setXOffset(camera.position.x /*- (VIRTUAL_WIDTH/2)*/);

        camera.update();
    }

    private void processMapMetadata() {
        // Load music
        String songPath = map.getProperties().get("music", String.class);
        if(songPath != null) {
            song = Gdx.audio.newMusic(Gdx.files.internal(songPath));
            if(song != null) {
                song.setLooping(true);
                song.play();
            }
        }

        MapLayer mapLayer = map.getLayers().get(0);
        Gdx.app.log("MyGdxGame", "processMapMetadata mapLayer:" + mapLayer);
        int width = ((TiledMapTileLayer)mapLayer).getWidth();
        int height = ((TiledMapTileLayer)mapLayer).getHeight();
        Gdx.app.log("MyGdxGame", "processMapMetadata width:"+width+" height:"+height);
        float tileWidth = ((TiledMapTileLayer)mapLayer).getTileWidth();
        float tileHeight = ((TiledMapTileLayer)mapLayer).getTileHeight();
        Gdx.app.log("MyGdxGame", "processMapMetadata tileWidth:"+((TiledMapTileLayer)mapLayer).getTileWidth()+" tileHeight:"+((TiledMapTileLayer)mapLayer).getTileHeight());
        major.setTileSize(tileWidth, tileHeight);

        if(mapLayer instanceof TiledMapTileLayer){
            for(int x = 0; x < width; x++) {
                for(int y = 0; y < height; y++) {
                    if(((TiledMapTileLayer)mapLayer).getCell(x, y) != null) {
                        Gdx.app.log("MyGdxGame", "processMapMetadata x:"+x+" y:"+y);
                    }
                }
            }
        }

    }
}

Major.java:

package com.mygdx.game;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;

public class Major extends Actor{

    float iconWidth = 32.0f, iconHeight = 48.0f;

   public static float x ;
   public static float y ;
   public float statetime;

    private TiledMap map;

   Texture texture;
   TextureRegion currentFrame;

   ImageButton buttonL;
   ImageButton buttonR;

   Animation aniRight;
   Animation aniLeft;
   Animation aniIdle;

   STATE state;

    float mapWidth, mapHeight;
    float tileWidth, tileHeight;
    float scaleSize = 0.0f;
    float xOffset = 0.0f;

    MyGdxGame gdxgame;

   enum STATE {
       Left,Right,Idel
   };

   public Major(MyGdxGame myGdxGame, float x,float y, float scale, TiledMap tiledMap) {
       gdxgame = myGdxGame;
       map = tiledMap;
       scaleSize = scale;

       this.x = x;
       this.y = y;
       this.statetime = 0;
       this.show();
       state = STATE.Idel;

   }
    public void setMapSize(float width, float height){
        mapWidth = width;
        mapHeight = height;
    }
   public void setTileSize(float width, float height){
       tileWidth = width;
       tileHeight = height;

       this.y = tileHeight;
   }
    public void setXOffset(float offset){
        xOffset = offset;

        buttonL.setPosition(xOffset, 0);
        buttonR.setPosition(xOffset + 32 / scaleSize, 0);
    }

   @Override
   public void draw(Batch batch, float parentAlpha) {
       // TODO Auto-generated method stub

       statetime += Gdx.graphics.getDeltaTime();

       this.update();

       this.check();

       batch.draw(currentFrame, x, y, 0.0f, 0.0f, iconWidth, iconHeight, 1.0f, 1.0f, 0.0f);
   }

    private boolean leftCheck(float x){
        float startX = x;
        int startRow = (int)(startX/32);
        int startColumn = 1;

        float endX = x+32;
        int endRow = (int)(endX/32);
        int endColumn = 1;

        if(((TiledMapTileLayer)map.getLayers().get(0)).getCell(startRow, startColumn) != null
                || ((TiledMapTileLayer)map.getLayers().get(0)).getCell(endRow, endColumn) != null){
            this.y = tileHeight * 2;
            return true;
        }else {
            this.y = tileHeight;
            return false;
        }
    }
    private boolean rightCheck(float x){
        float startX = x+32;
        startX -= 1;
        if(startX < 0.0f) startX = 0.0f;
        int startRow = (int)(startX/32);
        int startColumn = 1;

        float endX = x;
        int endRow = (int)(endX/32);
        int endColumn = 1;

        if(((TiledMapTileLayer)map.getLayers().get(0)).getCell(startRow, startColumn) != null
                || ((TiledMapTileLayer)map.getLayers().get(0)).getCell(endRow, endColumn) != null){
            this.y = tileHeight * 2;
            return true;
        }else {
            this.y = tileHeight;
            return false;
        }
    }

   public void update() {
       if(state == STATE.Left){
           if(this.x >= 544 && (this.x - 4) < 544){
               gdxgame.updateCameraExtenal(1, -1);
           }else if(this.x >= 928 && (this.x - 4) < 928){
               gdxgame.updateCameraExtenal(2, -1);
           }
           leftCheck(this.x);
           this.x -= 4;
           if(this.x < 0) this.x = 0;


       }else if (state == STATE.Right) {

           if(this.x <= 544 && (this.x + 4) > 544){
               gdxgame.updateCameraExtenal(2, 1);
           }else if(this.x <= 1113 && (this.x + 4) > 1113){
               gdxgame.updateCameraExtenal(3, 1);
           }
           rightCheck(this.x);
           this.x +=4;
           if(this.x >= (45*32-32)) this.x = (45*32-32);



       }else {
           gdxgame.updateCameraExtenal(-1, 0);
           this.y = tileHeight;
       }
       this.x = x;
   }

   public void check() {
       if(state == STATE.Left) {
           currentFrame = aniLeft.getKeyFrame(statetime, true);
           //state = STATE.Idel;
       }else if (state == STATE.Right) {
           currentFrame = aniRight.getKeyFrame(statetime, true);
           //state = STATE.Idel;
       }else if (state == STATE.Idel) {
           currentFrame = aniIdle.getKeyFrame(statetime, true);
       }

   }

   public void show() {
       texture = new Texture(Gdx.files.internal("data/animation.png"));

       TextureRegion[][] spilt = TextureRegion.split(texture, (int)iconWidth, (int)iconHeight);
       TextureRegion[][] buttons = TextureRegion.split(texture, (int)iconWidth, (int)iconHeight);

       TextureRegion[] regionR = spilt[2];
       aniRight = new Animation(0.1f, regionR);

       TextureRegion[] regionL = spilt[1];
       aniLeft = new Animation(0.1f, regionL);

       TextureRegion[] regionI = new TextureRegion[1];
       regionI[0] = spilt[0][0];

       aniIdle = new Animation(0.1f, regionI);

       TextureRegion[] buttonsRegion = new TextureRegion[4];
       buttonsRegion[0] = buttonsRegion[1] = new TextureRegion(texture, 0, 192, 64, 64);
       buttonsRegion[2] = buttonsRegion[3] = new TextureRegion(texture, 64, 192, 64, 64);
       buttonL = new ImageButton(new TextureRegionDrawable(buttonsRegion[0]), new TextureRegionDrawable(buttonsRegion[1]));
       buttonR = new ImageButton(new TextureRegionDrawable(buttonsRegion[2]), new TextureRegionDrawable(buttonsRegion[3]));

       buttonL.setOrigin(0, 0);
       buttonL.setPosition(xOffset, 0);
       buttonL.setSize(32, 32);
       buttonL.setScale(1/scaleSize);
       buttonL.getImage().setFillParent(true);
       buttonR.setOrigin(0, 0);
       buttonR.setPosition(xOffset + 32/scaleSize, 0);
       buttonR.setSize(32, 32);
       buttonR.setScale(1/scaleSize);
       buttonR.getImage().setFillParent(true);

       buttonL.addListener(new InputListener(){

           @Override
           public void touchUp(InputEvent event, float x, float y,
                   int pointer, int button) {
               // TODO Auto-generated method stub
               state = STATE.Idel;
               super.touchUp(event, x, y, pointer, button);
           }

           @Override
           public boolean touchDown(InputEvent event, float x, float y,
                   int pointer, int button) {
               // TODO Auto-generated method stub
               state = STATE.Left;
               return true;
           }

       });
       buttonR.addListener(new InputListener(){
           @Override
           public void touchUp(InputEvent event, float x, float y,
                   int pointer, int button) {
               // TODO Auto-generated method stub
               state = STATE.Idel;
               super.touchUp(event, x, y, pointer, button);
           }
           @Override
           public boolean touchDown(InputEvent event, float x, float y,
                   int pointer, int button) {
               // TODO Auto-generated method stub
               state = STATE.Right;
               return true;
           }

       });


   }


}

效果图:
这里写图片描述

tiles.tmx:

<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" renderorder="right-down" width="45" height="10" tilewidth="32" tileheight="32">
 <tileset firstgid="1" name="tukuai" tilewidth="32" tileheight="32" spacing="1" margin="1">
  <image source="tiles.png" width="512" height="256"/>
 </tileset>
 <layer name="块层 1" width="45" height="10">
  <data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,0,0,0,0,0,0,0,0,0,0,52,0,0,0,0,0,0,0,0,0,
37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37
</data>
 </layer>
</map>

tiles.png:
这里写图片描述

animation.png:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值