मैं एक 2 डी प्लेटफ़ॉर्मर में असमान दीवारों पर चरित्र कैसे बना सकता हूं?


11

मैं एक खेलने योग्य चरित्र रखना चाहता हूं, जो बग़ल में और ऊपर-नीचे सहित किसी भी कोण पर कार्बनिक सतह पर "चल" सकता है। 90 डिग्री के कोण पर सीधी रेखाओं के बजाय "कार्बनिक" स्तरों के साथ slanted और घुमावदार विशेषताओं के साथ।

मैं वर्तमान में AS3 (मध्यम शौकिया अनुभव) में काम कर रहा हूं और मूल गुरुत्वाकर्षण आधारित भौतिकी के लिए नपे (बहुत ज्यादा एक नौसिखिया) का उपयोग कर रहा हूं, जिसके लिए यह चलने वाला मैकेनिक एक स्पष्ट अपवाद होगा।

क्या इस तरह का वॉक मैकेनिक करने का एक प्रक्रियात्मक तरीका है, शायद नपे बाधाओं का उपयोग करना? या स्तर की सतहों के विपरीत चलने के बाद स्पष्ट चलना "पथ" बनाना सबसे अच्छा होगा और उनका उपयोग पैदल चलने की गति को बाधित करने के लिए किया जाएगा?


स्पष्ट करने के लिए: आप अपने स्तर पर अपने चरित्र को दीवारों और छत पर 'छड़ी' बनाने में सक्षम बनाना चाहते हैं?
Qqwy

यह सही है।
एरिक एन

जवाबों:


9

यहां मेरा पूरा सीखने का अनुभव है, जिसके परिणामस्वरूप मुझे नॉन के आंतरिक तरीकों का उपयोग करते हुए आंदोलन के एक बहुत ही कार्यात्मक संस्करण की आवश्यकता थी। यह सभी कोड मेरे स्पाइडर वर्ग के भीतर है, जो अपने माता-पिता से कुछ गुणों को खींचता है, एक स्तर वर्ग।

अन्य वर्गों और विधियों में से अधिकांश नपे पैकेज का हिस्सा हैं। यहाँ मेरी आयात सूची का उचित भाग है:

import flash.events.TimerEvent;
import flash.utils.Timer;

import nape.callbacks.CbEvent;
import nape.callbacks.CbType;
import nape.callbacks.InteractionCallback;
import nape.callbacks.InteractionListener;
import nape.callbacks.InteractionType;
import nape.callbacks.OptionType;
import nape.dynamics.Arbiter;
import nape.dynamics.ArbiterList;
import nape.geom.Geom;
import nape.geom.Vec2;

सबसे पहले, जब मकड़ी को मंच पर जोड़ा जाता है, तो मैं श्रोताओं को टकराव के लिए नपे दुनिया में जोड़ता हूं। जैसा कि मैं विकास में आगे हूं, मुझे टकराव समूहों को अलग करने की आवश्यकता होगी; इस समय, ये कॉलबैक तकनीकी रूप से चलाए जाएंगे जब कोई भी शरीर किसी अन्य शरीर से टकराता है।

        var opType:OptionType = new OptionType([CbType.ANY_BODY]);
        mass = body.mass;
        // Listen for collision with level, before, during, and after.
        var landDetect:InteractionListener =  new InteractionListener(CbEvent.BEGIN, InteractionType.COLLISION, opType, opType, spiderLand)
        var moveDetect:InteractionListener =  new InteractionListener(CbEvent.ONGOING, InteractionType.COLLISION, opType, opType, spiderMove);
        var toDetect:InteractionListener =  new InteractionListener(CbEvent.END, InteractionType.COLLISION, opType, opType, takeOff);

        Level(this.parent).world.listeners.add(landDetect);
        Level(this.parent).world.listeners.add(moveDetect);
        Level(this.parent).world.listeners.add(toDetect);

        /*
            A reference to the spider's parent level's master timer, which also drives the nape world,
            runs a callback within the spider class every frame.
        */
        Level(this.parent).nTimer.addEventListener(TimerEvent.TIMER, tick);

कॉलबैक में मकड़ी की "राज्य" संपत्ति बदल जाती है, जो कि बुलियन का एक सेट है, और मेरे चलने वाले तर्क में बाद में उपयोग के लिए किसी भी बाप टक्कर मध्यस्थ को रिकॉर्ड करता है। उन्होंने टिमीर को भी सेट और क्लियर कर दिया है, जो मकड़ी को विश्व गुरुत्वाकर्षण को फिर से पकड़ लेने की अनुमति देने से पहले 100 सेंटीमीटर तक की सतह के साथ संपर्क खोने की अनुमति देता है।

    protected function spiderLand(callBack:InteractionCallback):void {
        tArbiters = callBack.arbiters.copy();
        state.isGrounded = true;
        state.isMidair = false;
        body.gravMass = 0;
        toTimer.stop();
        toTimer.reset();
    }

    protected function spiderMove(callBack:InteractionCallback):void {
        tArbiters = callBack.arbiters.copy();
    }

    protected function takeOff(callBack:InteractionCallback):void {
        tArbiters.clear();
        toTimer.reset();
        toTimer.start();
    }

    protected function takeOffTimer(e:TimerEvent):void {
        state.isGrounded = false;
        state.isMidair = true;
        body.gravMass = mass;
        state.isMoving = false;
    }

अंत में, मैं गणना करता हूं कि मकड़ी को उसके राज्य और उसके स्तर ज्यामिति के संबंध के आधार पर क्या लागू करना है। मैं ज्यादातर टिप्पणियों को खुद के लिए बोलने देता हूँ।

    protected function tick(e:TimerEvent):void {
        if(state.isGrounded) {
            switch(tArbiters.length) {
                /*
                    If there are no arbiters (i.e. spider is in midair and toTimer hasn't expired),
                    aim the adhesion force at the nearest point on the level geometry.
                */
                case 0:
                    closestA = Vec2.get();
                    closestB = Vec2.get();
                    Geom.distanceBody(body, lvBody, closestA, closestB);
                    stickForce = closestA.sub(body.position, true);
                    break;
                // For one contact point, aim the adhesion force at that point.
                case 1:
                    stickForce = tArbiters.at(0).collisionArbiter.contacts.at(0).position.sub(body.position, true);
                    break;
                // For multiple contact points, add the vectors to find the average angle.
                default:
                    var taSum:Vec2 = tArbiters.at(0).collisionArbiter.contacts.at(0).position.sub(body.position, true);
                    tArbiters.copy().foreach(function(a:Arbiter):void {
                        if(taSum != a.collisionArbiter.contacts.at(0).position.sub(body.position, true))
                            taSum.addeq(a.collisionArbiter.contacts.at(0).position.sub(body.position, true));
                    });

                    stickForce=taSum.copy();
            }
            // Normalize stickForce's strength.
            stickForce.length = 1000;
            var curForce:Vec2 = new Vec2(stickForce.x, stickForce.y);

            // For graphical purposes, align the body (simulation-based rotation is disabled) with the adhesion force.
            body.rotation = stickForce.angle - Math.PI/2;

            body.applyImpulse(curForce);

            if(state.isMoving) {
                // Gives "movement force" a dummy value since (0,0) causes problems.
                mForce = new Vec2(10,10);
                mForce.length = 1000;

                // Dir is movement direction, a boolean. If true, the spider is moving left with respect to the surface; otherwise right.
                // Using the corrected "down" angle, move perpendicular to that angle
                if(dir) {
                    mForce.angle = correctAngle()+Math.PI/2;
                } else {
                    mForce.angle = correctAngle()-Math.PI/2;
                }
                // Flip the spider's graphic depending on direction.
                texture.scaleX = dir?-1:1;
                // Now apply the movement impulse and decrease speed if it goes over the max.
                body.applyImpulse(mForce);
                if(body.velocity.length > 1000) body.velocity.length = 1000;

            }
        }
    }

वास्तविक चिपचिपा हिस्सा मैंने पाया था कि आंदोलन के कोण को कई संपर्क बिंदु परिदृश्य में आंदोलन की वास्तविक वांछित दिशा में होना चाहिए जहां मकड़ी एक तेज कोण तक पहुंचती है या एक गहरी घाटी में बैठती है। विशेष रूप से तब से, आसंजन बल के लिए मेरे सुस्पष्ट वैक्टर को देखते हुए, वह बल AWAY को उस दिशा से खींच रहा होगा जिसे हम इसके बजाय लंबवत स्थानांतरित करना चाहते हैं, इसलिए हमें इसका मुकाबला करने की आवश्यकता है। इसलिए मुझे आंदोलन वेक्टर के कोण के आधार के रूप में उपयोग करने के लिए संपर्क बिंदुओं में से एक को लेने के लिए तर्क की आवश्यकता थी।

आसंजन बल के "पुल" का एक साइड इफेक्ट एक मामूली हिचकिचाहट है जब मकड़ी एक तेज अवतल कोण / वक्र तक पहुंचती है, लेकिन यह वास्तव में एक नज़र-और-महसूस दृष्टिकोण से यथार्थवादी है ताकि जब तक कि यह सड़क के नीचे की समस्याओं का कारण न हो। जैसा है वैसा ही छोड़ दो। अगर मुझे जरूरत है, तो मैं आसंजन बल की गणना करने के लिए इस पद्धति पर भिन्नता का उपयोग कर सकता हूं।

    protected function correctAngle():Number {
        var angle:Number;
        if(tArbiters.length < 2) {
            // If there is only one (or zero) contact point(s), the "corrected" angle doesn't change from stickForce's angle.
            angle = stickForce.angle;
        } else {
            /*
                For more than one contact point, we want to run perpendicular to the "new" down, so we copy all the
                contact point angles into an array...
            */
            var angArr:Array = [];
            tArbiters.copy().foreach(function(a:Arbiter):void {
                var curAng:Number = a.collisionArbiter.contacts.at(0).position.sub(body.position, true).angle;
                if (curAng < 0) curAng += Math.PI*2;
                angArr.push(curAng);
            });
            /*
                ...then we iterate through all those contact points' angles with respect to the spider's COM to figure out
                which one is more clockwise or more counterclockwise, depending, with some restrictions...
                ...Whatever, the correct one.
            */
            angle = angArr[0];
            for(var i:int = 1; i<angArr.length; i++) {
                if(dir) {
                    if(Math.abs(angArr[i]-angle) < Math.PI)
                        angle = Math.max(angle, angArr[i]);
                    else
                        angle = Math.min(angle, angArr[i]);
                }
                else {
                    if(Math.abs(angArr[i]-angle) < Math.PI)
                        angle = Math.min(angle, angArr[i]);
                    else
                        angle = Math.max(angle, angArr[i]);
                }
            }
        }

        return angle;
    }

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


1
अच्छा किया, भविष्य के आगंतुकों के लिए यहाँ विवरण पोस्ट करने के लिए धन्यवाद।
MichaelHouse

8

किसी भी "छड़ी" सतह को बनाने के बारे में कैसे एक चरित्र को छूता है सतह के व्युत्क्रम के साथ एक बल लागू होता है? जब तक वे सतह के संपर्क में रहते हैं तब तक बल बना रहता है और जब तक यह सक्रिय रहता है तब तक गुरुत्वाकर्षण पर हावी हो जाता है। तो छत से कूदने से फर्श पर गिरने का अपेक्षित प्रभाव होगा।

आप शायद इस काम को सुचारू रूप से करने के लिए कुछ अन्य सुविधाओं को लागू करना चाहते हैं और लागू करना आसान है। उदाहरण के लिए, इसके बजाय कि चरित्र क्या छूता है चरित्र के चारों ओर एक चक्र का उपयोग करें और उल्टे मानदंडों का योग करें। जैसा कि यह भद्दा पेंट छवि दिखाता है:

यहाँ छवि विवरण दर्ज करें

(मकड़ी समानता का प्रतिनिधित्व बाइट 56 की संपत्ति है)

नीले बिंदु उस बिंदु पर सतह पर उलटे मानदंड हैं। ग्रीन लाइन मकड़ी के लिए लागू की जा रही बल बल है। लाल वृत्त उस सीमा का प्रतिनिधित्व करता है जिस मकड़ी का उपयोग करने के लिए मानदंडों की तलाश है।

यह मकड़ी के बिना इलाके में कुछ ऊबड़ खाबड़ होने की अनुमति देगा "अपनी पकड़ खोना"। उस बात के लिए सर्कल के आकार और आकार पर प्रयोग, शायद मकड़ी के साथ एक आधा सर्कल उन्मुख का उपयोग करें, शायद सिर्फ एक आयत जो पैरों को घेर ले।

यह समाधान आपके लिए भौतिकी को चालू रखने की अनुमति देता है, चरित्र का अनुसरण करने वाले विशिष्ट रास्तों से निपटने की आवश्यकता के बिना। यह उन सूचनाओं का भी उपयोग कर रहा है जो प्राप्त करना और व्याख्या करना आसान है (मानदंड)। अंत में, यह गतिशील है। यहां तक ​​कि दुनिया के आकार को बदलना भी आसान है, क्योंकि आप जो भी रेखांकन कर रहे हैं, उसके लिए आप आसानी से मानदंड प्राप्त कर सकते हैं।

याद रखें कि जब कोई चेहरे मकड़ी की सीमा के भीतर नहीं होते हैं, तो सामान्य गुरुत्वाकर्षण पर कब्जा कर लेता है।


सम्‍मानित मानदंड संभवत: उन मुद्दों को हल करेंगे जो मेरे वर्तमान समाधान को तेज अवतल कोनों के साथ कर रहे हैं, लेकिन मैं आपको एएस 3 में कैसे मिलता है, इससे परिचित नहीं हूं।
एरिक एन

क्षमा करें, मैं परिचित नहीं हूं। संभवतः जब आप इलाके का निर्माण करते हैं तो आपको खुद को बनाए रखने की आवश्यकता होती है।
MichaelHouse

2
मैं इस विचार को अमल में लाने में कामयाब रहा हूं क्योंकि मैं नपे की टक्कर के संपर्क बिंदुओं का पता लगा सकता हूं और अगर एक से अधिक हैं तो उन्हें औसत कर सकता हूं। यह सपाट या उत्तल सतहों पर बढ़ने के लिए आवश्यक नहीं लगता है, लेकिन इसने मेरी सबसे बड़ी समस्या को हल कर दिया है: क्या करना है जब मेरा मकड़ी एक तेज कोने का सामना करता है। जैसा कि मेरे नए उत्तर में उल्लेख किया गया है, मैं अपने मकड़ी के ग्राफिक को उन्मुख करने में मदद करने के लिए इस विचार पर बदलाव का प्रयास कर सकता हूं।
एरिक एन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.