Ο κύκλος ζωής μιας εφαρμογής ή παιχνιδιού Defold είναι μεγάλης κλίμακας απλός. η μηχανή κινείται σε τρία στάδια εκτέλεσης: αρχικοποίηση, βρόχος ενημέρωσης (όπου οι εφαρμογές και τα παιχνίδια περνούν το μεγαλύτερο μέρος του χρόνου τους) και οριστικοποίηση.
Σε πολλές περιπτώσεις απαιτείται μόνο μια στοιχειώδης κατανόηση των εσωτερικών λειτουργιών του Defold. Ωστόσο, μπορεί να αντιμετωπίσετε περιπτώσεις όπου η ακριβής σειρά Defold εκτελεί τις εργασίες της καθίσταται ζωτικής σημασίας. Αυτό το έγγραφο περιγράφει πώς η μηχανή εκτελεί μια εφαρμογή από την αρχή έως το τέλος.
Η εφαρμογή ξεκινά αρχικοποιώντας ό, τι χρειάζεται για τη λειτουργία του κινητήρα. Φορτώνει την κύρια συλλογή και καλεί init()
σε όλα τα φορτωμένα στοιχεία που έχουν συνάρτηση init()
Lua (στοιχεία σεναρίου και στοιχεία GUI με σενάρια GUI). Αυτό σας επιτρέπει να κάνετε προσαρμοσμένη αρχικοποίηση.
Στη συνέχεια, η εφαρμογή μπαίνει στο βρόχο ενημέρωσης όπου η εφαρμογή θα περάσει το μεγαλύτερο μέρος της διάρκειας ζωής της. Κάθε πλαίσιο, αντικείμενα παιχνιδιού και τα στοιχεία που περιέχουν ενημερώνονται. Κλήση οποιασδήποτε δέσμης ενεργειών και σεναρίου GUI update()
. Κατά τη διάρκεια του βρόχου ενημέρωσης αποστέλλονται μηνύματα στους παραλήπτες τους, αναπαράγονται ήχοι και αποδίδονται όλα τα γραφικά.
Σε κάποιο σημείο ο κύκλος ζωής της εφαρμογής θα τελειώσει. Πριν από την εφαρμογή τερματίσει τον κινητήρα βγαίνει από το βρόχο ενημέρωσης και εισέρχεται στο στάδιο οριστικοποίησης. Προετοιμάζει όλα τα φορτωμένα αντικείμενα παιχνιδιού για διαγραφή. Όλες οι συνιστώσες αντικειμένων final()
καλούνται, γεγονός που επιτρέπει προσαρμοσμένη εκκαθάριση. Στη συνέχεια, τα αντικείμενα διαγράφονται και η κύρια συλλογή εκφορτώνεται.
Αυτό το διάγραμμα περιέχει μια πιο λεπτομερή ανάλυση των βημάτων προετοιμασίας. Τα βήματα που περιλαμβάνονται στο πέρασμα “μηνύματα αποστολής” (ακριβώς πριν από “δυναμικά αντικείμενα αναπαραγωγής”) έχουν τεθεί σε ξεχωριστό μπλοκ προς τα δεξιά για σαφήνεια.
Η μηχανή παίρνει πραγματικά πολύ περισσότερα βήματα κατά την αρχικοποίηση, προτού φορτωθεί η κύρια συλλογή. Ο προγραμματιστής μνήμης, οι υποδοχές, τα γραφικά, το HID (συσκευές εισόδου), ο ήχος, η φυσική και πολλά άλλα έχουν ρυθμιστεί. Η διαμόρφωση της εφαρμογής (game.project) φορτώνεται και ρυθμίζεται επίσης.
Το πρώτο σημείο εισαγωγής που ελέγχεται από το χρήστη, στο τέλος της αρχικοποίησης του κινητήρα, είναι η κλήση στη συνάρτηση init()
του τρέχοντος σεναρίου απόδοσης.
Στη συνέχεια φορτώνεται και αρχικοποιείται η κύρια συλλογή. Όλα τα αντικείμενα του παιχνιδιού στη συλλογή εφαρμόζουν τις μεταμορφώσεις τους (μετάφραση (αλλαγή θέσης), περιστροφή και κλιμάκωση) στα παιδιά τους. Στη συνέχεια καλούνται όλες οι συνιστώσες init()
.
Η σειρά με την οποία καλούνται οι συνιστώσες αντικειμένου παιχνιδιού init()
δεν έχει καθοριστεί. Δεν πρέπει να υποθέσετε ότι η μηχανή αρχικοποιεί αντικείμενα που ανήκουν στην ίδια συλλογή με συγκεκριμένη σειρά.
Δεδομένου ότι ο κώδικας init()
μπορεί να δημοσιεύσει νέα μηνύματα, να πει στα εργοστάσια να γεννήσουν νέα αντικείμενα, να επισημάνουν αντικείμενα για διαγραφή και να κάνουν κάθε είδους πράγματα, η μηχανή εκτελεί ένα πλήρες πέρασμα “μετά την ενημέρωση”. Αυτό το πάσο πραγματοποιεί την παράδοση μηνυμάτων, την πραγματική εργοστασιακή αναπαραγωγή αντικειμένων παιχνιδιών και τη διαγραφή αντικειμένων. Σημειώστε ότι το πέρασμα μετά την ενημέρωση περιλαμβάνει μια ακολουθία “αποστολών μηνυμάτων” που όχι μόνο στέλνει μηνύματα σε ουρά αλλά και χειρίζεται μηνύματα που αποστέλλονται σε διακομιστές μεσολάβησης συλλογής. Τυχόν επόμενες ενημερώσεις στους διακομιστές μεσολάβησης (ενεργοποίηση και απενεργοποίηση, φόρτωση και σήμανση για εκφόρτωση) πραγματοποιούνται κατά τη διάρκεια αυτών των βημάτων.
Μελετώντας το παραπάνω διάγραμμα αποκαλύπτεται ότι είναι πλήρως δυνατή η φόρτωση ενός collection proxy κατά τη διάρκεια του init()
, βεβαιωθείτε ότι όλα τα περιεχόμενα αντικείμενα έχουν αρχικοποιηθεί και, στη συνέχεια, ξεφορτώστε τη συλλογή μέσω του διακομιστή μεσολάβησης—όλα αυτά πριν από την κλήση του πρώτου στοιχείου update()
, δηλαδή πριν η μηχανή αποχωρήσει από το στάδιο προετοιμασίας και εισέλθει στο βρόχο ενημέρωσης:
function init(self)
print("init()")
msg.post("#collectionproxy", "load")
end
function update(self, dt)
-- The proxy collection is unloaded before this code is reached.
print("update()")
end
function on_message(self, message_id, message, sender)
if message_id == hash("proxy_loaded") then
print("proxy_loaded. Init, enable and then unload.")
msg.post("#collectionproxy", "init")
msg.post("#collectionproxy", "enable")
msg.post("#collectionproxy", "unload")
-- The proxy collection objects’ init() and final() functions
-- are called before we reach this object’s update()
end
end
Ο βρόχος ενημέρωσης διατρέχει μια μεγάλη ακολουθία μία φορά κάθε καρέ. Η ακολουθία ενημέρωσης στο παρακάτω διάγραμμα χωρίζεται σε λογικά μπλοκ ακολουθίας για σαφήνεια. Το “Αποστολή μηνυμάτων” διαχωρίζεται επίσης ξεχωριστά για τον ίδιο λόγο:
Η είσοδος διαβάζεται από τις διαθέσιμες συσκευές, αντιστοιχίζεται με input bindings και στη συνέχεια αποστέλλεται. Κάθε αντικείμενο παιχνιδιού που έχει αποκτήσει εστίαση εισόδου αποστέλλεται είσοδος σε όλες τις συναρτήσεις του on_input()
. Ένα αντικείμενο παιχνιδιού με ένα στοιχείο δέσμης ενεργειών και ένα στοιχείο GUI με ένα script GUI θα λάβει είσοδο στις συναρτήσεις on_input()
και των δύο στοιχείων—δεδομένου ότι έχουν οριστεί και ότι έχουν αποκτήσει input focus.
Κάθε αντικείμενο παιχνιδιού που έχει αποκτήσει εστίαση εισόδου και περιέχει στοιχεία διακομιστή μεσολάβησης αποστολής εισόδου σε στοιχεία εντός της συλλογής διακομιστή μεσολάβησης. Αυτή η διαδικασία συνεχίζεται αναδρομικά κάτω με ενεργοποιημένους διακομιστές μεσολάβησης εντός ενεργοποιημένων διακομιστών μεσολάβησης.
Κάθε στοιχείο αντικειμένου παιχνιδιού στην κύρια συλλογή διασχίζεται. Εάν οποιοδήποτε από αυτά τα στοιχεία έχει μια συνάρτηση update()
, τότε θα καλείται. Εάν το στοιχείο είναι διακομιστής μεσολάβησης, κάθε στοιχείο στη συλλογή μεσολάβησης ενημερώνεται αναδρομικά με όλα τα βήματα στην ακολουθία “ενημέρωση” στο παραπάνω διάγραμμα.
Η σειρά με την οποία καλούνται οι λειτουργίες του στοιχείου παιχνιδιού update()
δεν έχει καθοριστεί. Δεν πρέπει να υποθέσετε ότι η μηχανή ενημερώνει αντικείμενα που ανήκουν στην ίδια συλλογή με συγκεκριμένη σειρά.
Στο επόμενο βήμα αποστέλλονται όλα τα αναρτημένα μηνύματα. Δεδομένου ότι οποιοσδήποτε κωδικός “on_message ()” του παραλήπτη μπορεί να δημοσιεύσει επιπλέον μηνύματα, ο αποστολέας μηνυμάτων θα συνεχίσει να αποστέλλει αναρτημένα μηνύματα έως ότου η ουρά μηνυμάτων είναι κενή. Υπάρχει, ωστόσο, ένα όριο στον αριθμό των εκτελέσεων στην ουρά μηνυμάτων που εκτελεί ο αποστολέας μηνυμάτων. Ανατρέξτε στην ενότητα Message passing και στην ενότητα “Advanced topics - Προχωρημένα θέματα” για λεπτομέρειες.
Για στοιχεία αντικειμένου collision, αποστέλλονται μηνύματα φυσικής (collisions, triggers, ray_cast responses etc) σε όλο το αντικείμενο παιχνιδιού και σε όλα τα στοιχεία που περιέχει ένα script με συνάρτηση on_message()
.
Έπειτα, οι μετασχηματισμοί πραγματοποιούνται, εφαρμόζοντας οποιαδήποτε κίνηση αντικειμένου παιχνιδιού, περιστροφή και κλιμάκωση σε κάθε στοιχείο αντικειμένου παιχνιδιού και σε οποιοδήποτε στοιχείο αντικειμένου παιδικού παιχνιδιού.
Το μπλοκ ενημέρωσης απόδοσης αποστέλλει μηνύματα στην υποδοχή @render
socket (camera component set_view_projection
messages, set_clear_color
messages etc). Στη συνέχεια καλείται το script απόδοσης update()
.
Μετά τις ενημερώσεις, εκτελείται μια ακολουθία ενημέρωσης μετά. Εκφορτώνει από διακομιστές μεσολάβησης συλλογής μνήμης που επισημαίνονται για εκφόρτωση (αυτό συμβαίνει κατά τη σειρά “αποστολή μηνυμάτων”). Κάθε αντικείμενο παιχνιδιού που έχει επισημανθεί για διαγραφή θα καλέσει όλες τις λειτουργίες του final()
όλων των στοιχείων του, εάν υπάρχουν. Ο κώδικας στις συναρτήσεις final()
δημοσιεύει συχνά νέα μηνύματα στην ουρά, οπότε εκτελείται ένα πέρασμα «μηνυμάτων αποστολής».
Κάθε εργοστασιακό στοιχείο που έχει πει να δημιουργήσει ένα αντικείμενο παιχνιδιού θα το κάνει στη συνέχεια. Τέλος, τα αντικείμενα παιχνιδιού που έχουν επισημανθεί για διαγραφή στην πραγματικότητα διαγράφονται.
Το τελευταίο βήμα στον βρόχο ενημέρωσης περιλαμβάνει την αποστολή μηνυμάτων @system
messages (exit
, reboot
messages, toggling the profiler, starting and stopping video capture etc). Στη συνέχεια αποδίδονται γραφικά. Κατά τη διάρκεια της απόδοσης γραφικών, γίνεται λήψη βίντεο, όπως και κάθε απόδοση του οπτικού προφίλ (δείτε την Debugging documentation.)
Ο αριθμός των ενημερώσεων καρέ ανά δευτερόλεπτο (που ισούται με τον αριθμό των βρόχων ενημέρωσης ανά δευτερόλεπτο) μπορεί να οριστεί στις ρυθμίσεις του έργου ή μέσω προγραμματισμού στέλνοντας ένα μήνυμαset_update_frequency
στην υποδοχή @system
. Επιπλέον, είναι δυνατό να ορίσετε το time step για τους διακομιστές μεσολάβησης ξεχωριστά στέλνοντας ένα μήνυμα set_time_step
στον διακομιστή μεσολάβησης. Η αλλαγή του χρονικού βήματος μιας συλλογής δεν επηρεάζει το ρυθμό καρέ. Επηρεάζει το βήμα χρόνου ενημέρωσης φυσικής καθώς και τη μεταβλητή dt
που μεταβιβάστηκε στην update()
. Επίσης, σημειώστε ότι η αλλαγή του βήματος χρόνου δεν αλλάζει τον αριθμό των φορών που η update()
θα καλείται σε κάθε πλαίσιο—είναι πάντα ακριβώς μια φορά.
(See the Collection proxy manual and set_time_step
for details)
Όταν τερματιστεί η εφαρμογή, πρώτα ολοκληρώσει την τελευταία ακολουθία βρόχου ενημέρωσης, η οποία θα ξεφορτώσει τυχόν διακομιστές μεσολάβησης: οριστικοποίηση και διαγραφή όλων των αντικειμένων παιχνιδιών σε κάθε συλλογή μεσολάβησης.
Όταν γίνει αυτό, η μηχανή εισάγει μια ακολουθία οριστικοποίησης που χειρίζεται την κύρια συλλογή και τα αντικείμενά της:
Οι συναρτήσεις final()
ονομάζονται πρώτα. Ακολουθεί μια επόμενη αποστολή μηνυμάτων. Τέλος, όλα τα αντικείμενα του παιχνιδιού διαγράφονται και η κύρια συλλογή εκφορτώνεται.
η μηχανή παρακολουθεί πίσω από τα παρασκήνια το κλείσιμο των υποσυστημάτων: η διαμόρφωση του έργου διαγράφεται, το πρόγραμμα προβολής μνήμης είναι κλειστό και ούτω καθεξής.
Η εφαρμογή τερματίστηκε εντελώς.
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB