我正在尝试创建一个游戏,需要为每个对象使用多个不同的输入侦听器(检测器)。我有一个名为“ Blocker”的类,它是在此处创建“块”形状的地方。在我的主要游戏屏幕类中,由于需要10个“积木”,我从Block类创建了一个由10个积木实例组成的数组。
我直接在Block类中实现了GestureDetector接口。
这是Block类:
public class Block implements GestureDetector.GestureListener {
GameScreen gameScreen;
Controller game;
public Body block;
float screenWidth;
Stack distance;
Stack time;
//Calculated speed to be used once block is released
public float speed;
//Becomes true when user starts panning
public boolean isPaning = false;
public boolean isReleased = false;
public boolean isActive = false;
//Tracks user drag location
public float panLocation;
//Becomes true when the user release block
public boolean released = false;
public Block(GameScreen gameScreen, Controller game){
this.gameScreen = gameScreen;
this.game = game;
distance = new Stack();
time = new Stack();
screenWidth = gameScreen.screenWidth;
//Creates block that stops balls
block = createBlock();
//Sets properties
setBlockProperties(block);
}
public Body createBlock(){
float tmp = (screenWidth - gameScreen.goalPostThickness);
float xPos = tmp/gameScreen.PPM;
Body bBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set(xPos, 0);
def.fixedRotation = true;
bBody = gameScreen.world.createBody(def);
return bBody;
}
//Sets radius, density, etc.
public void setBlockProperties(Body body){
float gbt = screenWidth / 75; //Goal post thickness
// Create a circle shape and set its radius to 6
PolygonShape square = new PolygonShape();
square.setAsBox(gameScreen.goalPostThickness/gameScreen.PPM, (gameScreen.goalWidth/2)/gameScreen.PPM);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = square;
fixtureDef.density = 3.5f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 0.6f; // Make it bounce a little bit
fixtureDef.filter.categoryBits = 0x0004;
fixtureDef.filter.maskBits = 0x0002;
// Create our fixture and attach it to the body
Fixture fixture = block.createFixture(fixtureDef);
square.dispose();
}
//EVERYTHING BELOW IS FOR USER INPUT
@Override
public boolean touchDown(float x, float y, int pointer, int button) {
return false;
}
@Override
public boolean tap(float x, float y, int count, int button) {
return false;
}
@Override
public boolean longPress(float x, float y) {
return false;
}
@Override
public boolean fling(float velocityX, float velocityY, int button) {
return false;
}
@Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
isPaning = true;
Vector3 input = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
long currentTime = System.currentTimeMillis();
double seconds = currentTime / 1000.0;
//Input is backwards (Y down) to camera so this swaps it
game.cam.unproject(input);
float meters = input.y / gameScreen.PPM;
distance.push(new Double(meters));
time.push(new Double(seconds));
setPanLocation(input.y);
//Incase pan stop is not triggered, speed is still calculated
if ((input.y / gameScreen.PPM) >= gameScreen.boundaryLocation){
isPaning = false;
speed = calculateSpeed(distance, time);
setCheckRelease(true);
}
return false;
}
@Override
public boolean panStop(float x, float y, int pointer, int button) {
isPaning = false;
Vector3 input = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
long currentTime = System.currentTimeMillis();
double seconds = currentTime / 1000.0;
//Input is backwards (Y down) to camera so this swaps it
game.cam.unproject(input);
float meters = input.y / gameScreen.PPM;
distance.push(new Double (meters));
time.push(new Double (seconds));
speed = calculateSpeed(distance, time);
//System.out.println("Calculated speed: " + speed );
//System.out.println("Stop time: " + meters);
setCheckRelease(true);
return false;
}
@Override
public boolean zoom(float initialDistance, float distance) {
return false;
}
@Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
return false;
}
@Override
public void pinchStop() {
}
public void setPanLocation(float v){
panLocation = v;
}
public float getPanLocation(){
return panLocation;
}
public void setCheckRelease(boolean check){
released = check;
}
public boolean getCheckRelease(){
return released;
}
//Calculates speed from the drag time and distance
public float calculateSpeed(Stack distance, Stack time){
boolean checkDifference = false;
int popCount = 0;
double tmpDis = 0;
double tmpTime = 0;
double endDistance = (Double) distance.pop();
double endTime = (Double) time.pop();
//pop elements until there can be a calculated difference
//between start and end time/distance
while (!checkDifference) {
tmpDis = (Double) distance.pop();
tmpTime = (Double) time.pop();
if (tmpDis != endDistance && tmpTime != endTime){
checkDifference = true;
}
popCount++;
}
//System.out.println("Pop count: " + popCount);
double startDistance = tmpDis;
double startTime = tmpTime;
double finalDistance = endDistance - startDistance;
double finalTime = endTime - startTime;
// System.out.println("START DISTANCE: " + startDistance);
// System.out.println("START TIME: " + startTime);
// System.out.println("END DISTANCE: " + endDistance);
// System.out.println("END TIME: " + endTime);
// System.out.println("FINAL DISTANCE: " + finalDistance);
// System.out.println("FINAL TIME: " + finalTime);
double speed = (finalDistance/finalTime);
float tmp = (float) speed;
//System.out.println("DOUBLE SPEED: " + speed);
return tmp;
}
}
我正在游戏屏幕类中使用inputMultiplexer尝试创建多个输入侦听器:
multiplexer = new InputMultiplexer();
for (int i = 0; i < 10 ; i++) {
blockObj[i] = new Block(this, game);
multiplexer.addProcessor(new GestureDetector(blockObj[i]));
}
我正在使用isActive变量来设置当前正在使用的块。但是,即使此方法可行,只要下一个块变为活动状态,它就会从先前的块中获取信息,例如拖动位置。
答案 0 :(得分:0)
其他模块从其他模块等接收触摸事件的原因是由于您的设计方式。目前,对于您的设计,我无法想到解决此问题的合理方法。
但是,我认为只要稍加重构,就可以得到想要的东西。首先,我建议您研究scenes。您的Block
类应扩展Actor
。
通过这样做,我们可以将Block与舞台一起使用,并用它做许多更复杂的事情。您绝对应该看一下actor中的hit()
方法。您将需要重写该方法,以便“块”可以处理触摸事件。
如果您查看我上面链接的Scenes2d教程的“其他侦听器”部分,则可以看到它支持ActorGestureListener
。
这可能需要大量的重构,我不能保证这是最好的解决方案,因为我看不到您的所有代码,也不知道您要做什么,但是当前的问题是什么设置是所有块在触摸屏幕时都会接收事件,而不仅仅是实际触摸到的块。
答案 1 :(得分:0)
将BLOCK类扩展为Actor将使您可以在主代码中附加侦听器。然后,您可以使用:
for(Block block : blockobj)
{
block.addListener(new InputListener(){
//You can add different listeners like ActorGestureListener etc...
// press Ctrl + O while the cursor is inside this block to override methods.
});
}