【问题标题】:andengine smooth scrolling and zooming with SurfaceScrollDetector, PinchZoomDetectorandengine 使用 SurfaceScrollDetector、PinchZoomDetector 平滑滚动和缩放
【发布时间】:2013-05-15 16:07:05
【问题描述】:

我正在尝试使用 SurfaceScrollDetector 和 PinchZoomDetector 实现平滑的 TMX 地图滚动和缩放。

这是我的代码:

public class TMXTiledMapExample extends SimpleBaseGameActivity implements IOnSceneTouchListener, IScrollDetectorListener, IPinchZoomDetectorListener {

private static final int CAMERA_WIDTH = 480;
private static final int CAMERA_HEIGHT = 320;

private SmoothCamera camera;

private TMXTiledMap mTMXTiledMap;

private SurfaceScrollDetector mScrollDetector;
private PinchZoomDetector mPinchZoomDetector;
private float mPinchZoomStartedCameraZoomFactor;

@Override
public EngineOptions onCreateEngineOptions() {
    this.camera = new SmoothCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT, 400, 400, 10f);
    final CroppedResolutionPolicy canvasSurface = new CroppedResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT);
    EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, canvasSurface, this.camera);

    if (MultiTouch.isSupported(this)) {
        if (MultiTouch.isSupportedDistinct(this)) {
            Toast.makeText(this, "MultiTouch detected --> Both controls will work properly!", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "MultiTouch detected, but your device has problems distinguishing between fingers.\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG)
                    .show();
        }
    } else {
        Toast.makeText(this, "Sorry your device does NOT support MultiTouch!\n\n(Falling back to SingleTouch.)\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
    }

    return engineOptions;
}

@Override
public void onCreateResources() {
    BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
}

@Override
public Scene onCreateScene() {
    this.mEngine.registerUpdateHandler(new FPSLogger());

    final Scene scene = new Scene();
    scene.setOnAreaTouchTraversalFrontToBack();

    this.mScrollDetector = new SurfaceScrollDetector(this);
    this.mPinchZoomDetector = new PinchZoomDetector(this);

    scene.setOnSceneTouchListener(this);
    scene.setTouchAreaBindingOnActionDownEnabled(true);

    try {
        final TMXLoader tmxLoader = new TMXLoader(this.getAssets(), this.mEngine.getTextureManager(), TextureOptions.BILINEAR, this.getVertexBufferObjectManager(),
                new ITMXTilePropertiesListener() {
                    @Override
                    public void onTMXTileWithPropertiesCreated(final TMXTiledMap pTMXTiledMap, final TMXLayer pTMXLayer, final TMXTile pTMXTile,
                            final TMXProperties<TMXTileProperty> pTMXTileProperties) {
                    }
                });
        this.mTMXTiledMap = tmxLoader.loadFromAsset("tmx/desert2.tmx");

    } catch (final TMXLoadException e) {
        Debug.e(e);
    }

    final TMXLayer tmxLayer = this.mTMXTiledMap.getTMXLayers().get(0);
    scene.attachChild(tmxLayer);

    this.camera.setBounds(0, 0, tmxLayer.getHeight(), tmxLayer.getWidth());
    this.camera.setBoundsEnabled(true);

    return scene;
}

@Override
public void onScrollStarted(final ScrollDetector pScollDetector, final int pPointerID, final float pDistanceX, final float pDistanceY) {
    final float zoomFactor = this.camera.getZoomFactor();
    this.camera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY / zoomFactor);
}

@Override
public void onScroll(final ScrollDetector pScollDetector, final int pPointerID, final float pDistanceX, final float pDistanceY) {
    final float zoomFactor = this.camera.getZoomFactor();
    this.camera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY / zoomFactor);
}

@Override
public void onScrollFinished(final ScrollDetector pScollDetector, final int pPointerID, final float pDistanceX, final float pDistanceY) {
    final float zoomFactor = this.camera.getZoomFactor();
    this.camera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY / zoomFactor);
}

@Override
public void onPinchZoomStarted(final PinchZoomDetector pPinchZoomDetector, final TouchEvent pTouchEvent) {
    this.mPinchZoomStartedCameraZoomFactor = this.camera.getZoomFactor();
}

@Override
public void onPinchZoom(final PinchZoomDetector pPinchZoomDetector, final TouchEvent pTouchEvent, final float pZoomFactor) {
    this.camera.setZoomFactor(this.mPinchZoomStartedCameraZoomFactor * pZoomFactor);
}

@Override
public void onPinchZoomFinished(final PinchZoomDetector pPinchZoomDetector, final TouchEvent pTouchEvent, final float pZoomFactor) {
    this.camera.setZoomFactor(this.mPinchZoomStartedCameraZoomFactor * pZoomFactor);
}

@Override
public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
    this.mPinchZoomDetector.onTouchEvent(pSceneTouchEvent);

    if (this.mPinchZoomDetector.isZooming()) {
        this.mScrollDetector.setEnabled(false);
    } else {
        if (pSceneTouchEvent.isActionDown()) {
            this.mScrollDetector.setEnabled(true);
        }
        this.mScrollDetector.onTouchEvent(pSceneTouchEvent);
    }

    return true;
}
}

这段代码的滚动和缩放不是很流畅。它的问题在哪里?如何创建漂亮的惯性滚动?

关于缩放的另一个问题。如何用 min 和 max zoomfactor 限制它?我应该在 IPinchZoomDetectorListener 方法中放置一个特殊条件,还是可以通过提供给我的相机对象的一些参数来实现?

另外,最后三个 SmoothCamera 参数的“正常”值是多少 - 最终浮点 pMaxVelocityX、最终浮点 pMaxVelocityY、最终浮点 pMaxZoomFactorChange ?

【问题讨论】:

    标签: java android andengine


    【解决方案1】:

    我以前做过类似的工作,所以我可以帮助你实现你的目标。

    首先,如果您想要放大/缩小功能,那么您必须使用 ZoomCamera,其中您只需提供宽度和高度,所有其他参数均使用默认值。

        mZoomCamera = new ZoomCamera(0, 0, Constants.CAMERA_WIDTH,
                Constants.CAMERA_HEIGHT);
        mZoomCamera.setBounds(0f, 0f, Constants.CAMERA_WIDTH,
                Constants.CAMERA_HEIGHT);
        mZoomCamera.setBoundsEnabled(true);
    

    在示例代码中,您会看到我如何为相机设置边界,因此相机不可能超出此范围。而且我还认为,由于您提供的速度不合适,您会出现异常行为。

    对于设置特定的缩放值,您可以使用以下代码,

    private void setCameraZoomFactor(float pZoomFactor) {
        newZoomFactor = mPinchZoomStartedCameraZoomFactor * pZoomFactor;
        if (newZoomFactor < 1f)
            newZoomFactor = 1f;
        if (newZoomFactor > 1.5f)
            newZoomFactor = 1.5f;
    
        mZoomCamera.setZoomFactor(newZoomFactor);
    }
    

    您必须在 onPinchZoom 方法中调用此方法。

    我想现在我已经回答了你所有的问题。

    【讨论】:

    • 感谢您的回答!还有一个问题——SmoothCamera 和 ZoomCamera 有什么区别。 SmoothCamera 扩展了 ZoomCamera。我应该使用哪一个?
    • 很高兴能为您提供帮助。对于平滑相机和变​​焦相机之间的区别,我必须知道,所以我不会误导你。根据我的建议,您必须使用变焦相机,因为您不必在此处提供任何速度值。所以不会有错位的可能。
    • SmoothCamera 和 ZoomCamera 的区别在于 SmoothCamera 在设置位置或缩放时会逐渐移动相机,而 ZoomCamera 是直接移动相机,没有过渡。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    • 2010-11-25
    • 2017-08-22
    • 1970-01-01
    • 2016-10-09
    • 2011-02-12
    相关资源
    最近更新 更多