Manuals
Manuals




This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English

Διευθυνσιοδότηση

Ο κώδικας που ελέγχει ένα παιχνίδι το οποίο εκτελείται πρέπει να μπορεί να προσπελάσει κάθε αντικείμενο και στοιχείο, ώστε να μετακινεί, να κλιμακώνει, να κινεί, να διαγράφει και να χειρίζεται όσα βλέπει και ακούει ο παίκτης. Ο μηχανισμός διευθυνσιοδότησης (addressing) του Defold το καθιστά δυνατό.

Αναγνωριστικά

Το Defold χρησιμοποιεί διευθύνσεις (ή URL, αλλά ας τα αγνοήσουμε προς το παρόν) για να αναφέρεται σε αντικείμενα παιχνιδιού και στοιχεία. Οι διευθύνσεις αυτές αποτελούνται από αναγνωριστικά. Ακολουθούν μερικά παραδείγματα του τρόπου με τον οποίο το Defold χρησιμοποιεί διευθύνσεις. Στη συνέχεια του εγχειριδίου θα εξετάσουμε λεπτομερώς πώς λειτουργούν:

local id = factory.create("#enemy_factory")
label.set_text("my_gameobject#my_label", "Hello World!")

local pos = go.get_position("my_gameobject")
go.set_position(pos, "/level/stuff/other_gameobject")

msg.post("#", "hello_there")
local id = go.get_id(".")

Ας ξεκινήσουμε με ένα πολύ απλό παράδειγμα. Ας υποθέσουμε ότι έχετε ένα αντικείμενο παιχνιδιού με ένα μόνο στοιχείο sprite. Έχετε επίσης ένα στοιχείο script για τον έλεγχο του αντικειμένου παιχνιδιού. Η διάταξη στον επεξεργαστή μοιάζει με αυτή:

Το bean στον επεξεργαστή

Τώρα θέλετε να απενεργοποιήσετε το sprite όταν ξεκινά το παιχνίδι, ώστε να μπορείτε να το εμφανίσετε αργότερα. Αυτό γίνεται εύκολα τοποθετώντας τον ακόλουθο κώδικα στο controller.script:

function init(self)
    msg.post("#body", "disable") -- <1>
end
  1. Μην ανησυχείτε αν σας προβληματίζει ο χαρακτήρας #. Θα τον εξηγήσουμε σύντομα.

Αυτό λειτουργεί όπως αναμένεται. Όταν ξεκινά το παιχνίδι, το στοιχείο script διευθυνσιοδοτεί το στοιχείο sprite μέσω του αναγνωριστικού body και χρησιμοποιεί αυτή τη διεύθυνση για να του στείλει το μήνυμα disable. Αυτό το ειδικό μήνυμα της μηχανής κάνει το στοιχείο sprite να κρύψει το γραφικό του. Σχηματικά, η διάταξη μοιάζει με αυτή:

Διάταξη του bean

Τα αναγνωριστικά στη διάταξη ορίζονται από τον προγραμματιστή και πρέπει να είναι μοναδικά μέσα στο περιβάλλον ονοματοδοσίας τους. Εδώ επιλέξαμε να δώσουμε στο αντικείμενο παιχνιδιού το αναγνωριστικό bean, στο στοιχείο sprite το αναγνωριστικό body και στο στοιχείο script που ελέγχει τον χαρακτήρα το αναγνωριστικό controller. Τα αναγνωριστικά που χρησιμοποιούνται σε διευθύνσεις URL συμβολοσειράς δεν πρέπει να περιέχουν : ή #, επειδή η σύνταξη URL δεσμεύει το : ως διαχωριστικό υποδοχής και το # ως διαχωριστικό αντικειμένου παιχνιδιού και στοιχείου. Κατά τα άλλα, ο αναλυτής URL δεν απορρίπτει σημεία στίξης.

Εάν δεν επιλέξετε όνομα, θα το κάνει ο επεξεργαστής. Κάθε φορά που δημιουργείτε ένα νέο αντικείμενο παιχνιδιού ή στοιχείο στον επεξεργαστή, ορίζεται αυτόματα μια μοναδική ιδιότητα Id.

  • Τα αντικείμενα παιχνιδιού λαμβάνουν αυτόματα ένα αναγνωριστικό με όνομα go και έναν αύξοντα αριθμό (go2, go3 κ.λπ.).
  • Τα στοιχεία λαμβάνουν ένα αναγνωριστικό που αντιστοιχεί στον τύπο στοιχείου (sprite, sprite2 κ.λπ.).

Μπορείτε να διατηρήσετε αυτά τα αυτόματα εκχωρημένα ονόματα εάν θέλετε, αλλά σας προτείνουμε να αλλάξετε τα αναγνωριστικά σε καλά, περιγραφικά ονόματα.

Τώρα ας προσθέσουμε ένα ακόμη στοιχείο sprite και ας δώσουμε στο bean μια ασπίδα:

Το bean με ασπίδα στον επεξεργαστή

Το νέο στοιχείο πρέπει να έχει μοναδικό αναγνωριστικό μέσα στο αντικείμενο παιχνιδιού. Εάν του δίναμε το όνομα body, ο κώδικας του script δεν θα ήξερε σε ποιο sprite πρέπει να στείλει το μήνυμα disable. Επομένως επιλέγουμε το μοναδικό και περιγραφικό αναγνωριστικό shield. Τώρα μπορούμε να ενεργοποιούμε και να απενεργοποιούμε τα sprite body και shield κατά βούληση.

Το bean και η ασπίδα

Εάν προσπαθήσετε να χρησιμοποιήσετε ένα αναγνωριστικό περισσότερες από μία φορές στο ίδιο περιβάλλον ονοματοδοσίας, ο επεξεργαστής θα επισημάνει ένα σφάλμα, οπότε αυτό δεν αποτελεί πρόβλημα στην πράξη:

Σύγκρουση αναγνωριστικών

Τώρα ας δούμε τι συμβαίνει όταν προσθέτετε περισσότερα αντικείμενα παιχνιδιού. Ας υποθέσουμε ότι θέλετε να συνδυάσετε δύο χαρακτήρες bean σε μια μικρή ομάδα. Ονομάζετε το ένα αντικείμενο παιχνιδιού bean και το άλλο buddy. Όταν το bean παραμένει αδρανές για λίγο, πρέπει να πει στο buddy να αρχίσει να χορεύει. Αυτό γίνεται με την αποστολή ενός προσαρμοσμένου μηνύματος dance από το στοιχείο script controller του bean στο script controller του buddy:

Τα bean και buddy

Υπάρχουν δύο ξεχωριστά στοιχεία με όνομα controller, ένα σε κάθε αντικείμενο παιχνιδιού. Αυτό είναι απολύτως έγκυρο, καθώς κάθε αντικείμενο παιχνιδιού δημιουργεί νέο περιβάλλον ονοματοδοσίας.

Εφόσον ο παραλήπτης του μηνύματος βρίσκεται έξω από το αντικείμενο παιχνιδιού που το στέλνει (bean), ο κώδικας πρέπει να καθορίσει ποιο controller θα λάβει το μήνυμα. Πρέπει να προσδιορίσει τόσο το αναγνωριστικό του αντικειμένου παιχνιδιού προορισμού όσο και το αναγνωριστικό του στοιχείου. Η πλήρης διεύθυνση του στοιχείου είναι "buddy#controller" και αποτελείται από δύο μέρη:

  • πρώτα έρχεται το αναγνωριστικό του αντικειμένου παιχνιδιού προορισμού (buddy),
  • ακολουθεί ο χαρακτήρας διαχωρισμού αντικειμένου παιχνιδιού και στοιχείου (#),
  • και τέλος το αναγνωριστικό του στοιχείου προορισμού (controller).

Επιστρέφοντας στο προηγούμενο παράδειγμα με ένα αντικείμενο παιχνιδιού, βλέπουμε ότι αν παραλείψουμε το αναγνωριστικό του αντικειμένου παιχνιδιού από τη διεύθυνση προορισμού, ο κώδικας μπορεί να απευθύνεται σε στοιχεία του τρέχοντος αντικειμένου παιχνιδιού.

Για παράδειγμα, το "#body" δηλώνει τη διεύθυνση του στοιχείου body στο τρέχον αντικείμενο παιχνιδιού. Αυτό είναι πολύ χρήσιμο, επειδή ο κώδικας λειτουργεί σε οποιοδήποτε αντικείμενο παιχνιδιού, αρκεί να υπάρχει ένα στοιχείο body.

Συλλογές

Οι συλλογές καθιστούν δυνατή τη δημιουργία ομάδων ή ιεραρχιών αντικειμένων παιχνιδιού και την ελεγχόμενη επαναχρησιμοποίησή τους. Χρησιμοποιείτε αρχεία συλλογής ως πρότυπα (templates, prototypes ή prefabs) στον επεξεργαστή, όταν συμπληρώνετε το παιχνίδι σας με περιεχόμενο.

Ας υποθέσουμε ότι θέλετε να δημιουργήσετε πολλές ομάδες bean και buddy. Ένας καλός τρόπος είναι να δημιουργήσετε ένα πρότυπο σε ένα νέο αρχείο συλλογής με όνομα team.collection. Δημιουργήστε τα αντικείμενα παιχνιδιού της ομάδας στο αρχείο συλλογής και αποθηκεύστε το. Έπειτα τοποθετήστε ένα στιγμιότυπο (instance) του περιεχομένου αυτού του αρχείου στην κύρια συλλογή εκκίνησης και δώστε του το αναγνωριστικό team_1:

Η ομάδα στον επεξεργαστή

Με αυτή τη δομή, το αντικείμενο παιχνιδιού bean μπορεί ακόμη να αναφέρεται στο στοιχείο controller του buddy με τη διεύθυνση "buddy#controller".

Η συλλογή ομάδας

Αν προσθέσετε ένα δεύτερο στιγμιότυπο του team.collection με όνομα team_2, ο κώδικας που εκτελείται μέσα στα στοιχεία script του team_2 λειτουργεί εξίσου καλά. Το στιγμιότυπο του αντικειμένου παιχνιδιού bean στη συλλογή team_2 μπορεί και πάλι να απευθυνθεί στο στοιχείο controller του buddy με τη διεύθυνση "buddy#controller".

Δύο ομάδες στον επεξεργαστή

Σχετική διευθυνσιοδότηση

Η διεύθυνση "buddy#controller" λειτουργεί για τα αντικείμενα παιχνιδιού και στις δύο συλλογές, επειδή είναι σχετική διεύθυνση. Καθεμία από τις συλλογές team_1 και team_2 δημιουργεί ένα νέο περιβάλλον ονοματοδοσίας, ή namespace. Το Defold αποφεύγει τις συγκρούσεις ονομάτων λαμβάνοντας υπόψη το περιβάλλον ονοματοδοσίας που δημιουργεί κάθε συλλογή:

Σχετικά αναγνωριστικά

  • Στο περιβάλλον ονοματοδοσίας team_1, τα αντικείμενα παιχνιδιού bean και buddy αναγνωρίζονται μοναδικά.
  • Ομοίως, στο περιβάλλον ονοματοδοσίας team_2, τα αντικείμενα παιχνιδιού bean και buddy αναγνωρίζονται επίσης μοναδικά.

Η σχετική διευθυνσιοδότηση λειτουργεί προσθέτοντας αυτόματα μπροστά το τρέχον περιβάλλον ονοματοδοσίας κατά την επίλυση μιας διεύθυνσης προορισμού. Αυτό είναι ιδιαίτερα χρήσιμο, επειδή μπορείτε να δημιουργείτε ομάδες αντικειμένων παιχνιδιού με κώδικα και να τις επαναχρησιμοποιείτε αποτελεσματικά σε όλο το παιχνίδι.

Συντομεύσεις

Το Defold παρέχει δύο εύχρηστες συντομεύσεις που μπορείτε να χρησιμοποιήσετε για να στείλετε μήνυμα χωρίς να καθορίσετε ένα πλήρες URL:

.
Shorthand resolving to the current game object.
#
Shorthand resolving to the current component.

For example:

   -- Let this game object acquire input focus
   msg.post(".", "acquire_input_focus")
   -- Post "reset" to the current script
   msg.post("#", "reset")

Διαδρομές αντικειμένων παιχνιδιού

Για να κατανοήσουμε σωστά τον μηχανισμό ονοματοδοσίας, ας δούμε τι συμβαίνει όταν δημιουργείτε και εκτελείτε το έργο:

  1. Ο επεξεργαστής διαβάζει τη συλλογή εκκίνησης (main.collection) και όλο το περιεχόμενό της, δηλαδή αντικείμενα παιχνιδιού και άλλες συλλογές.
  2. Για κάθε στατικό αντικείμενο παιχνιδιού, ο μεταγλωττιστής δημιουργεί ένα αναγνωριστικό. Τα αναγνωριστικά σχηματίζονται ως διαδρομές (paths), ξεκινώντας από τη ρίζα εκκίνησης και ακολουθώντας την ιεραρχία συλλογής μέχρι το αντικείμενο. Σε κάθε επίπεδο προστίθεται ο χαρακτήρας /.

Στο παραπάνω παράδειγμα, το παιχνίδι εκτελείται με τα ακόλουθα τέσσερα αντικείμενα παιχνιδιού:

  • /team_1/bean
  • /team_1/buddy
  • /team_2/bean
  • /team_2/buddy

Τα αναγνωριστικά αποθηκεύονται ως κατακερματισμένες τιμές (hashes). Ο χρόνος εκτέλεσης αποθηκεύει επίσης την κατάσταση κατακερματισμού κάθε αναγνωριστικού συλλογής, ώστε να μπορεί να συνεχίσει τον κατακερματισμό μιας σχετικής συμβολοσειράς και να παράγει ένα απόλυτο αναγνωριστικό.

Κατά τον χρόνο εκτέλεσης, η ομαδοποίηση των συλλογών δεν υπάρχει. Δεν υπάρχει τρόπος να μάθετε σε ποια συλλογή ανήκε ένα συγκεκριμένο αντικείμενο παιχνιδιού πριν από τη μεταγλώττιση, ούτε είναι δυνατό να χειριστείτε ταυτόχρονα όλα τα αντικείμενα μιας συλλογής. Αν χρειάζεστε τέτοιες λειτουργίες, μπορείτε να παρακολουθείτε μόνοι σας τα αντικείμενα στον κώδικα. Το αναγνωριστικό κάθε αντικειμένου είναι στατικό και παραμένει σταθερό σε όλη τη διάρκεια ζωής του. Επομένως μπορείτε να το αποθηκεύσετε με ασφάλεια και να το χρησιμοποιήσετε αργότερα.

Απόλυτη διευθυνσιοδότηση

Μπορείτε να χρησιμοποιήσετε τα πλήρη αναγνωριστικά που περιγράφονται παραπάνω κατά τη διευθυνσιοδότηση. Στις περισσότερες περιπτώσεις προτιμάται η σχετική διευθυνσιοδότηση, επειδή επιτρέπει την επαναχρησιμοποίηση περιεχομένου, αλλά μερικές φορές είναι απαραίτητη η απόλυτη διευθυνσιοδότηση.

Για παράδειγμα, ας υποθέσουμε ότι θέλετε έναν διαχειριστή AI που παρακολουθεί την κατάσταση κάθε αντικειμένου bean. Τα bean αναφέρουν την ενεργή κατάστασή τους στον διαχειριστή, ενώ εκείνος λαμβάνει τακτικές αποφάσεις και τους δίνει εντολές με βάση αυτή την κατάσταση. Σε αυτή την περίπτωση είναι λογικό να δημιουργήσετε ένα αντικείμενο παιχνιδιού manager με ένα στοιχείο script και να το τοποθετήσετε μαζί με τις συλλογές των ομάδων στη συλλογή εκκίνησης.

Το αντικείμενο manager

Κάθε bean είναι υπεύθυνο για την αποστολή μηνυμάτων κατάστασης στον διαχειριστή: contact αν εντοπίσει έναν εχθρό ή ouch! αν χτυπηθεί και υποστεί ζημιά. Για να λειτουργήσει αυτό, το script controller του bean χρησιμοποιεί απόλυτη διευθυνσιοδότηση για να στέλνει μηνύματα στο στοιχείο controller του manager.

Κάθε διεύθυνση που ξεκινά με / επιλύεται από τη ρίζα του κόσμου του παιχνιδιού. Αυτή αντιστοιχεί στη ρίζα της συλλογής εκκίνησης που φορτώνεται κατά την έναρξη του παιχνιδιού.

Η απόλυτη διεύθυνση του script του διαχειριστή είναι "/manager#controller" και επιλύεται στο σωστό στοιχείο ανεξάρτητα από το πού χρησιμοποιείται.

Οι ομάδες και το manager

Απόλυτη διευθυνσιοδότηση

Κατακερματισμένα αναγνωριστικά

Η μηχανή αποθηκεύει όλα τα αναγνωριστικά ως κατακερματισμένες τιμές (hashes). Όλες οι συναρτήσεις που λαμβάνουν ως όρισμα ένα στοιχείο ή αντικείμενο παιχνιδιού δέχονται συμβολοσειρά, hash ή αντικείμενο URL. Παραπάνω είδαμε πώς χρησιμοποιούνται οι συμβολοσειρές για τη διευθυνσιοδότηση.

Όταν ζητάτε το αναγνωριστικό ενός αντικειμένου παιχνιδιού, η μηχανή επιστρέφει πάντα ένα κατακερματισμένο αναγνωριστικό απόλυτης διαδρομής:

local my_id = go.get_id()
print(my_id) --> hash: [/path/to/the/object]

local spawned_id = factory.create("#some_factory")
print(spawned_id) --> hash: [/instance42]

Μπορείτε να χρησιμοποιήσετε ένα τέτοιο αναγνωριστικό αντί για ένα αναγνωριστικό συμβολοσειράς ή να δημιουργήσετε ένα μόνοι σας. Λάβετε υπόψη ότι ένα κατακερματισμένο αναγνωριστικό αντιστοιχεί στη διαδρομή προς το αντικείμενο, δηλαδή σε μια απόλυτη διεύθυνση:

Οι σχετικές διευθύνσεις πρέπει να δίνονται ως συμβολοσειρές (strings), επειδή η μηχανή υπολογίζει ένα νέο κατακερματισμένο αναγνωριστικό με βάση την κατάσταση κατακερματισμού του τρέχοντος περιβάλλοντος ονοματοδοσίας, προσθέτοντας τη δεδομένη συμβολοσειρά στο hash.

local spawned_id = factory.create("#some_factory")
local pos = vmath.vector3(100, 100, 0)
go.set_position(pos, spawned_id)

local other_id = hash("/path/to/the/object")
go.set_position(pos, other_id)

-- This will not work! Relative addresses must be given as strings.
local relative_id = hash("my_object")
go.set_position(pos, relative_id)

Διευθύνσεις URL

Για να ολοκληρώσουμε την εικόνα, ας δούμε την πλήρη μορφή των διευθύνσεων του Defold: το URL.

Ένα URL είναι ένα αντικείμενο που συνήθως γράφεται ως ειδικά διαμορφωμένη συμβολοσειρά. Ένα γενικό URL αποτελείται από τρία μέρη:

[socket:][path][#fragment]

socket (υποδοχή)
Προσδιορίζει τον κόσμο παιχνιδιού του προορισμού. Είναι σημαντικό όταν εργάζεστε με proxy συλλογής, οπότε χρησιμοποιείται για τον προσδιορισμό της δυναμικά φορτωμένης συλλογής.
path (διαδρομή)
Αυτό το μέρος του URL περιέχει το πλήρες αναγνωριστικό του αντικειμένου παιχνιδιού προορισμού.
fragment (τμήμα)
Το αναγνωριστικό του στοιχείου προορισμού μέσα στο καθορισμένο αντικείμενο παιχνιδιού.

Όπως είδαμε παραπάνω, στις περισσότερες περιπτώσεις μπορείτε να παραλείψετε μερικές ή και τις περισσότερες από αυτές τις πληροφορίες. Σχεδόν ποτέ δεν χρειάζεται να καθορίσετε την υποδοχή, ενώ συχνά, αλλά όχι πάντα, πρέπει να καθορίσετε τη διαδρομή. Όταν πρέπει να απευθυνθείτε σε κάτι σε άλλον κόσμο παιχνιδιού, πρέπει να καθορίσετε το τμήμα socket του URL. Για παράδειγμα, η πλήρης συμβολοσειρά URL για το script controller στο αντικείμενο παιχνιδιού manager είναι:

"main:/manager#controller"

και για το controller του buddy στο team_2 είναι:

"main:/team_2/buddy#controller"

Μπορούμε να τους στείλουμε μηνύματα:

-- Send "hello" to the manager script and team buddy bean
msg.post("main:/manager#controller", "hello_manager")
msg.post("main:/team_2/buddy#controller", "hello_buddy")

Δημιουργία αντικειμένων URL

Τα αντικείμενα URL μπορούν επίσης να δημιουργηθούν μέσω προγραμματισμού σε κώδικα Lua:

-- Construct URL object from a string:
local my_url = msg.url("main:/manager#controller")
print(my_url) --> url: [main:/manager#controller]
print(my_url.socket) --> 786443 (internal numeric value)
print(my_url.path) --> hash: [/manager]
print(my_url.fragment) --> hash: [controller]

-- Construct URL from parameters:
local my_url = msg.url("main", "/manager", "controller")
print(my_url) --> url: [main:/manager#controller]

-- Build from empty URL object:
local my_url = msg.url()
my_url.socket = "main" -- specify by valid name
my_url.path = hash("/manager") -- specify as string or hash
my_url.fragment = "controller" -- specify as string or hash

-- Post to target specified by URL
msg.post(my_url, "hello_manager!")