LibGDX में विभिन्न पहलू अनुपात से कैसे निपटें?


81

मैंने libGDX का उपयोग करके कुछ स्क्रीन लागू की हैं जो स्पष्ट रूप Screenसे libGDX फ्रेमवर्क द्वारा प्रदान की गई कक्षा का उपयोग करेंगी। हालाँकि, इन स्क्रीन के लिए कार्यान्वयन केवल पूर्व-परिभाषित स्क्रीन आकारों के साथ काम करता है। उदाहरण के लिए, यदि स्प्राइट 640 x 480 आकार की स्क्रीन (4: 3 एस्पेक्ट रेश्यो) के लिए होता है, तो यह अन्य स्क्रीन आकारों के अनुसार काम नहीं करेगा क्योंकि स्प्राइट स्क्रीन की सीमाओं के बराबर होते हैं और स्क्रीन के आकार के अनुसार नहीं होते हैं बिल्कुल भी। इसके अलावा, अगर साधारण स्केलिंग libGDX द्वारा प्रदान की गई होती, तो मैं जिस मुद्दे का सामना कर रहा हूं, वह अभी भी होता, क्योंकि इससे गेम स्क्रीन का पहलू अनुपात बदल जाता।

इंटरनेट पर शोध करने के बाद, मैं एक ब्लॉग / फोरम पर आया, जिसने उसी मुद्दे पर चर्चा की। मैंने इसे लागू किया है और अब तक यह ठीक चल रहा है। लेकिन मैं यह पुष्टि करना चाहता हूं कि क्या यह हासिल करने का सबसे अच्छा विकल्प है या क्या बेहतर विकल्प हैं। नीचे यह दिखाने के लिए कोड है कि मैं इस वैध समस्या से कैसे निपट रहा हूं।

फोरम लिंक: http://www.java-gaming.org/index.php?topic=25685.new

public class SplashScreen implements Screen {

    // Aspect Ratio maintenance
    private static final int VIRTUAL_WIDTH = 640;
    private static final int VIRTUAL_HEIGHT = 480;
    private static final float ASPECT_RATIO = (float) VIRTUAL_WIDTH / (float) VIRTUAL_HEIGHT;

    private Camera camera;
    private Rectangle viewport;
    // ------end------

    MainGame TempMainGame;

    public Texture splashScreen;
    public TextureRegion splashScreenRegion;
    public SpriteBatch splashScreenSprite;

    public SplashScreen(MainGame maingame) {
        TempMainGame = maingame;
    }

    @Override
    public void dispose() {
        splashScreenSprite.dispose();
        splashScreen.dispose();
    }

    @Override
    public void render(float arg0) {
        //----Aspect Ratio maintenance

        // update camera
        camera.update();
        camera.apply(Gdx.gl10);

        // set viewport
        Gdx.gl.glViewport((int) viewport.x, (int) viewport.y,
        (int) viewport.width, (int) viewport.height);

        // clear previous frame
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        // DRAW EVERYTHING
        //--maintenance end--

        splashScreenSprite.begin();
        splashScreenSprite.disableBlending();
        splashScreenSprite.draw(splashScreenRegion, 0, 0);
        splashScreenSprite.end();
    }

    @Override
    public void resize(int width, int height) {
        //--Aspect Ratio Maintenance--
        // calculate new viewport
        float aspectRatio = (float)width/(float)height;
        float scale = 1f;
        Vector2 crop = new Vector2(0f, 0f);

        if(aspectRatio > ASPECT_RATIO) {
            scale = (float) height / (float) VIRTUAL_HEIGHT;
            crop.x = (width - VIRTUAL_WIDTH * scale) / 2f;
        } else if(aspectRatio < ASPECT_RATIO) {
            scale = (float) width / (float) VIRTUAL_WIDTH;
            crop.y = (height - VIRTUAL_HEIGHT * scale) / 2f;
        } else {
            scale = (float) width / (float) VIRTUAL_WIDTH;
        }

        float w = (float) VIRTUAL_WIDTH * scale;
        float h = (float) VIRTUAL_HEIGHT * scale;
        viewport = new Rectangle(crop.x, crop.y, w, h);
        //Maintenance ends here--
    }

    @Override
    public void show() {
        camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT); //Aspect Ratio Maintenance

        splashScreen = new Texture(Gdx.files.internal("images/splashScreen.png"));
        splashScreenRegion = new TextureRegion(splashScreen, 0, 0, 640, 480);
        splashScreenSprite = new SpriteBatch();

        if(Assets.load()) {
            this.dispose();
            TempMainGame.setScreen(TempMainGame.mainmenu);
        }
    }
}

अद्यतन: मुझे हाल ही में पता चला है कि पहलू अनुपात को बनाए रखने के लिए libGDX की अपनी कुछ कार्यक्षमता है, जिसके बारे में मैं यहां चर्चा करना चाहूंगा। इंटरनेट भर में पहलू अनुपात के मुद्दे की खोज करते समय, मुझे कई मंचों / डेवलपर्स के बारे में पता चला, जिनके पास "विभिन्न स्क्रीन आकारों पर पहलू अनुपात को बनाए रखने की समस्या" कैसे थी? मेरे लिए वास्तव में काम करने वाले समाधानों में से एक ऊपर पोस्ट किया गया था।

बाद में जब मैं touchDown()स्क्रीन के लिए तरीकों को लागू करने के साथ आगे बढ़ा , तो मैंने पाया कि आकार बदलने पर स्केलिंग के कारण, जिन समन्वयकों को मैंने लागू touchDown()किया था, वे एक बड़ी राशि से बदल जाएंगे। स्क्रीन रिसाइज के अनुसार को-ऑर्डिनेट्स का अनुवाद करने के लिए कुछ कोड के साथ काम करने के बाद, मैंने इस राशि को काफी हद तक कम कर दिया, लेकिन मैं उन्हें पिन पॉइंट सटीकता के साथ बनाए रखने में सफल नहीं रहा। उदाहरण के लिए, यदि मैंने touchDown()एक बनावट पर लागू किया था, तो स्क्रीन का आकार परिवर्तन पर निर्भर करते हुए, स्क्रीन को टचस्क्रीनिस्ट्रेट पर दाएं या बाएं कुछ पिक्सेल को दाईं या बाईं ओर स्थानांतरित कर देगा।

बाद में मुझे पता चला कि पहलू अनुपात ( boolean stretch = false) को बनाए रखने के लिए मंच की अपनी मूल कार्यक्षमता है । अब जब मैंने स्टेज स्क्रीन का उपयोग करके अपनी स्क्रीन को लागू किया है, तो पहलू अनुपात इसके द्वारा अच्छी तरह से बनाए रखा गया है। हालाँकि आकार या अलग-अलग स्क्रीन आकारों पर, उत्पन्न होने वाला काला क्षेत्र हमेशा स्क्रीन के दाईं ओर दिखाई देता है; यही कारण है कि स्क्रीन केंद्रित नहीं है, जो कि यदि काला क्षेत्र काफी बड़ा है तो यह काफी बदसूरत है।

क्या कोई भी समुदाय सदस्य इस समस्या को हल करने में मेरी मदद कर सकता है?


क्या आप उस ब्लॉग या फोरम से जुड़ सकते हैं जिसमें एक ही मुद्दा था?
स्टीव ब्लैकवेल

@SteveBlackwell यहाँ लिंक है: java-gaming.org/index.php?topic=25685.new
Rafay

@SteveBlackwell कृपया अद्यतन प्रश्न देखें और देखें कि क्या आप इस पर मदद कर सकते हैं।
रफय

1
मैं स्टेज के बारे में बहुत ज्यादा नहीं जानता, लेकिन यहां देखकर ऐसा लगता है कि इसे ठीक किया जाना चाहिए था। डॉक्स केंद्रित के लिए बहुत ज्यादा मदद नहीं कर रहे हैं। हो सकता है कि आप कैमरे को थोड़ा आगे बढ़ा सकते हैं या व्यूपोर्ट को समायोजित कर सकते हैं।
स्टीव ब्लैकवेल

1
खैर मेरा मुद्दा वास्तव में हल हो गया। मैं इसे उत्तर के रूप में पोस्ट कर रहा हूं।
राफे

जवाबों:


51

आजकल यह कैसे करना है:

चूंकि यह यहाँ libgdx पर सबसे प्रसिद्ध प्रश्नों में से एक है, इसलिए मैं इसे थोड़ा अपडेट करूँगा :

LibGDX v1.0 ने Viewportइस समस्या को संभालने के लिए शुरुआत की । इसका उपयोग करना बहुत आसान है और स्केलिंग रणनीति प्लग करने योग्य है, जिसका अर्थ है कि एक एकल लाइन व्यवहार को बदल सकती है और आप इसके साथ खेल सकते हैं और देख सकते हैं कि कौन सा आपके गेम को सबसे अच्छा लगता है।

इसके बारे में आपको जो कुछ भी जानने की जरूरत है वह यहां मिल सकती है


मैंने इसकी कोशिश की है लेकिन अभी भी मेरे TextureRegionस्ट्रेचेस हैं। यदि reszie(int width, int height)फ़ंक्शन को खाली छोड़ दें । यह सही TextureRegionनहीं है।
मुहम्मद बाबर

लेकिन व्यूपोर्ट्स का उपयोग करते समय भी हमें अलग-अलग पहलू अनुपात के लिए अलग-अलग बनावट का उपयोग करना होगा, क्या हम नहीं? क्या उस पद्धति को सरल बनाने का कोई तर्क है? या ग्राफिक डिजाइनिंग को संकल्पों से स्वतंत्र रखकर किया जाना चाहिए?
वेर्डफ्लाब0

Viewports का उपयोग करने पर अच्छा ट्यूटोरियल: gamefromscratch.com/post/2014/12/09/…
ubzack

इस उत्तर को जोड़ना और टिप्पणियों में प्रश्नों का उत्तर देना, आप 16: 9 के लिए अपनी दुनिया को आकर्षित कर सकते हैं और 4: 3 में लोड करने में सक्षम होने के लिए अपनी बनावट को अधिक ऊंचाई दे सकते हैं। फिर, अपने व्यूपोर्ट को इंस्टैंट करते समय आप स्क्रीन के वास्तविक पहलू अनुपात की जांच कर सकते हैं और अपनी चौड़ाई को मानक रखते हुए आप अपने व्यूपोर्ट को एक ऊंचाई दे सकते हैं जो आपके द्वारा चलाए जा रहे पहलू अनुपात को फिट कर देगा। एक दोष यह है कि आपके पास 4: 3 के रिज़ॉल्यूशन पर बहुत अधिक "खाली" स्थान होगा, लेकिन अगर आपकी बनावट को संभाल सकता है, तो सब कुछ खींचा हुआ नहीं दिखाई देगा और खींचा नहीं जाएगा
क्लिटोस जी।

24

EDIT: libGDX विकसित हुआ है। सबसे अच्छा जवाब अब यह एक उपयोगकर्ता द्वारा दोपहर है। Viewportदस्तावेज़ के लिंक की जाँच करना सुनिश्चित करें

जैसा कि स्टीवब्लैक ने उस समस्या का लिंक पोस्ट किया था, जो स्टेज क्लास में रिपोर्ट की गई थी, मैं वहां सिर्फ यह पता लगाने के लिए गया था कि नवीनतम नाइटलाइट्स में इस मुद्दे (वास्तव में मेरा मुद्दा नहीं था) को हल कर दिया गया है।

जिस मुद्दे पर मैं चल रहा था, उसके लिए इंटरनेट पर यहां और वहां शोध करने के बाद, मुझे कोई समाधान नहीं मिला, इसलिए उस व्यक्ति से संपर्क करने का फैसला किया जिसने बग की सूचना दी। उसके बाद, उन्होंने मुझे libgdx मंचों पर जवाब दिया और मैं उनकी मदद करने के लिए उनका ऋणी हूं। लिंक यहां दिया गया है

यह कोड की एक एकल पंक्ति थी और आपको बस इतना करना है:

आकार में () मेथोंड:

stage.setViewport(640, 480, false);
stage.getCamera().position.set(640/2, 480/2, 0);

जहां 640 X 480 आपके TextureRegion का रिज़ॉल्यूशन है जो कि इच्छित पहलू अनुपात का वर्णन करता है। यदि आपका TextureRegion का आकार 320 X 240 था, तो दोनों तर्कों को चाल करने के लिए नए रिज़ॉल्यूशन में बदल दिया जाना चाहिए।

मूल व्यक्ति का प्रोफ़ाइल लिंक जिसने वास्तव में मेरे मुद्दे को हल किया


6
LibGDX 0.9.6 में, stage.setViewport (640, 480, गलत) पर्याप्त है क्योंकि इसमें पहले से ही stage.getCamera () .position.set (640/2, 480/2, 0) कॉल शामिल है;
एलेक्सिस पॉट्रोट

1
setViewportअब उपलब्ध नहीं में 3 मापदंडों के साथ!
मुहम्मद बाबर

मैंने उपयोगकर्ता द्वारा किसी के द्वारा पोस्ट किए गए उत्तर को बदल दिया है क्योंकि स्टीव ब्लैकवेल ने बताया क्योंकि यह नवीनतम और सही लगता है।
राफाय

7

स्क्रीन को फिट करने के लिए अपने पूरे दृश्य को विकृत करने की तुलना में बाएं / दाएं या ऊपर / नीचे काली पट्टियां बेहतर लगती हैं। यदि आप एक पहलू अनुपात को लक्षित करते हैं जो कि संभव सीमाओं के बीच में है (4: 3 शायद कम अंत है, 16: 9 शायद उच्च अंत है), तो अधिकांश उपकरणों के लिए सलाखों को छोटा रहना चाहिए। यह भी चलो आप स्क्रीन के अधिकांश का उपयोग बड़ी स्क्रीन पर भी करते हैं, और आपके पास पहले से ही उस आदमी का कोड है इसलिए यह बहुत आसान है। यह भी अच्छा होगा अगर यह सिर्फ libgdx में बनाया गया एक विकल्प था।

लेकिन, मुझे लगता है कि पूरी स्क्रीन का उपयोग करना सबसे अच्छा तरीका है। मैंने अभी तक ऐसा नहीं किया है, लेकिन यह वह दृष्टिकोण होगा जो मैं अपनी अगली परियोजना के लिए ले रहा हूं। विचार यह है कि अगर किसी के पास एक विस्तृत स्क्रीन है, तो उन्हें पक्षों पर अधिक देखना चाहिए। क्रिस प्रुइट ने अपनी एक वार्ता में ऐसा करने के बारे में बात की ( लिंक टू स्पॉट इन - वास्तव में, पूरी बात वास्तव में बहुत अच्छी है)। विचार ऊंचाई के पैमाने पर है, और फिर स्क्रीन को फिट करने के लिए अपने व्यूपोर्ट को पर्याप्त चौड़ा करें। ओपनजीएल को बाकी को प्रदर्शित करने का ध्यान रखना चाहिए। जिस तरह से वह करता है वह यहाँ है

Libgdx के लिए, हो सकता है कि मंच पर कैमरा ले जाकर दृश्य 2d के साथ ऐसा करने का एक आसान तरीका हो, लेकिन मैंने वास्तव में दृश्य 2d के साथ काम नहीं किया है। किसी भी स्थिति में, एवीडी का एक गुच्छा बनाने की तुलना में ऐप को मूल आकार बदलने योग्य विंडो के रूप में चलाना कई स्क्रीन आकारों का परीक्षण करने का एक बहुत आसान तरीका है।


"किसी भी स्थिति में, एवीडी का एक गुच्छा बनाने की तुलना में ऐप को मूल आकार बदलने योग्य विंडो के रूप में चलाना कई स्क्रीन आकारों का परीक्षण करने का एक बहुत आसान तरीका है।" ख़ूब कहा है। वास्तव में मैं इस घटना पर काम कर रहा हूं ताकि विभिन्न आकारों के बनावट के साथ विभिन्न स्क्रीन आकारों को लक्षित करने के बजाय अधिकतम संगतता सुनिश्चित कर सके।
रफय


3

ResolutionFileResolver वर्ग आप सबसे अच्छा समाधान करने के लिए फ़ाइल नाम को हल करने की अनुमति देता है। मेरा मानना ​​है कि अलग-अलग पहलू अनुपात के साथ काम करेगा, बशर्ते आपने उन पहलू अनुपातों के लिए स्प्राइट बनाया हो। AssetManagerTest में एक उदाहरण का उपयोग है ।


0

मैं उस विधि का प्रयोग http://blog.acamara.es/2012/02/05/keep-screen-aspect-ratio-with-different-resolutions-using-libgdx/ से कर रहा हूँ

मैंने इस फ़ंक्शन को बनाया है जो स्क्रीन पर उस बिंदु को लौटाता है, जिसे आप चाहते हैं कि खेल की स्थिति तक बढ़ा दिया गया है।

public Vector2 getScaledPos(float x, float y) {
    float yR = viewport.height / (y - viewport.y);
    y = CAMERA_HEIGHT / yR;

    float xR = viewport.width / (x - viewport.x);
    x = CAMERA_WIDTH / xR;

    return new Vector2(x, CAMERA_HEIGHT - y);
}

टचडाउन / अप / ड्रैग में इसका उपयोग करें और आप अपने गेम में टच की जांच कर सकते हैं।


यह कैमरे के अनप्रोजेक्ट विधि के समान लगता है। क्या यह वही काम करता है?
23

@milosmns यह उसी तरह से है जैसे मैं 1 साल पहले कर रहा था, अच्छा मुझे पता चला कि अकारण बात है .. अच्छा है जब आपका कैमरा हमेशा एक ही स्थिति में होता है ..
बोल्डिजार पॉल

0

यह कोड मेरे लिए नवीनतम अपडेट के साथ काम करता है: * ऑर्थोग्राफ़िकैमरा कैम है, इससे कोई फ़सल नहीं होती है, बस व्यूपोर्ट बदल जाता है इसलिए चौड़ाई अभी भी "वास्तविक विंडो / डिवाइस से कई गुना" बड़ी है

public void resize(int width, int height) {
    int newW = width, newH = height;
    if (cam.viewportWidth > width) {
        float scale = (float) cam.viewportWidth / (float) width;
        newW *= scale;
        newH *= scale;
    }

    // true here to flip the Y-axis
    cam.setToOrtho(true, newW, newH);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.