LibGDX ক্যামেরাটি টাইলডম্যাপের সীমানার মধ্যে রাখে


9

আমার একটি সহজ টাইল্ডম্যাপ রয়েছে যা আমি জরিমানা করতে পারি। আমার আশেপাশে একটি খেলোয়াড় রয়েছে (বক্স 2 ডি সহ) এবং আমার ক্যামেরাটি প্লেয়ারটিকে চারপাশে অনুসরণ করে:

cam.position.set(
    player.position().x * Game.PPM + Game.V_WIDTH / 4,
    player.position().y * Game.PPM,
    0
);
cam.update();

তবে ক্যামেরাটি টাইলডম্যাপটি "অফ" করবে। আমি কীভাবে আমার ক্যামেরাটি টাইল্ডম্যাপে রাখতে পারি, তাই যখন আমি আমার মানচিত্রের প্রান্তের কাছাকাছি চলে যাই তখন ক্যামেরাটি স্ক্রোলিং বন্ধ করে দেয় এবং প্লেয়ার ক্যামেরার প্রান্তের দিকে চলে যায়?

উত্তর:


12

ঠিক আছে, সুতরাং আপনি এখানে দুটি আয়তক্ষেত্রের সাথে কাজ করছেন। এর অভ্যন্তরে একটি বৃহত্তর স্থিতিশীল এক (মানচিত্র) এবং একটি ছোট চলন্ত একটি (ক্যামেরা)। আপনি যা চান তা ছোট আয়তক্ষেত্রের সীমাটি বৃহত আয়তক্ষেত্রের অভ্যন্তরের সীমানার বাইরে না যেতে দেওয়া।

// These values likely need to be scaled according to your world coordinates.
// The left boundary of the map (x)
int mapLeft = 0;
// The right boundary of the map (x + width)
int mapRight = 0 + map.getWidth();
// The bottom boundary of the map (y)
int mapBottom = 0;
// The top boundary of the map (y + height)
int mapTop = 0 + map.getHeight();
// The camera dimensions, halved
float cameraHalfWidth = cam.viewportWidth * .5f;
float cameraHalfHeight = cam.viewportHeight * .5f;

// Move camera after player as normal

float cameraLeft = cam.position.x - cameraHalfWidth;
float cameraRight = cam.position.x + cameraHalfWidth;
float cameraBottom = cam.position.y - cameraHalfHeight;
float cameraTop = cam.position.y + cameraHalfHeight;

// Horizontal axis
if(map.getWidth() < cam.viewportWidth)
{
    cam.position.x = mapRight / 2;
}
else if(cameraLeft <= mapLeft)
{
    cam.position.x = mapLeft + cameraHalfWidth;
}
else if(cameraRight >= mapRight)
{
    cam.position.x = mapRight - cameraHalfWidth;
}

// Vertical axis
if(map.getHeight() < cam.viewportHeight)
{
    cam.position.y = mapTop / 2;
}
else if(cameraBottom <= mapBottom)
{
    cam.position.y = mapBottom + cameraHalfHeight;
}
else if(cameraTop >= mapTop)
{
    cam.position.y = mapTop - cameraHalfHeight;
}

সুতরাং যুক্তি বেশ সহজ। ছোট বক্সটি বড় বক্সের ভিতরে রাখুন। একবার আপনি এই ধারণাটি বুঝতে পারলে এই কোডটি ডাউন হয়ে যায়। আপনি যদি চান তবে এটি আপনার ক্যামেরার অবস্থান ট্র্যাকিংয়ের নেস্টেড মিনি / ম্যাক্স স্টেটমেন্টের একটি সিরিজেও স্থানান্তরিত করতে পারেন।


1
আমার আগে বিছানায় যাওয়া উচিত। আমার এটিকে বাস্তবায়িত করার মতো কিছু ছিল, কিন্তু এটি কাজ করতে পারা যায় না। তবে একটি দুর্দান্ত setPosition()পদ্ধতি কল করার পরিবর্তে এটি সীমাটি স্থির করে দেবে, আমি তখনও ক্যামের অবস্থানটি সরাসরি সেট করেছিলাম (উদাহরণস্বরূপ cam.position.set()) এটি একটি কবজির মতো কাজ করে! ব্যাখ্যার জন্য ধন্যবাদ!
অ্যারিজান

7

আপনি সহজেই এর মতো মানচিত্রের সীমানায় ক্যামেরার অবস্থানটি ক্ল্যাম্প করতে পারেন:

camera.position.x = MathUtils.clamp(camera.position.x, camViewportHalfX, mapWidth - camViewportHalfX);
camera.position.y = MathUtils.clamp(camera.position.y, camViewportHalfY, mapHeight - camViewportHalfY);

কি camViewportHalfXএবং camViewportHalfY?
সাইফার

@ সাইফার: এটি ভিউপোর্ট এক্স এবং ওয়াই অক্ষের আকারের অর্ধেক।
ম্যাথিয়াস

তাহলে camViewportHalfXসমান হবে camera.viewportWidth / 2?
সাইফার

0

সীমাতে সরানোর Cameraজন্য TiledMap, OrthogonalTiledMapRendererব্যবহৃত হয়েছিল।

আমি এটিও লক্ষ্য করেছি যে এটি অপ্রত্যাশিতভাবে আচরণ করে: Cameraমানচিত্রের সীমানায় পৌঁছে, টাইলড মানচিত্র যেমন জড়তার দ্বারা কিছু পিক্সেলকে অনেক দূরে সরিয়ে দেয় (এটি সোয়াইপের বেগের উপর নির্ভর করে)।

সমাধান হিসাবে , প্রতিটি Cameraআন্দোলনের উপর , Cameraজোর করে মানচিত্রের সীমানায় রাখা হয়। putInMapBounds()পদ্ধতি দেখুন ।

TiledMapরেন্ডারিংয়ে গ্লিটস এড়াতে , ব্যবহৃত Math.min(float, float)

এই শ্রোতা আপনার পরিচালনা করতে ব্যবহার করুন Camera:

/**
 * @author Gram <gram7gram@gmail.com>
 */
public class CameraListener extends InputAdapter {

    private final UIStage stage;
    private final Camera camera;
    private final Vector3 curr;
    private final Vector3 last;
    private final Vector3 delta;
    private final int mapWidth;
    private final int mapHeight;

    public CameraListener(UIStage stage) {
        this.stage = stage;
        this.camera = stage.getViewport().getCamera();

        curr = new Vector3();
        last = new Vector3(-1, -1, -1);
        delta = new Vector3();

        TiledMapTileLayer layer = stage.getLevel().getMap().getFirstLayer();
        mapWidth = layer.getWidth() * DDGame.TILE_HEIGHT;
        mapHeight = layer.getHeight() * DDGame.TILE_HEIGHT;
    }

    @Override
    public boolean touchDragged(int x, int y, int pointer) {

        camera.unproject(curr.set(x, y, 0));

        if (!(last.x == -1 && last.y == -1 && last.z == -1)) {
            camera.unproject(delta.set(last.x, last.y, 0));
            delta.sub(curr);
            camera.translate(Math.min(delta.x, 5), Math.min(delta.y, 5), 0);
            if (isInMapBounds()) {
                stage.moveBy(Math.min(delta.x, 5), Math.min(delta.y, 5));
            }
        }

        last.set(x, y, 0);

        putInMapBounds();

        return false;
    }


    private boolean isInMapBounds() {

        return camera.position.x >= camera.viewportWidth / 2f
                && camera.position.x <= mapWidth - camera.viewportWidth / 2f
                && camera.position.y >= camera.viewportHeight / 2f
                && camera.position.y <= mapHeight - camera.viewportHeight / 2f;

    }

    private void putInMapBounds() {

        if (camera.position.x < camera.viewportWidth / 2f)
            camera.position.x = camera.viewportWidth / 2f;
        else if (camera.position.x > mapWidth - camera.viewportWidth / 2f)
            camera.position.x = mapWidth - camera.viewportWidth / 2f;

        if (camera.position.y < camera.viewportHeight / 2f)
            camera.position.y = camera.viewportHeight / 2f;
        else if (camera.position.y > mapHeight - camera.viewportHeight / 2f)
            camera.position.y = mapHeight - camera.viewportHeight / 2f;

        stage.moveTo(
                camera.position.x,
                camera.position.y);

    }

    @Override
    public boolean touchUp(int x, int y, int pointer, int button) {
        last.set(-1, -1, -1);
        Log.info("Camera at " + camera.position.x + ":" + camera.position.y);
        return false;
    }
}

0

আপনার যদি যত্ন নিতে জুম ফ্যাক্টর থাকে তবে আমি এটি আরও ভালভাবে কাজ করতে দেখতে পেয়েছি:

public void fixBounds() {
    float scaledViewportWidthHalfExtent = viewportWidth * zoom * 0.5f;
    float scaledViewportHeightHalfExtent = viewportHeight * zoom * 0.5f;

    // Horizontal
    if (position.x < scaledViewportWidthHalfExtent)
        position.x = scaledViewportWidthHalfExtent;
    else if (position.x > xmax - scaledViewportWidthHalfExtent)
        position.x = xmax - scaledViewportWidthHalfExtent;

    // Vertical
    if (position.y < scaledViewportHeightHalfExtent)
        position.y = scaledViewportHeightHalfExtent;
    else if (position.y > ymax - scaledViewportHeightHalfExtent)
        position.y = ymax - scaledViewportHeightHalfExtent;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.