36.游戏背景移动(二)
2013-08-28 14:45阅读:
本文使用的libgdx是0.98版本,可能和最新版有一些不同地方。全文内容仅供参考。
上一次我们讲解了如何实现“雷电类”游戏的背景移动,我们是通过游戏滚屏的方式,通过衔接2个不同的图片,最终共实现游戏背景的移动。在不同类型的游戏中,需要有不同的游戏背景滚动方式来实现,那么今天我们就来学习下第二章类型的游戏背景移动,也就是我们所说的“超级玛丽”类的游戏背景移动。
Libgdx游戏引擎(1群):187378034
Libgdx游戏引擎(2群):148848483
Libgdx游戏引擎(3群): 79168470
视频教程
1.需求分析
今天我们要实现一个超级玛丽的游戏背景移动,这个相对比较简单,在之前的博文中,我就实现过一个《碰撞检测》的超级马里奥和TiledMao地图图块的碰撞的实现,今天相对比较简单。
(1)首先,实现超级马里奥的人物移动的动画。
(2)其次,实现人物移动过程中的游戏背景移动
。
(3)最后,实现人物移动的按钮的触屏监听。
2.游戏素材
1.游戏图片。
(人物动画、按钮素材)
(TiledMap的地图素材)
PS:这个游戏的素材,在之前的博文中都可以下载到,不过这个地图是后来在网上随便找的。毕竟只要是讲解原来,素材就不讲究那么精巧了。
3.算法实现
由于咱们这个例子是我的博文《碰撞检测》中的例子,所以这里就不做详细的介绍了,如果有有看不懂的同学,可以去我的博文《碰撞检测》中去详细的了解这个例子的内容,那么这里我就简单的介绍一下,实现我们这个例子的背景移动的部分代码。
1.更改马里奥的坐标,这个例子的是之前的,所以要修改y轴移动坐标,这里,要将带有碰撞检测的代码,修改为固定坐标。
如图:
2.更改2个照相机的position位置,2D横版游戏重要是处理stage和tiledmap这个2个相机的观察点和人物移动坐标的关系就好了,这里简单的做一个赋值,但是原理是一样的,这里只是给大家一个简单的思路。
如图:
3.舞台相机原理:不同的游戏元素,绘制是需要不同的相机,相机其实是一个投影矩形,根据不同的相机
可以实现,舞台和TiledMap的绘制。
如图:
4.完整代码
1.TiledMapTest类代码。
package
com.
potato;
import
com.badlogic.gdx.ApplicationListener;
import
com.badlogic.gdx.Gdx;
import
com.badlogic.gdx.graphics.GL10;
import
com.badlogic.gdx.graphics.OrthographicCamera;
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.scenes.scene2d.Stage;
public class TiledMapTest
implements ApplicationListener
{
public static
TiledMap
map;
TileAtlas
atlas;
TileMapRenderer
render;
OrthographicCamera
cam;
Stage
stage;
Mario
mario;
@Override
public void
create()
{
map
=
TiledLoader.
createMap(Gdx.
files.
internal(
'data/level1.tmx'));
atlas
=
new TileAtlas(map,
Gdx.
files.
internal(
'data/'));
render
=
new TileMapRenderer(map,
atlas,
10,
10);
cam
=
new
OrthographicCamera();
cam.
setToOrtho(
false,
800,
480);
stage
=
new Stage(
480,
320,
false);
mario
=
new Mario(
0,
0);
setMario();
stage.
addActor(mario);
stage.
addActor(mario.
buttonL);
stage.
addActor(mario.
buttonR);
Gdx.
input.
setInputProcessor(stage);
}
@Override
public void
dispose()
{
}
public void
setMario()
{
for
(TiledObjectGroup
group
:
map.
objectGroups)
{
for
(TiledObject
object
:
group.
objects)
{
if
(
'mario'.
equals(object.
name))
{
mario.
x =
object.
x;
mario.
y =
render.
getMapHeightUnits()
-
object.
y;
}
}
}
}
@Override
public void
render()
{
Gdx.
gl.
glClearColor(
0,
0,
0,
0);
Gdx.
gl.
glClear(GL10.
GL_COLOR_BUFFER_BIT);
cam.
position.
x =
mario.
x;
stage.
getCamera().
position.
x
=
mario.
x;
cam.
update();
System.
out.
println(
'TiledMap的相机是:
' +
cam.
position.
x);
System.
out.
println(
'stage
照相机是: '+
stage.
getCamera().
position.
x);
System.
out.
println(
'马里奥的x坐标是:
'+mario.
x);
render.
render(cam);
stage.
act();
stage.
draw();
}
@Override
public void
resize(
int width,
int height)
{
}
@Override
public void
pause()
{
}
@Override
public void
resume()
{
}
}
2.Mario类中代码。
package
com.
potato;
import
com.badlogic.gdx.Gdx;
import
com.badlogic.gdx.Input.Keys;
import
com.badlogic.gdx.graphics.GL10;
import
com.badlogic.gdx.graphics.Texture;
import
com.badlogic.gdx.graphics.g2d.Animation;
import
com.badlogic.gdx.graphics.g2d.SpriteBatch;
import
com.badlogic.gdx.graphics.g2d.TextureRegion;
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 Mario
extends Actor
{
public static
float x;
public static
float y;
public float
statetime;
Texture
texture;
TextureRegion
currentFrame;
ImageButton
buttonL;
ImageButton
buttonR;
Animation
aniRight;
Animation
aniLeft;
Animation
aniIdle;
STATE
state;
enum STATE
{
Left,
Right,
Idel
};
public Mario(
float
x,
float y)
{
this.
x
=
x;
this.
y
=
y;
this.
statetime =
0;
this.
show();
state
=
STATE.
Idel;
}
@Override
public void
act(
float delta)
{
statetime
+=
delta;
this.
update();
this.
check();
super.
act(delta);
}
@Override
public void
draw(SpriteBatch
batch,
float
parentAlpha)
{
batch.
draw(currentFrame,
x,
y);
}
public void
update()
{
// 能否像下走。
if
(Collision.
downEnable(
this.
x,
this.
y))
{
// this.y
-=6.5*statetime;
this.
y =
87;
}
// 能否像左走
if (state
==
STATE.
Left &&
Collision.
leftEnable(x,
y,
64,
64))
{
this.
x -=
1.5f;
}
if (state
==
STATE.
Right)
{
this.
x +=
1.5f;
}
}
public void
check()
{
if (state
==
STATE.
Left)
{
currentFrame
=
aniLeft.
getKeyFrame(statetime,
true);
}
else
if (state
==
STATE.
Right)
{
currentFrame
=
aniRight.
getKeyFrame(statetime,
true);
}
else
if (state
==
STATE.
Idel)
{
currentFrame
=
aniIdle.
getKeyFrame(statetime,
true);
}
}
public void
show()
{
texture
=
new
Texture(Gdx.
files.
internal(
'data/Mario.png'));
TextureRegion[][]
spilt
=
TextureRegion.
split(texture,
64,
64);
TextureRegion[][]
miror
=
TextureRegion.
split(texture,
64,
64);
for
(TextureRegion[]
region1
:
miror)
{
for
(TextureRegion
region2
:
region1)
{
region2.
flip(
true,
false);
}
}
// 右
TextureRegion[]
regionR
=
new
TextureRegion[
3];
regionR[
0]
=
spilt[
0][
1];
regionR[
1]
=
spilt[
0][
2];
regionR[
2]
=
spilt[
0][
0];
aniRight
=
new Animation(
0.1f,
regionR);
// 左
TextureRegion[]
regionL
=
new
TextureRegion[
3];
regionL[
0]
=
miror[
0][
1];
regionL[
1]
=
miror[
0][
2];
regionL[
2]
=
miror[
0][
0];
aniLeft
=
new Animation(
0.1f,
regionL);
// 空闲
TextureRegion[]
regionI
=
new
TextureRegion[
1];
regionI[
0]
=
spilt[
0][
0];
aniIdle
=
new Animation(
0.1f,
regionI);
buttonL
=
new ImageButton(
new
TextureRegionDrawable(spilt[
1][
0]),
new
TextureRegionDrawable(spilt[
1][
1]));
buttonR
=
new ImageButton(
new
TextureRegionDrawable(miror[
1][
0]),
new
TextureRegionDrawable(miror[
1][
1]));
buttonL.
setPosition(
20,
20);
buttonR.
setPosition(
100,
20);
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;
}
});
}
}
3.Colision类中代码。
package
com.
potato;
import
com.badlogic.gdx.graphics.g2d.tiled.TiledMap;
import
com.badlogic.gdx.math.MathUtils;
public class Collision
{
public static
int tile[][];
public static
TiledMap
map;
static{
map
=
TiledMapTest.
map;
tile
=
map.
layers.
get(
0).
tiles;
}
public static
boolean leftEnable
(
float x,
float
y,
float width,
float
height)
{
int m1
=
MathUtils.
ceilPositive((x)
/
map.
tileWidth);
//
int n1
=
tile.
length -
MathUtils.
ceilPositive((y)
/
map.
tileHeight);
int m7
=
MathUtils.
ceilPositive((x)
/
map.
tileWidth);
int n7
=
tile.
length
-
MathUtils.
ceilPositive((y
+
height
/
2)
/
map.
tileHeight);
int m8
=
MathUtils.
ceilPositive((x)
/
map.
tileWidth);
int n8
=
tile.
length
-
MathUtils.
ceilPositive((y
+
height)
/
map.
tileHeight);
if (tile[n1][m1
-
1]
!=
0
||
tile[n7][m7
-
1]
!=
0
||
tile[n8][m8
-
1]
!=
0)
{
return
false;
}
else
return
true;
}
public static
boolean downEnable(
float
x,
float y)
{
int m1
=
MathUtils.
ceilPositive((x
+
12)
/
map.
tileWidth);
int n1
=
tile.
length -
MathUtils.
ceilPositive((y
-
1)
/
map.
tileHeight);
int m2
=
MathUtils.
ceilPositive((x
+
24)
/
map.
tileWidth);
int n2
=
tile.
length -
MathUtils.
ceilPositive((y
-
1)
/
map.
tileHeight);
int m3
=
MathUtils.
ceilPositive((x
+
40)
/
map.
tileWidth);
int n3
=
tile.
length -
MathUtils.
ceilPositive((y
-
1)
/
map.
tileHeight);
if (tile[n3][m3
-
1]
!=
0
||
tile[n2][m2
-
1]
!=
0
||
tile[n1][m1
-
1]
!=
0)
{
return
false;
}
else
{
return
true;
}
}
}
效果图:
点击播放
源码下载:http://pan.baidu.com/share/link?shareid=2672238187&uk=3456175979
写在最后,关于libgdx中游戏背景移动,就暂时给大家介绍到这里,希望对大家有所帮助,下一篇是是关于libgdx框架中《Rectangle的使用》的博文,我会继续介绍Rectangle的使用。如果大家有什么问题可以加我QQ:316344618,一起讨论下。PS:请大家多多留言交流,大家的评论土豆都会看的,也欢迎大家来libgdx的中文论坛来发帖交流,土豆也是会给大家及时解答的。
------------奋斗小土豆丶
2013 年 8 月 28 日