我想要的是:当我触摸触摸板背景(不是旋钮)时,旋钮移动到此位置。代码,我用于github / libgdx / gdx / src / com / badlogic / gdx / scenes / scene2d / ui / Touchpad.java的触摸板
package com.liketurbo.funnyGame;
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
import com.badlogic.gdx.scenes.scene2d.Event;
import com.badlogic.gdx.scenes.scene2d.EventListener;
import com.badlogic.gdx.scenes.scene2d.ui.Widget;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Circle;
import com.badlogic.gdx.math.Vector2;
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.utils.ChangeListener.ChangeEvent;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.utils.Pools;
/** An on-screen joystick. The movement area of the joystick is circular, centered on the touchpad, and its size determined by the
* smaller touchpad dimension.
* <p>
* The preferred size of the touchpad is determined by the background.
* <p>
* {@link ChangeEvent} is fired when the touchpad knob is moved. Cancelling the event will move the knob to where it was
* previously.
* @author Josh Street */
public class Touchpad extends Widget {
private TouchpadStyle style;
boolean touched;
boolean resetOnTouchUp = true;
private float deadzoneRadius;
private final Circle knobBounds = new Circle(0, 0, 0);
private final Circle touchBounds = new Circle(0, 0, 0);
private final Circle deadzoneBounds = new Circle(0, 0, 0);
private final Vector2 knobPosition = new Vector2();
private final Vector2 knobPercent = new Vector2();
/** @param deadzoneRadius The distance in pixels from the center of the touchpad required for the knob to be moved. */
public Touchpad (float deadzoneRadius, Skin skin) {
this(deadzoneRadius, skin.get(TouchpadStyle.class));
}
/** @param deadzoneRadius The distance in pixels from the center of the touchpad required for the knob to be moved. */
public Touchpad (float deadzoneRadius, Skin skin, String styleName) {
this(deadzoneRadius, skin.get(styleName, TouchpadStyle.class));
}
/** @param deadzoneRadius The distance in pixels from the center of the touchpad required for the knob to be moved. */
public Touchpad (float deadzoneRadius, TouchpadStyle style) {
if (deadzoneRadius < 0) throw new IllegalArgumentException("deadzoneRadius must be > 0");
this.deadzoneRadius = deadzoneRadius;
knobPosition.set(getWidth() / 2f, getHeight() / 2f);
setStyle(style);
setSize(getPrefWidth(), getPrefHeight());
addListener(new InputListener() {
@Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
if (touched) return false;
touched = true;
calculatePositionAndValue(x, y, false);
return true;
}
@Override
public void touchDragged (InputEvent event, float x, float y, int pointer) {
calculatePositionAndValue(x, y, false);
}
@Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
touched = false;
calculatePositionAndValue(x, y, resetOnTouchUp);
}
});
}
void calculatePositionAndValue (float x, float y, boolean isTouchUp) {
float oldPositionX = knobPosition.x;
float oldPositionY = knobPosition.y;
float oldPercentX = knobPercent.x;
float oldPercentY = knobPercent.y;
float centerX = knobBounds.x;
float centerY = knobBounds.y;
y = centerY;
knobPosition.set(centerX, centerY);
knobPercent.set(0f, 0f);
if (!isTouchUp) {
if (!deadzoneBounds.contains(x, y)) {
knobPercent.set((x - centerX) / knobBounds.radius*3.5f, 0);
float length = knobPercent.len();
if (length > 1) knobPercent.scl(1 / length);
if (knobBounds.contains(x, y)) {
knobPosition.set(x, y);
} else {
knobPosition.set(knobPercent).nor().scl(knobBounds.radius*3.5f).add(knobBounds.x, knobBounds.y);
}
}
}
if (oldPercentX != knobPercent.x || oldPercentY != knobPercent.y) {
ChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);
if (fire(changeEvent)) {
knobPercent.set(oldPercentX, oldPercentY);
knobPosition.set(oldPositionX, oldPositionY);
}
Pools.free(changeEvent);
}
}
public void setStyle (TouchpadStyle style) {
if (style == null) throw new IllegalArgumentException("style cannot be null");
this.style = style;
invalidateHierarchy();
}
/** Returns the touchpad's style. Modifying the returned style may not have an effect until {@link #setStyle(TouchpadStyle)} is
* called. */
public TouchpadStyle getStyle () {
return style;
}
@Override
public Actor hit (float x, float y, boolean touchable) {
return touchBounds.contains(x, y) ? this : null;
}
@Override
public void layout () {
// Recalc pad and deadzone bounds
float halfWidth = getWidth() / 2;
float halfHeight = getHeight() / 2;
float radius = Math.min(halfWidth, halfHeight);
touchBounds.set(halfWidth, halfHeight, radius);
if (style.knob != null) radius -= Math.max(style.knob.getMinWidth(), style.knob.getMinHeight()) / 2;
knobBounds.set(halfWidth, halfHeight, radius);
deadzoneBounds.set(halfWidth, halfHeight, deadzoneRadius);
// Recalc pad values and knob position
knobPosition.set(halfWidth, halfHeight);
knobPercent.set(0, 0);
}
@Override
public void draw (Batch batch, float parentAlpha) {
validate();
Color c = getColor();
batch.setColor(c.r, c.g, c.b, c.a * parentAlpha);
float x = getX();
float y = getY();
float w = getWidth();
float h = getHeight();
final Drawable bg = style.background;
if (bg != null) bg.draw(batch, x, y, w, h);
final Drawable knob = style.knob;
if (knob != null) {
x += knobPosition.x - (knob.getMinWidth()*2) / 2f;
y += knobPosition.y - (knob.getMinHeight()*2) / 2f;
knob.draw(batch, x, y, knob.getMinWidth()*2, knob.getMinHeight()*2);
}
}
@Override
public float getPrefWidth () {
return style.background != null ? style.background.getMinWidth() : 0;
}
@Override
public float getPrefHeight () {
return style.background != null ? style.background.getMinHeight() : 0;
}
public boolean isTouched () {
return touched;
}
public boolean getResetOnTouchUp () {
return resetOnTouchUp;
}
/** @param reset Whether to reset the knob to the center on touch up. */
public void setResetOnTouchUp (boolean reset) {
this.resetOnTouchUp = reset;
}
/** @param deadzoneRadius The distance in pixels from the center of the touchpad required for the knob to be moved. */
public void setDeadzone (float deadzoneRadius) {
if (deadzoneRadius < 0) throw new IllegalArgumentException("deadzoneRadius must be > 0");
this.deadzoneRadius = deadzoneRadius;
invalidate();
}
/** Returns the x-position of the knob relative to the center of the widget. The positive direction is right. */
public float getKnobX () {
return knobPosition.x;
}
/** Returns the y-position of the knob relative to the center of the widget. The positive direction is up. */
public float getKnobY () {
return knobPosition.y;
}
/** Returns the x-position of the knob as a percentage from the center of the touchpad to the edge of the circular movement
* area. The positive direction is right. */
public float getKnobPercentX () {
return knobPercent.x;
}
/** Returns the y-position of the knob as a percentage from the center of the touchpad to the edge of the circular movement
* area. The positive direction is up. */
public float getKnobPercentY () {
return knobPercent.y;
}
/** The style for a {@link Touchpad}.
* @author Josh Street */
public static class TouchpadStyle {
/** Stretched in both directions. Optional. */
public Drawable background;
/** Optional. */
public Drawable knob;
public TouchpadStyle () {
}
public TouchpadStyle (Drawable background, Drawable knob) {
this.background = background;
this.knob = knob;
}
public TouchpadStyle (TouchpadStyle style) {
this.background = style.background;
this.knob = style.knob;
}
}
}
线addListener(new InputListener() {...}
仅适用于旋钮,如果我能弄清楚触控板的背景是如何工作的,它解决了我的问题。有人知道如何解决这个问题吗?提前谢谢。
答案 0 :(得分:1)
您不应该在触控板上添加侦听器。只需限制可以使用触摸板的屏幕触摸区域。
以下是仅在屏幕右半部分激活的代码:
private Touchpad touchpad;
private Vector2 screenPos = new Vector2(); // position where touch occurs
private Vector2 localPos = new Vector2(); // position in local coordinates
private InputEvent fakeTouchDownEvent = new InputEvent(); // fake touch for correct work
private Vector2 stagePos; // position to fire touch event
private void getDirection() {
if (Gdx.input.justTouched()) {
// Get the touch point in screen coordinates.
screenPos.set(Gdx.input.getX(), Gdx.input.getY());
if (screenPos.x > Gdx.graphics.getWidth() / 2) { // right half of a screen
// Convert the touch point into local coordinates, place the touchpad and show it.
localPos.set(screenPos);
localPos = touchpad.getParent().screenToLocalCoordinates(localPos);
touchpad.setPosition(localPos.x - touchpad.getWidth() / 2, localPos.y - touchpad.getHeight() / 2);
// Fire a touch down event to get the touchpad working.
Vector2 stagePos = touchpad.getStage().screenToStageCoordinates(screenPos);
fakeTouchDownEvent.setStageX(stagePos.x);
fakeTouchDownEvent.setStageY(stagePos.y);
touchpad.fire(fakeTouchDownEvent);
}
}
}