android游戏开发框架libgdx的使用(十三)—TiledMap中的角色和角色移动

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载自夜明的孤行灯

本文链接地址: https://www.huangyunkun.com/2012/01/13/libgdx_13/

本文使用的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);
}
}elseif (newx >0 && newy <0) {
if (newx > -newy) {
ChangeDirect(4);
}else {
ChangeDirect(2);
}
}elseif (newx <0 && newy >0) {
if (-newx > newy) {
ChangeDirect(3);
}else {
ChangeDirect(1);
}
}else {
if (-newx > -newy) {
ChangeDirect(3);
}else {
ChangeDirect(2);
}
}

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

代码如下:

privatevoidCameraMove(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;

publicclass 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
publicvoidcreate() {
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
publicvoiddispose() {
// TODO Auto-generated method stub

}

@Override
publicvoidpause() {
// TODO Auto-generated method stub

}

@Override
publicvoidrender() {
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();
}

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

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

}

@Override
publicvoidresume() {
// TODO Auto-generated method stub

}

@Override
publicbooleankeyDown(int keycode) {
// TODO Auto-generated method stub
returnfalse;
}

@Override
publicbooleankeyTyped(char character) {
// TODO Auto-generated method stub
returnfalse;
}

@Override
publicbooleankeyUp(int keycode) {
// TODO Auto-generated method stub
returnfalse;
}

@Override
publicbooleanscrolled(int amount) {
// TODO Auto-generated method stub
returnfalse;
}

privatevoidChangeDirect(int typeId) {
switch (typeId) {
case1:
moveVector.set(0,1,0);
Gdx.app.log("方向变动","向上");
break;
case2:
moveVector.set(0, -1,0);
Gdx.app.log("方向变动","向下");
break;
case3:
moveVector.set(-1,0,0);
Gdx.app.log("方向变动","向左");
break;
case4:
moveVector.set(1,0,0);
Gdx.app.log("方向变动","向右");
break;
}
}

@Override
publicbooleantouchDown(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);
}
}elseif (newx >0 && newy <0) {
if (newx > -newy) {
ChangeDirect(4);
}else {
ChangeDirect(2);
}
}elseif (newx <0 && newy >0) {
if (-newx > newy) {
ChangeDirect(3);
}else {
ChangeDirect(1);
}
}else {
if (-newx > -newy) {
ChangeDirect(3);
}else {
ChangeDirect(2);
}
}
isPress =true;
returnfalse;
}

@Override
publicbooleantouchDragged(int x,int y,int pointer) {
// TODO Auto-generated method stub
returnfalse;
}

@Override
publicbooleantouchMoved(int x,int y) {
// TODO Auto-generated method stub
returnfalse;
}

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

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

(…传不上来)无语中

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

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

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载自夜明的孤行灯

本文链接地址: https://www.huangyunkun.com/2012/01/13/libgdx_13/

发表评论