33.手势识别

标签: android开发it | 分类: libGDX开发教程 |
1.GestureListener 类
我们做章节选择这个界面的时候,第一个难点就是要解决就是屏幕的
手势识别
,那么如何解决这个问题呢?其实libgdx已经给我们提供了很好的方法,这就是
GestureDetector.GestureListener
,这个其实就是libgdx自做的
手势识别器
,他可以检测出你当前对屏幕做的操作类型,包括6种操作:
翻页
、拖拽、长按、捏、zoom(手指放大)、按下、快速点击
。下面我们就来详细的讲解下,手势识别器是如何使用的。
API定义:这个类是GestureDetector的一个监听,他负责监听
触屏手势 如:
翻页
、拖拽、长按、捏、zoom(手指放大)、按下
、快速点击。每个方法返回一个布尔类型,不同的手势识别还会伴随其他几个状态的响应。
功能方法:
(1)fling(float velocityX, float velocityY, int button)
(2)longPress(float x, float y)
(4)
pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2)
我们在捏的动作中需要2个手指来做这个动作,我们定义其中一个手指为“起始手指”,另外一个手指为“第二手指”,来进行区分。
(6)
touchDown
(float x, float y, int count, int button)
如图:
(5)tap:“快速点击”的动作。
如图:
3.SelectScreen 类
上一篇博文,我们讲解了“保卫萝卜”的游戏入口、开始界面、加载界面的内容那么今天我们接着讲解SelectctScreen类---- 章节选择界面。本博文之前的讲解的手势识别器,也是为了这个界面做的只是铺垫,为了方便大家理解,这里就给大家先讲解了。
(1)游戏中固定常量设置。
在游戏中,我们要适应不同的分辨率的手机,那么我们就不能像以前的那样,将坐标写死,那么我们要使用什么办法来实现这个功能呢?我们可以通过让系统自动获取长宽,然后在游戏中凡事要使用坐标的地方都用自动获取的游戏宽高的比例来实现,这样就可以使用不同的设备。
如图:
如图:
(3)游戏中基本成员的初始化。
如图:

(4)章节图片处理,这里我采用了一个技巧,我将所需的5张图片,分别命名为“1.png”“2.png”“3.png”“4.png”“5.png”,这样就可以再使用TextureAltas寻找的时候建立循环。
如图:
如图:
(6)将一个三维向量,赋值为我们游戏舞台相机的位置向量。
如图:
如图:
(8)游戏章节图片回滚。这个内容我们在“保卫萝卜(三)”中详细学习,其中有很多原理,比较复杂,这里由于篇幅的关系,暂时不讲。
4.完整代码
(1)SelectScreen类中代码。
package
com.
potato;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
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.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
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.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
;
public
class
selectScreen
implements
Screen,
GestureListener
{
//游戏舞台的基本宽高
public
static
float
GAMESTAGE_WIDTH;
public
static
float
GAMESTAGE_HEIGHT;
//游戏中选择游戏章节中,章节图标的基本宽高和摆放间隔,以及每张图片回滚速度、相机的X坐标的变化间隔
public
static
float
CHAPTER_WIDTH;
public
static
float
CHAPTER_HEIGHT;
public
static
float
CHAPTER_INTERVAL;
public
static
float
CHAPTER_ROLLBACKSPEED;
float
disRollBack;
float
touch_X;
float
touch_Y;
float
touchBaseX;
float
touchBaseY;
float
baseOffset;
float
SELECT_STATE
;
float
SELECT_CHAPTER_FIRST
;
float
SELECT_CHAPTER_SECOND;
float
SELECT_CHAPTER_THIRD;
float
SELECT_CHAPTER_FOURTH;
float
SELECT_CHAPTER_FIFTH;
boolean
isRollbackIng;
boolean
isTouching;
SpriteBatch
batch;
//处理使用图片打包工具打包的图片所需变量。
TextureAtlas
pager;
TextureRegion[]
pages;
Texture
texture;
Image[]
images;
Stage
stage;
MyGame
game;
Sound
sound;
Sound
soundSelect;
Vector3
beforCameraPos;
public
selectScreen(MyGame
game)
{
this.
game
=
game;
}
@Override
public
void
show()
{
GAMESTAGE_WIDTH
=
Gdx.
graphics.
getWidth();
GAMESTAGE_HEIGHT
=
Gdx.
graphics.
getHeight();
CHAPTER_WIDTH
=
GAMESTAGE_WIDTH
*
0.625f;
CHAPTER_HEIGHT
=
GAMESTAGE_HEIGHT
*
0.7f;
CHAPTER_INTERVAL
=
GAMESTAGE_WIDTH
*
0.375f;
CHAPTER_ROLLBACKSPEED
=
GAMESTAGE_WIDTH
/
50;
batch
=
new
SpriteBatch();
texture
=
new
Texture(Gdx.
files.
internal(
"data/bg.png"));
sound
=
Gdx.
audio.
newSound(Gdx.
files.
internal(
"data/MenuSelect.ogg"));
soundSelect
=
Gdx.
audio.
newSound(Gdx.
files.
internal(
"data/Select.ogg"));
stage
=
new
Stage(GAMESTAGE_WIDTH,
GAMESTAGE_HEIGHT,
false);
Gdx.
input.
setInputProcessor(
new
GestureDetector(
this));
pages
=
new
TextureRegion[
5];
images
=
new
Image[
5];
pager
=
new
TextureAtlas(Gdx.
files.
internal(
"data/potato.pack"));
//设置基准偏移量
baseOffset
=
(GAMESTAGE_WIDTH
-
CHAPTER_WIDTH)
/
2;
float
offset
=
baseOffset;
for
(
int
i
=
0;
i
<
pages.
length;
i++)
{
//通过名字,找到用texturePacker处理的图片
pages[i]
=
pager.
findRegion((i
+
1)
+
"");
//将对应名字的图片赋给images数组中对象的成员
images[i]
=
new
Image(pages[i]);
//设置image的大小和位置。
images[i].
setSize(GAMESTAGE_WIDTH,
GAMESTAGE_HEIGHT);
images[i].
setPosition(offset,-(GAMESTAGE_HEIGHT
-
CHAPTER_HEIGHT)
/
2);
//这个offset是每次都加一个“章节间隔距离,出去章节图片的宽度游戏剩下的距离 ”
offset
+=
CHAPTER_INTERVAL
+
GAMESTAGE_WIDTH
-
CHAPTER_WIDTH;
//将image加入舞台。
stage.
addActor(images[i]);
}
beforCameraPos
=
new
Vector3(stage.
getCamera().
position);
}
public
void
update()
{
// justTouched 是开始按下手指的第一个点。
if
(Gdx.
input.
justTouched()
&&
isTouching
==
false)
{
isTouching
=
true;
touchBaseX
=
Gdx.
input.
getX(
0);
touchBaseY
=
Gdx.
input.
getY(
0);
touchBaseX
+=
stage.
getCamera().
position.
x
-
GAMESTAGE_WIDTH
/
2;
// isTouched 是结束时,手指按下的点。
}
else
if
(Gdx.
input.
isTouched(
0)
&&
isTouching
==
true)
{
touch_X
=
Gdx.
input.
getX(
0);
touch_Y
=
Gdx.
input.
getY(
0);
// 滑动相机,相机的移动是和手指移动相反的,手指右滑,是为了看左面。
stage.
getCamera().
position.
set(touchBaseX
-
touch_X
+
beforCameraPos.
x,
beforCameraPos.
y,
beforCameraPos.
z);
}
else
{
isTouching
=
false;
if
(isRollbackIng
==
false)
{
rollBackPre();
}
else
{
rollBack();
}
}
}
private
void
rollBackPre()
{
float
camX
=
stage.
getCamera().
position.
x;
disRollBack
=
camX
-
(images[
0].
getX()
+
CHAPTER_WIDTH
/
2);
// 计算距离手指结束位置最近的章节图片是哪个
for
(
int
i
=
1;
i
<
images.
length;
i++)
{
float
temp
=
camX
-
(images[i].
getX()
+
CHAPTER_WIDTH
/
2);
if
(Math.
abs(temp)
<
Math.
abs(disRollBack))
{
disRollBack
=
temp;
}
}
isRollbackIng
=
true;
}
private
void
rollBack()
{
float
temDis
=
disRollBack
*
Gdx.
graphics.
getDeltaTime()
*
CHAPTER_ROLLBACKSPEED;
stage.
getCamera().
position.
x
-=
temDis;
disRollBack
-=
temDis;
if
(Math.
abs(disRollBack)
<
0.1)
{
stage.
getCamera().
position.
x
-=
disRollBack;
isRollbackIng
=
false;
}
}
@Override
public
void
render(
float
delta)
{
Gdx.
gl.
glClear(GL10.
GL_COLOR_BUFFER_BIT);
update();
batch.
begin();
batch.
draw(texture,
0,
0,
GAMESTAGE_WIDTH,
GAMESTAGE_HEIGHT);
batch.
end();
stage.
act();
stage.
draw();
}
@Override
public
void
resize(
int
width,
int
height)
{
// TODO Auto-generated method stub
}
@Override
public
void
hide()
{
// TODO Auto-generated method stub
}
@Override
public
void
pause()
{
// TODO Auto-generated method stub
}
@Override
public
void
resume()
{
// TODO Auto-generated method stub
}
@Override
public
void
dispose()
{
// TODO Auto-generated method stub
}
@Override
public
boolean
touchDown(
float
x,
float
y,
int
pointer,
int
button)
{
// TODO Auto-generated method stub
return
true;
}
@Override
public
boolean
tap(
float
x,
float
y,
int
count,
int
button)
{
soundSelect.
play(
15f);
//相机位置 ,以及选择状态的判定。
SELECT_STATE
=
stage.
getCamera().
position.
x;
SELECT_CHAPTER_FIRST
=
GAMESTAGE_WIDTH
*
0.5f;
SELECT_CHAPTER_SECOND
=
GAMESTAGE_WIDTH
*
1.25f;
SELECT_CHAPTER_THIRD
=
GAMESTAGE_WIDTH
*
2.0f;
SELECT_CHAPTER_FOURTH
=
GAMESTAGE_WIDTH
*
2.75f;
SELECT_CHAPTER_FIFTH
=
GAMESTAGE_WIDTH
*
3.5f;
if(SELECT_STATE
==
SELECT_CHAPTER_FIRST)
{
gameScreen.
CHAPTER_COUNT
=
1;
game.
setScreen(game.
gamescreen);
}
else
if
(SELECT_STATE
==
SELECT_CHAPTER_SECOND)
{
gameScreen.
CHAPTER_COUNT
=
2;
game.
setScreen(game.
gamescreen);
}
else
if
(SELECT_STATE
==
SELECT_CHAPTER_THIRD)
{
gameScreen.
CHAPTER_COUNT
=
3;
game.
setScreen(game.
gamescreen);
}
else
if
(SELECT_STATE
==
SELECT_CHAPTER_FOURTH)
{
gameScreen.
CHAPTER_COUNT
=
4;
game.
setScreen(game.
gamescreen);
}
else
if
(SELECT_STATE
==
SELECT_CHAPTER_FIFTH)
{
gameScreen.
CHAPTER_COUNT
=
5;
game.
setScreen(game.
gamescreen);
}
return
false;
}
@Override
public
boolean
longPress(
float
x,
float
y)
{
// TODO Auto-generated method stub
return
false;
}
@Override
public
boolean
fling(
float
velocityX,
float
velocityY,
int
button)
{
// TODO Auto-generated method stub
sound.
play(
15f);
return
false;
}
@Override
public
boolean
pan(
float
x,
float
y,
float
deltaX,
float
deltaY)
{
// TODO Auto-generated method stub
return
false;
}
@Override
public
boolean
zoom(
float
initialDistance,
float
distance)
{
// TODO Auto-generated method stub
return
false;
}
@Override
public
boolean
pinch(Vector2
initialPointer1,
Vector2
initialPointer2,
Vector2
pointer1,
Vector2
pointer2)
{
// TODO Auto-generated method stub
return
false;
}
}
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
;
public
}