zoukankan      html  css  js  c++  java
  • android游戏开发框架libgdx的使用(十三)—TiledMap中的角色和角色移动

    本文使用的libgdx是0.92版本,和现在的最新版可能有一些不一样的地方。全文内容仅供参考

    本文紧跟上文,地址:android游戏开发框架libgdx的使用(十二)—TiledMap地图的使用

    地图我们创建好了接下来就是主角的出现。其实上文介绍了如何TiledMap和Stage的结合,角色的处理就简单了。

    可以继承Actor类创建主角类,我就偷个懒,用Image代替。

    编辑我们的TMX文件,添加一个对象层。

    在主角要出现的地方加个形状

    取名为play1

    我们的主角是:

    思路是我们遍历map中的所有Object,如果名字和我们设定的play1一致,那么就实例化一个Image,位置和Object一致,添加到舞台。

    关键代码:

    for (TiledObjectGroup group : map.objectGroups) { 
    for (TiledObject object : group.objects) {
    if ("play1".equals(object.name)) {
    player = new Image(new TextureRegion(new Texture(Gdx.files
    .internal("map/player.png")), 0, 0, 27, 40));
    player.x = object.x;
    player.y = tileMapRenderer.getMapHeightUnits() - object.y; //map是左上角,Stage是左下角
    stage.addActor(player);
    }
    }
    }



    效果如下:

    然后现在来试试让主角动起来。

    首先是我们如何控制,android设备的话优先选用触控。如果我们按住前方不放,主角向前。按住上方不放,主角向上。

    那么如何确定我们按住的是哪个方向呢?

    如图所示,黄色的是Stage,粉红的边框是整个Map,有部分显示,有一部分没有显示。右下角的绿色点是主角的位置,我们假定红色的点是我们的触碰点。

    认定红色的触碰点为向前,我在提供一个方案,但是方法不唯一哈,我这样确定方向也不一定是最符合用户体验的。

    以主角的位置为原点重现建立坐标系,得到触碰点的新坐标x,y.

    确定了在新坐标系下的触碰点的象限,在判断x,y的大小就可以知道方向了。

    代码如下:

    Vector3 tmp = new Vector3(x, y, 0);
    stage.getCamera().unproject(tmp);
    float newx = tmp.x - player.x;
    float newy = tmp.y - player.y;
    if (newx > 0 && newy > 0) {
    if (newx > newy) {
    ChangeDirect(4);
    } else {
    ChangeDirect(1);
    }
    } else if (newx > 0 && newy < 0) {
    if (newx > -newy) {
    ChangeDirect(4);
    } else {
    ChangeDirect(2);
    }
    } else if (newx < 0 && newy > 0) {
    if (-newx > newy) {
    ChangeDirect(3);
    } else {
    ChangeDirect(1);
    }
    } else {
    if (-newx > -newy) {
    ChangeDirect(3);
    } else {
    ChangeDirect(2);
    }
    }

    直接移动Camera位置可以移动地图,但是我们的主角却从地图上消失了…处理办法是将你希望仍然显示在地图上的Actor的坐标随着Camera一起移动。

    代码如下:

    private void CameraMove(Vector3 vector3) {
    stage.getCamera().position.add(vector3);
    for (Actor actor : stage.getActors()) {
    actor.x += vector3.x;
    actor.y += vector3.y;
    }
    }

    完整代码:

    package com.cnblogs.htynkn.game;

    import com.badlogic.gdx.ApplicationListener;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.InputMultiplexer;
    import com.badlogic.gdx.InputProcessor;
    import com.badlogic.gdx.files.FileHandle;
    import com.badlogic.gdx.graphics.Color;
    import com.badlogic.gdx.graphics.GL10;
    import com.badlogic.gdx.graphics.OrthographicCamera;
    import com.badlogic.gdx.graphics.Texture;
    import com.badlogic.gdx.graphics.g2d.BitmapFont;
    import com.badlogic.gdx.graphics.g2d.TextureRegion;
    import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas;
    import com.badlogic.gdx.graphics.g2d.tiled.TileMapRenderer;
    import com.badlogic.gdx.graphics.g2d.tiled.TiledLoader;
    import com.badlogic.gdx.graphics.g2d.tiled.TiledMap;
    import com.badlogic.gdx.graphics.g2d.tiled.TiledObject;
    import com.badlogic.gdx.graphics.g2d.tiled.TiledObjectGroup;
    import com.badlogic.gdx.math.Vector2;
    import com.badlogic.gdx.math.Vector3;
    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.Label;
    import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;

    public class firstGame implements ApplicationListener, InputProcessor {

    Stage stage;
    float width;
    float height;
    private TiledMap map;
    private TileAtlas atlas;
    private TileMapRenderer tileMapRenderer;
    Image player;
    Vector3 camDirection = new Vector3(1, 1, 0);
    Vector2 maxCamPosition = new Vector2(0, 0);
    Vector3 moveVector = new Vector3(0, 0, 0);
    boolean isPress;

    // Image image;

    @Override
    public void create() {
    final String path = "map/";
    final String mapname = "tilemap";
    FileHandle mapHandle = Gdx.files.internal(path + mapname + ".tmx");
    map = TiledLoader.createMap(mapHandle);
    atlas = new TileAtlas(map, Gdx.files.internal("map/"));
    tileMapRenderer = new TileMapRenderer(map, atlas, 10, 10);
    maxCamPosition.set(tileMapRenderer.getMapWidthUnits(), tileMapRenderer
    .getMapHeightUnits());

    width = Gdx.graphics.getWidth();
    height = Gdx.graphics.getHeight();
    stage = new Stage(width, height, true);
    Label label = new Label("FPS:", new LabelStyle(new BitmapFont(Gdx.files
    .internal("font/blue.fnt"),
    Gdx.files.internal("font/blue.png"), false), Color.WHITE),
    "fpsLabel");
    label.y = height - label.getPrefHeight();
    label.x = 0;
    stage.addActor(label);

    for (TiledObjectGroup group : map.objectGroups) {
    for (TiledObject object : group.objects) {
    if ("play1".equals(object.name)) {
    player = new Image(new TextureRegion(new Texture(Gdx.files
    .internal("map/player.png")), 0, 0, 27, 40));
    player.x = object.x;
    player.y = tileMapRenderer.getMapHeightUnits() - object.y; // map是左上角,Stage是左下角
    stage.addActor(player);
    }
    }
    }

    InputMultiplexer inputMultiplexer = new InputMultiplexer();
    inputMultiplexer.addProcessor(this);
    inputMultiplexer.addProcessor(stage);
    Gdx.input.setInputProcessor(inputMultiplexer);
    }

    @Override
    public void dispose() {
    // TODO Auto-generated method stub

    }

    @Override
    public void pause() {
    // TODO Auto-generated method stub

    }

    @Override
    public void render() {
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    OrthographicCamera c = (OrthographicCamera) stage.getCamera();
    if (isPress) {
    CameraMove(moveVector);
    }
    ((Label) stage.findActor("fpsLabel")).setText("FPS: "
    + Gdx.graphics.getFramesPerSecond());
    stage.act(Gdx.graphics.getDeltaTime());
    tileMapRenderer.render(c);
    stage.draw();
    }

    private void CameraMove(Vector3 vector3) {
    stage.getCamera().position.add(vector3);
    for (Actor actor : stage.getActors()) {
    actor.x += vector3.x;
    actor.y += vector3.y;
    }
    }

    @Override
    public void resize(int width, int height) {
    // TODO Auto-generated method stub

    }

    @Override
    public void resume() {
    // TODO Auto-generated method stub

    }

    @Override
    public boolean keyDown(int keycode) {
    // TODO Auto-generated method stub
    return false;
    }

    @Override
    public boolean keyTyped(char character) {
    // TODO Auto-generated method stub
    return false;
    }

    @Override
    public boolean keyUp(int keycode) {
    // TODO Auto-generated method stub
    return false;
    }

    @Override
    public boolean scrolled(int amount) {
    // TODO Auto-generated method stub
    return false;
    }

    private void ChangeDirect(int typeId) {
    switch (typeId) {
    case 1:
    moveVector.set(0, 1, 0);
    Gdx.app.log("方向变动", "向上");
    break;
    case 2:
    moveVector.set(0, -1, 0);
    Gdx.app.log("方向变动", "向下");
    break;
    case 3:
    moveVector.set(-1, 0, 0);
    Gdx.app.log("方向变动", "向左");
    break;
    case 4:
    moveVector.set(1, 0, 0);
    Gdx.app.log("方向变动", "向右");
    break;
    }
    }

    @Override
    public boolean touchDown(int x, int y, int pointer, int button) {
    Vector3 tmp = new Vector3(x, y, 0);
    stage.getCamera().unproject(tmp);
    float newx = tmp.x - player.x;
    float newy = tmp.y - player.y;
    if (newx > 0 && newy > 0) {
    if (newx > newy) {
    ChangeDirect(4);
    } else {
    ChangeDirect(1);
    }
    } else if (newx > 0 && newy < 0) {
    if (newx > -newy) {
    ChangeDirect(4);
    } else {
    ChangeDirect(2);
    }
    } else if (newx < 0 && newy > 0) {
    if (-newx > newy) {
    ChangeDirect(3);
    } else {
    ChangeDirect(1);
    }
    } else {
    if (-newx > -newy) {
    ChangeDirect(3);
    } else {
    ChangeDirect(2);
    }
    }
    isPress = true;
    return false;
    }

    @Override
    public boolean touchDragged(int x, int y, int pointer) {
    // TODO Auto-generated method stub
    return false;
    }

    @Override
    public boolean touchMoved(int x, int y) {
    // TODO Auto-generated method stub
    return false;
    }

    @Override
    public boolean touchUp(int x, int y, int pointer, int button) {
    isPress = false;
    Gdx.app.log("Info", "touchUp: x:" + x + " y: " + y + " pointer: "
    + pointer + " button: " + button);
    return false;
    }
    }



    最终效果:(图像加载可能有点慢)

     (...传不上来)无语中...

    我不知道怎么录制手机屏幕,所以只有用模拟机演示,但是真机(中兴V880)速度很流畅,完全没问题。

    如果有多个角色,方法是一样的,多建几个Object就行了。可以很明显看出,我们的忍者水平很高…行走地图完全没有障碍,而且如果你一直走的话会发现地图会消失一部分,这些问题接下的文章会慢慢解决的。

  • 相关阅读:
    GCD 信号量使用记录
    使用AFNetWorking 上传文件/图片
    iOS 13 使用LaunchScreen.storyboard设置启动图注意事项
    clipsToBounds和masksToBounds的区别?
    react-native 单页面界面横屏(带导航栏的V5.0不支持,V4.0,V3.0支持)
    react-native 5.0导航栏配置
    使用SSZipArchive 注意事项
    iOS 相册照片heic (实况)
    react-native 集成Code-Push的常用命令
    Java基础知识学习02-运算符、循环语句、break、continue
  • 原文地址:https://www.cnblogs.com/htynkn/p/libgdx_13.html
Copyright © 2011-2022 走看看