分享了一些素材,有兴趣的朋友可以看看:http://www.cnblogs.com/htynkn/archive/2012/01/19/game_resource.html
前些日子的文章介绍了tiledmap的主角出现和移动等等问题。相对于主角游戏自然还应该有敌人(?)。
与主角不同的是,这些元素的移动时程序控制的,一般有3种。
1.随主角的移动变化,靠近主角或远离主角
2.按照固定路线移动
3.不动
第一种的话完全是看你的游戏逻辑决定,和tiledmap关系不大。第二种的话我们可以避免硬编码(把移动路径写入程序代码中),而采用tiledmap实现,下面我们来看看具体过程。
还是新建一张地图,我选用的大小是50*30,块大小:32*32。
然后绘制地图:
我们假定敌人从地图中间的那条路走到左边的角上。路径如下:
现在新建一个对象层,命名为wayPoints。在几个关键的地方标注上对象,命名为wayPoint1,wayPoint2…
处理好地图后拷贝到项目中。
现在新建一个Enemy类,继承Image。
现在来整理一下思路,首先我们要得到所有的wayPoint.而第一个wayPoint就是角色的初始化点。那么Enemy类首先需要一个Vector2列表,然后继承Image需要一个TextureRegion。
所以构造函数为
public Enemy(List<Vector2> vector2s, TextureRegion region) {
super(region);
this.vector2s = vector2s;
currentIndex = 0;
this.x = vector2s.get(currentIndex).x;
this.y = vector2s.get(currentIndex).y;
}
初始点有了,如何移动呢?我们先来看一下坐标
我们现在在点1位置,将要移动到点2位置。只需计算x,y,z长度,然后求出对应的moveX和moveY就可以了。
float x = Math.abs(v1.x - v2.x);
float y = Math.abs(v1.y - v2.y);
float z = (float) MathUtil.distanceBetweenTwoPoints(v1, v2);
float moveX = 0f;
float moveY = 0f;
moveX = (x / z) * stepLength;
moveY = (y / z) * stepLength;
if (this.x < v2.x) {
this.x += moveX;
} else {
this.x -= moveX;
}
if (this.y < v2.y) {
this.y += moveY;
} else {
this.y -= moveY;
}
distanceBetweenTwoPoints是我自己写的方法,计算两点距离。
现在我们的Enemy类就可以很正常的移动到下一个点了。
但当它接近下一个点的时候可以发现它在不停的颤抖。这是因为我们没有处理当Enemy到达下一个点时对点序列的更新。
当它和下一个点的距离很小时我们认定它到达下一个点,更新序列以保证它继续向下一个点移动。
int nextIndex = currentIndex + 1 >= vector2s.size() - 1 ? vector2s
.size() - 1 : currentIndex + 1;
Vector2 v1 = vector2s.get(currentIndex);
Vector2 v2 = vector2s.get(nextIndex);
if (MathUtil.distanceBetweenTwoPoints(new Vector2(this.x, this.y), v2) < 1) {
currentIndex = currentIndex + 1 < vector2s.size() - 1 ? currentIndex + 1
: vector2s.size() - 1;
nextIndex = currentIndex + 1 >= vector2s.size() - 1 ? vector2s
.size() - 1 : currentIndex + 1;
v1 = vector2s.get(currentIndex);
v2 = vector2s.get(nextIndex);
}
基本没有问题了,我们看一下效果:
因为手机不好截图,所以用的java桌面项目。
Enemy用的图片是这张
用TextureRegion[][] regions = TextureRegion.split(texture, 25, 33);切分,去2行3列。
完整代码:
package com.cnblogs.htynkn.game;
import java.util.ArrayList;
import java.util.List;
import javax.swing.text.ZoneView;
import javax.swing.text.html.MinimalHTMLWriter;
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.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
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.TileSet;
import com.badlogic.gdx.graphics.g2d.tiled.TiledLayer;
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.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.MathUtil;
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;
import com.cnblogs.htynkn.actors.Enemy;
public class MapDemo implements ApplicationListener, InputProcessor {
Stage stage;
float width;
float height;
private TiledMap map;
private TileAtlas atlas;
private TileMapRenderer tileMapRenderer;
Vector3 camDirection = new Vector3(1, 1, 0);
Vector2 maxCamPosition = new Vector2(0, 0);
Vector3 moveVector = new Vector3(0, 0, 0);
Enemy enemy;
int i = 0;
@Override
public void create() {
final String path = "map/";
final String mapname = "adancedmap";
FileHandle mapHandle = Gdx.files.internal(path + mapname + ".tmx");
map = TiledLoader.createMap(mapHandle);
atlas = new TileAtlas(map, new FileHandle("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);
List<Vector2> list = new ArrayList<Vector2>();
//获取所有wayPoints
for (TiledObjectGroup group : map.objectGroups) {
for (TiledObject object : group.objects) {
if (object.name.startsWith("wayPoint")) {
System.out.println(object.name + " X:" + object.x + " Y:"
+ object.y);
list
.add(new Vector2(object.x, maxCamPosition.y
- object.y));
}
}
}
TextureAtlas region = new TextureAtlas(Gdx.files.internal("imgs/pack"));
Texture texture = region.findRegion("Enemy").getTexture();
TextureRegion[][] regions = TextureRegion.split(texture, 25, 33);
enemy = new Enemy(list, regions[1][2]);
stage.addActor(enemy);
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();
c.position.set(enemy.x, enemy.y, 0);
stage.act(Gdx.graphics.getDeltaTime());
tileMapRenderer.render(c);
stage.draw();
}
@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) {
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;
}
@Override
public boolean touchDown(int x, int y, int pointer, int button) {
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) {
Gdx.app.log("Info", "touchUp: x:" + x + " y: " + y + " pointer: "
+ pointer + " button: " + button);
return false;
}
}
分割线=====================================分割线
package com.cnblogs.htynkn.actors;
import java.util.ArrayList;
import java.util.List;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.MathUtil;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
public class Enemy extends Image {
List<Vector2> vector2s = new ArrayList<Vector2>();
int currentIndex;
float stepLength = 1f;
public Enemy(List<Vector2> vector2s, TextureRegion region) {
super(region);
this.vector2s = vector2s;
currentIndex = 0;
this.x = vector2s.get(currentIndex).x;
this.y = vector2s.get(currentIndex).y;
}
@Override
public void draw(SpriteBatch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
}
@Override
public Actor hit(float x, float y) {
return null;
}
@Override
public void act(float delta) {
int nextIndex = currentIndex + 1 >= vector2s.size() - 1 ? vector2s
.size() - 1 : currentIndex + 1;
Vector2 v1 = vector2s.get(currentIndex);
Vector2 v2 = vector2s.get(nextIndex);
if (MathUtil.distanceBetweenTwoPoints(new Vector2(this.x, this.y), v2) < 1) {
currentIndex = currentIndex + 1 < vector2s.size() - 1 ? currentIndex + 1
: vector2s.size() - 1;
nextIndex = currentIndex + 1 >= vector2s.size() - 1 ? vector2s
.size() - 1 : currentIndex + 1;
v1 = vector2s.get(currentIndex);
v2 = vector2s.get(nextIndex);
}
float x = Math.abs(v1.x - v2.x);
float y = Math.abs(v1.y - v2.y);
float z = (float) MathUtil.distanceBetweenTwoPoints(v1, v2);
float moveX = 0f;
float moveY = 0f;
moveX = (x / z) * stepLength;
moveY = (y / z) * stepLength;
if (this.x < v2.x) {
this.x += moveX;
} else {
this.x -= moveX;
}
if (this.y < v2.y) {
this.y += moveY;
} else {
this.y -= moveY;
}
System.out.println("pos: " + this.x + "," + this.y + " v1:"
+ v1.toString() + " v2:" + v2.toString() + " d:" + z + " move:"
+ moveX + " , " + moveY);
super.act(delta);
}
}
文章中用到的地图文件和相关资源:http://www.ctdisk.com/file/4279808