Η ανάπτυξη παιχνιδιών iOS μπορεί να είναι μια εμπλουτιστική εμπειρία τόσο σε προσωπικό όσο και σε προσωπικό χρηματοοικονομική ανάπτυξη. Νωρίτερα φέτος, ανέπτυξα ένα παιχνίδι βασισμένο σε Cocos2D, Αγώνας μελισσών , στο App Store. Το παιχνίδι του είναι απλό: ένας άπειρος δρομέας στον οποίο οι παίκτες (σε αυτήν την περίπτωση, οι μέλισσες) συλλέγουν πόντους και αποφεύγουν εμπόδια. Βλέπω εδώ για μια επίδειξη.
πιο δημοφιλή εργαλεία οπτικοποίησης δεδομένων
Σε αυτό το σεμινάριο, θα εξηγήσω τη διαδικασία ανάπτυξης παιχνιδιών για iOS, από το Cocos2D έως τη δημοσίευση. Για αναφορά, ακολουθεί ένας σύντομος πίνακας περιεχομένων:
Προτού φτάσουμε στις λεπτομερείς λεπτομέρειες, θα ήταν χρήσιμο να κατανοήσουμε τη διάκριση μεταξύ ξωτικά και φυσικά αντικείμενα.
Για κάθε δεδομένη οντότητα που εμφανίζεται στην οθόνη ενός ατελείωτου παιχνιδιού δρομέα, η γραφική παράσταση αυτής της οντότητας αναφέρεται ως ξωτικό , ενώ η πολυγωνική αναπαράσταση αυτής της οντότητας στη μηχανή φυσικής αναφέρεται ως φυσικό αντικείμενο .
Έτσι, το sprite σχεδιάζεται στην οθόνη, υποστηριζόμενο από το αντίστοιχο φυσικό αντικείμενο, το οποίο στη συνέχεια χειρίζεται ο κινητήρας φυσικής σας. Αυτή η ρύθμιση μπορεί να απεικονιστεί εδώ, όπου τα sprites εμφανίζονται στην οθόνη, με τα φυσικά πολυγωνικά αντίστοιχα να περιγράφονται με πράσινο χρώμα:
Τα φυσικά αντικείμενα δεν είναι συνδεδεμένα στα αντίστοιχα sprite τους από προεπιλογή, πράγμα που σημαίνει ότι εσείς ως Προγραμματιστής iOS μπορεί να επιλέξει ποια μηχανή φυσικής να χρησιμοποιήσει και πώς να συνδέσει τα sprites και το σώμα. Ο πιο συνηθισμένος τρόπος είναι η υποκατηγορία του προεπιλεγμένου sprite και η προσθήκη ενός συγκεκριμένου φυσικού σώματος σε αυτό.
Με αυτό στο μυαλό…
Cocos2D-iPhone είναι ένα πλαίσιο ανοιχτού κώδικα για iOS που χρησιμοποιεί το OpenGL για επιτάχυνση γραφικών υλικού και υποστηρίζει το Είδος σκίουρου και Πλαίσιο 2D κινητήρες φυσικής.
Πρώτα απ 'όλα, γιατί χρειαζόμαστε ένα τέτοιο πλαίσιο; Λοιπόν, για αρχάριους, τα πλαίσια εφαρμόζουν τα συχνά χρησιμοποιούμενα στοιχεία της ανάπτυξης παιχνιδιών. Για παράδειγμα, το Cocos2D μπορεί να φορτώσει sprites (συγκεκριμένα, φύλλα sprite ( Γιατί? )), εκκινήστε ή σταματήστε μια μηχανή φυσικής και χειριστείτε σωστά το συγχρονισμό και την κίνηση. Και τα κάνει όλα αυτά με κώδικα που έχει ελεγχθεί και δοκιμαστεί εκτενώς - γιατί αφιερώστε τον δικό σας χρόνο για να ξαναγράψετε τον πιθανό-κατώτερο κώδικα;
Ίσως το πιο σημαντικό, ωστόσο— Η ανάπτυξη παιχνιδιών Cocos2D χρησιμοποιεί επιτάχυνση υλικού γραφικών . Χωρίς τέτοια επιτάχυνση, οποιοδήποτε παιχνίδι με άπειρο δρομέα iOS, ακόμη και με μέτριο αριθμό sprite, θα τρέχει με ιδιαίτερα κακή απόδοση. Εάν προσπαθήσουμε να κάνουμε μια πιο περίπλοκη εφαρμογή, τότε πιθανότατα θα αρχίσουμε να βλέπουμε ένα εφέ 'bullet-time' στην οθόνη, δηλαδή πολλαπλά αντίγραφα κάθε sprite καθώς προσπαθεί να κινούσει.
Τέλος, η Cocos2D βελτιστοποιεί τη χρήση της μνήμης από τότε σπρέι . Επομένως, κάθε διπλό sprite απαιτεί ελάχιστη επιπλέον μνήμη, η οποία είναι προφανώς χρήσιμο για παιχνίδια.
Μετά από όλους τους επαίνους που έχω δώσει στο Cocos2D, μπορεί να φαίνεται παράλογο πρότεινε τη χρήση Storyboards . Γιατί όχι μόνο να χειριστείτε τα αντικείμενά σας με το Cocos2D κ.λπ.; Λοιπόν, για να είμαι ειλικρινής, για στατικά παράθυρα είναι συχνά πιο βολικό να χρησιμοποιείτε το Xcode's Interface Builder και το μηχανισμό του Storyboard.
Πρώτον, μου επιτρέπει να μεταφέρω και να τοποθετήσω όλα τα γραφικά μου στοιχεία για το ατελείωτο παιχνίδι δρομέων με το ποντίκι μου. Δεύτερον, το API του Storyboard είναι πολύ, πολύ χρήσιμο. (Και ναι, το ξέρω Cocos Builder ).
Ακολουθεί μια γρήγορη ματιά στο Storyboard μου:
Ο κύριος ελεγκτής προβολής του παιχνιδιού περιέχει μόνο μια σκηνή Cocos2D με μερικά στοιχεία HUD στην κορυφή:
Δώστε προσοχή στο λευκό φόντο: είναι μια σκηνή της Cocos2D, η οποία θα φορτώσει όλα τα απαραίτητα γραφικά στοιχεία κατά το χρόνο εκτέλεσης. Άλλες προβολές (ζωντανές ενδείξεις, πικραλίδες, κουμπιά κ.λπ.) είναι όλες οι τυπικές προβολές κακάου, που προστίθενται στην οθόνη χρησιμοποιώντας το Interface Builder.
Δεν θα αναφερθώ στις λεπτομέρειες - αν σας ενδιαφέρει, μπορείτε να βρείτε παραδείγματα στο GitHub.
(Για να δώσω περισσότερα κίνητρα, θα ήθελα να περιγράψω το ατελείωτο παιχνίδι δρομέων μου με λίγο περισσότερες λεπτομέρειες. Μη διστάσετε να παραλείψετε αυτήν την ενότητα εάν θέλετε να προχωρήσετε στην τεχνική συζήτηση.)
Κατά τη διάρκεια του ζωντανού παιχνιδιού, η μέλισσα είναι ακίνητη και το ίδιο το πεδίο τρέχει, φέρνοντας μαζί του διάφορους κινδύνους (αράχνες και δηλητηριώδη λουλούδια) και προνόμια (πικραλίδες και τους σπόρους τους).
Το Cocos2D έχει αντικείμενο κάμερας που σχεδιάστηκε για να ακολουθεί τον χαρακτήρα. Στην πράξη, ήταν λιγότερο περίπλοκο να χειριστείτε το CCLayer που περιέχει τον κόσμο του παιχνιδιού.
Τα χειριστήρια είναι απλά: αγγίζοντας την οθόνη μετακινεί τη μέλισσα και μια άλλη βρύση την μετακινεί προς τα κάτω.
Το ίδιο το παγκόσμιο επίπεδο έχει στην πραγματικότητα δύο υποεπίπεδα. Όταν ξεκινά το παιχνίδι, το πρώτο δευτερεύον στρώμα συμπληρώνεται από 0 έως BUF_LEN και εμφανίζεται αρχικά. Το δεύτερο δευτερεύον επίπεδο συμπληρώνεται εκ των προτέρων από BUF_LEN έως 2 * BUF_LEN. Όταν η μέλισσα φτάσει στο BUF_LEN, το πρώτο υπόστρωμα καθαρίζεται και επανεγκαθίσταται αμέσως από 2 * BUF_LEN σε 3 * BUF_LEN και εμφανίζεται το δεύτερο υποστρωματικό στρώμα. Με αυτόν τον τρόπο, εναλλάσσουμε μεταξύ των επιπέδων, χωρίς να διατηρούμε παρωχημένα αντικείμενα, ένα σημαντικό μέρος της αποφυγής διαρροών μνήμης.
Όσον αφορά τους κινητήρες φυσικής, χρησιμοποίησα το Chipmunk για δύο λόγους:
Ο κινητήρας φυσικής χρησιμοποιήθηκε πραγματικά μόνο για την ανίχνευση σύγκρουσης. Μερικές φορές, με ρωτάνε, 'Γιατί δεν γράψατε τη δική σας ανίχνευση σύγκρουσης;'. Στην πραγματικότητα, δεν υπάρχει πολύ νόημα σε αυτό. Οι κινητήρες φυσικής σχεδιάστηκαν για τους ίδιους σκοπούς: μπορούν να ανιχνεύσουν συγκρούσεις μεταξύ σωμάτων πολύπλοκων σχημάτων και να βελτιστοποιήσουν αυτήν τη διαδικασία. Για παράδειγμα, οι μηχανές φυσικής χωρίζουν συχνά τον κόσμο σε κύτταρα και πραγματοποιούν ελέγχους σύγκρουσης μόνο για σώματα στα ίδια ή γειτονικά κελιά.
δοκιμάστε τις βέλτιστες πρακτικές catch javascript
Ένα βασικό συστατικό της ανεξέλεγκτης ανάπτυξης παιχνιδιών δρομέων είναι να αποφύγετε να μπείτε σε μικρά ζητήματα. Ο χρόνος είναι ένας κρίσιμος πόρος κατά την ανάπτυξη μιας εφαρμογής και ο αυτοματισμός μπορεί να εξοικονομεί απίστευτα χρόνο.
Αλλά μερικές φορές, ο αυτοματισμός μπορεί επίσης να είναι ένας συμβιβασμός μεταξύ τελειομανίας και τήρησης της προθεσμίας σας. Υπό αυτήν την έννοια, ο τελειομανισμός μπορεί να είναι δολοφόνος Angry Birds.
Για παράδειγμα, σε ένα άλλο παιχνίδι iOS που αναπτύσσω αυτήν τη στιγμή, δημιούργησα ένα πλαίσιο για τη δημιουργία διατάξεων χρησιμοποιώντας ένα ειδικό εργαλείο (διαθέσιμο στο GitHub ). Αυτό το πλαίσιο έχει τους περιορισμούς του (για παράδειγμα, δεν έχει ωραίες μεταβάσεις μεταξύ σκηνών), αλλά με τη χρήση μου επιτρέπει να κάνω τις σκηνές μου στο δέκατο του χρόνου.
Έτσι, ενώ δεν μπορείτε να δημιουργήσετε το δικό σας υπερπλαίσιο με ειδικά supertools, μπορείτε ακόμα και πρέπει να αυτοματοποιήσετε όσο το δυνατόν περισσότερες από αυτές τις μικρές εργασίες.
Η τελειομανία μπορεί να είναι δολοφόνος Angry Birds. Ο χρόνος είναι ένας κρίσιμος πόρος για την ανάπτυξη παιχνιδιών iOS. ΤιτίβισμαΚατά την κατασκευή αυτού του άπειρου δρομέα, ο αυτοματισμός ήταν το κλειδί για άλλη μια φορά. Για παράδειγμα, ο καλλιτέχνης μου θα μου έστειλε γραφικά υψηλής ανάλυσης μέσω ενός ειδικού φακέλου Dropbox. Για να εξοικονομήσω χρόνο, έγραψα κάποια σενάρια για να δημιουργήσω αυτόματα σύνολα αρχείων για τις διάφορες αναλύσεις στόχου που απαιτούνται από το App Store, προσθέτοντας επίσης -hd ή @ 2x (τα εν λόγω σενάρια βασίζονται σε ImageMagick ).
Όσον αφορά τα πρόσθετα εργαλεία, βρήκα TexturePacker να είναι πολύ χρήσιμο - μπορεί να συσκευάσει sprite σε φύλλα sprite, ώστε η εφαρμογή σας να καταναλώνει λιγότερη μνήμη και να φορτώνει γρηγορότερα, καθώς όλα τα sprite σας θα διαβάζονται από ένα μόνο αρχείο. Μπορεί επίσης να εξάγει υφές σε όλες σχεδόν τις πιθανές μορφές πλαισίων. (Σημειώστε ότι το TexturePacker δεν είναι ένα δωρεάν εργαλείο, αλλά νομίζω ότι αξίζει την τιμή. Μπορείτε επίσης να δείτε δωρεάν εναλλακτικές λύσεις όπως Κουτί παπουτσιών .)
Η κύρια δυσκολία που σχετίζεται με τη φυσική του παιχνιδιού είναι η δημιουργία κατάλληλων πολυγώνων για κάθε sprite. Με άλλα λόγια, δημιουργώντας μια πολυγωνική αναπαράσταση κάποιας ασήμαντης μορφής μέλισσας ή λουλουδιού. Μην προσπαθήσετε καν να το κάνετε με το χέρι - χρησιμοποιείτε πάντα ειδικές εφαρμογές, από τις οποίες υπάρχουν πολλές. Μερικά είναι ακόμη αρκετά… εξωτικά - όπως η δημιουργία μάσκας φορέα με το Inkspace και στη συνέχεια η εισαγωγή τους στο παιχνίδι.
Για τη δική μου ατελείωτη ανάπτυξη παιχνιδιών δρομέα, δημιούργησα ένα εργαλείο για την αυτοματοποίηση αυτής της διαδικασίας (βλ εδώ για σωστή χρήση), την οποία αποκαλώ Βοηθός Andengine Vertex . Όπως υποδηλώνει το όνομα, σχεδιάστηκε αρχικά για το Πλαίσιο Andengine , αν και θα λειτουργήσει κατάλληλα με διάφορες μορφές αυτές τις μέρες.
Στην περίπτωσή μας, πρέπει να χρησιμοποιήσουμε το μοτίβο plist:
%.5f%.5f
Στη συνέχεια, δημιουργούμε ένα αρχείο plist με περιγραφές αντικειμένων:
jet_ant vertices -0.182620.08277 -0.14786-0.22326 0.20242-0.55282 0.470470.41234 0.038230.41234
Και ένας φορτωτής αντικειμένων:
- (void)createBodyAtLocation:(CGPoint)location{ float mass = 1.0; body = cpBodyNew(mass, cpMomentForBox(mass, self.sprite.contentSize.width*self.sprite.scale, self.sprite.contentSize.height*self.sprite.scale)); body->p = location; cpSpaceAddBody(space, body); NSString *path =[[NSBundle mainBundle] pathForResource:@'obj _descriptions' ofType:@'plist']; // e = 0.7; shape->u = 1.0; shape->collision_type = OBJ_COLLISION_TYPE; cpSpaceAddShape(space, shape); }
Για να ελέγξετε πώς τα sprites αντιστοιχούν στο φυσικό τους σώμα, δείτε εδώ .
διαφορά μεταξύ s corporation και γ
Πολύ καλύτερα, σωστά;
Συνοπτικά, αυτοματοποιήστε πάντα όταν είναι δυνατόν. Ακόμα και τα απλά σενάρια μπορούν να σας εξοικονομήσουν χρόνο. Και το σημαντικό είναι ότι αυτός ο χρόνος μπορεί να χρησιμοποιηθεί για προγραμματισμό αντί για κλικ στο ποντίκι. (Για επιπλέον κίνητρα, εδώ είναι διακριτικό XKCD .)
Οι συλλεγόμενες μπάλες στο παιχνίδι λειτουργούν ως νόμισμα εντός της εφαρμογής, επιτρέποντας στους χρήστες να αγοράζουν νέα δέρματα για τη μέλισσα τους. Ωστόσο, αυτό το νόμισμα μπορεί επίσης να αγοραστεί με πραγματικά χρήματα. Ένα σημαντικό σημείο που πρέπει να σημειωθεί σχετικά με τη χρέωση εντός εφαρμογής είναι εάν πρέπει ή όχι να πραγματοποιήσετε ελέγχους από την πλευρά του διακομιστή για την εγκυρότητα της αγοράς. Δεδομένου ότι όλα τα αγαθά που αγοράζονται είναι ουσιαστικά ίσα όσον αφορά το παιχνίδι (αλλάζοντας απλώς την εμφάνιση της μέλισσας), δεν χρειάζεται να εκτελέσετε έλεγχο διακομιστή για την εγκυρότητα της αγοράς. Ωστόσο, σε πολλές περιπτώσεις, σίγουρα θα πρέπει να το κάνετε.
Για περισσότερα, ο Ray Wenderlich έχει το τέλειο φροντιστήριο χρέωσης εντός εφαρμογής .
Σε παιχνίδια για κινητά, κοινωνικοποίηση είναι κάτι παραπάνω από απλώς την προσθήκη ενός κουμπιού 'Μου αρέσει' στο Facebook ή τη δημιουργία βαθμολογικών πινάκων. Για να κάνω το παιχνίδι πιο συναρπαστικό, εφάρμοσα μια έκδοση για πολλούς παίκτες.
Πώς λειτουργεί; Κατ 'αρχάς, δύο παίκτες συνδέονται χρησιμοποιώντας τον αγώνα σε πραγματικό χρόνο του iOS Game Center. Καθώς οι παίκτες παίζουν πραγματικά το ίδιο άπειρο παιχνίδι δρομέων, πρέπει να υπάρχει μόνο ένα σύνολο αντικειμένων παιχνιδιού. Αυτό σημαίνει ότι το παράδειγμα ενός παίκτη πρέπει να δημιουργεί τα αντικείμενα και το άλλο παιχνίδι θα τα διαβάσει. Με άλλα λόγια, εάν και οι δύο συσκευές παικτών δημιουργούσαν αντικείμενα παιχνιδιού, θα ήταν δύσκολο να συγχρονίσετε την εμπειρία.
Έχοντας αυτό κατά νου, μετά τη σύνδεση, και οι δύο παίκτες στέλνουν ο ένας στον άλλο έναν τυχαίο αριθμό. Ο παίκτης με τον υψηλότερο αριθμό λειτουργεί ως 'διακομιστής', δημιουργώντας αντικείμενα παιχνιδιού.
Θυμάστε τη συζήτηση για την παγκόσμια γενιά με μερίδα; Πού είχαμε δύο δευτερεύοντα επίπεδα, ένα από το 0 έως το BUF_LEN και το άλλο από το BUF_LEN έως το 2 * BUF_LEN; Αυτή η αρχιτεκτονική δεν χρησιμοποιήθηκε τυχαία - ήταν απαραίτητη η παροχή ομαλών γραφικών σε καθυστερημένα δίκτυα. Όταν δημιουργείται ένα τμήμα αντικειμένων, συσκευάζεται σε μια πλακέτα και αποστέλλεται στην άλλη συσκευή αναπαραγωγής. Το buffer είναι αρκετά μεγάλο για να αφήσει τον δεύτερο παίκτη να παίξει ακόμα και με καθυστέρηση δικτύου. Και οι δύο παίκτες στέλνουν ο ένας στον άλλο την τρέχουσα θέση τους με περίοδο μισού δευτερολέπτου, στέλνοντας επίσης τις κινήσεις τους προς τα πάνω αμέσως. Για να εξομαλυνθεί η εμπειρία, η θέση και η ταχύτητα διορθώνονται κάθε 0,5 δευτερόλεπτα με ομαλή κίνηση, έτσι στην πράξη φαίνεται ότι ο άλλος παίκτης κινείται ή επιταχύνεται σταδιακά.
Υπάρχουν σίγουρα περισσότερες σκέψεις που πρέπει να γίνουν όσον αφορά το ατελείωτο παιχνίδι παιχνιδιού για πολλούς παίκτες, αλλά ελπίζουμε ότι αυτό θα σας δώσει μια αίσθηση για τους τύπους των προκλήσεων που εμπλέκονται.
Τα παιχνίδια δεν τελειώνουν ποτέ. Βεβαίως, υπάρχουν αρκετοί τομείς στους οποίους θα ήθελα να βελτιώσω τον δικό μου, συγκεκριμένα:
Το παγκόσμιο επίπεδο μετακινείται χρησιμοποιώντας την ενέργεια CCMoveBy. Αυτό ήταν εντάξει όταν η ταχύτητα του παγκόσμιου στρώματος ήταν σταθερή, καθώς η δράση CCMoveBy κυκλοφόρησε με το CCRepeatForever:
πότε να χρησιμοποιήσετε το apache spark
-(void) infiniteMove{ id actionBy = [CCMoveBy actionWithDuration: BUFFER_DURATION position: ccp(-BUFFER_LENGTH, 0)]; id actionCallFunc = [CCCallFunc actionWithTarget:self selector:@selector(requestFillingNextBuffer)]; id actionSequence = [CCSequence actions: actionBy, actionCallFunc, nil]; id repeateForever = [CCRepeatForever actionWithAction:actionSequence]; [self.bufferContainer runAction:repeateForever]; }
Αλλά αργότερα, πρόσθεσα μια παγκόσμια αύξηση ταχύτητας για να κάνω το παιχνίδι πιο δύσκολο καθώς συνεχίζεται:
-(void) infiniteMoveWithAccel { float duration = BUFFER_DURATION-BUFFER_ACCEL*self.lastBufferNumber; duration = max(duration, MIN_BUFFER_DURATION); id actionBy = [CCMoveBy actionWithDuration: duration position: ccp(-BUFFER_LENGTH, 0)]; id restartMove = [CCCallFunc actionWithTarget:self selector:@selector(infiniteMoveWithAccel)]; id fillBuffer = [CCCallFunc actionWithTarget:self selector:@selector(requestFillingNextBuffer)]; id actionSequence = [CCSequence actions: actionBy, restartMove, fillBuffer, nil]; [self.bufferContainer runAction:actionSequence]; }
Αυτή η αλλαγή έκανε το κινούμενο σχέδιο να χαλάσει σε κάθε επανεκκίνηση της δράσης. Προσπάθησα να διορθώσω το πρόβλημα, χωρίς αποτέλεσμα. Ωστόσο, οι δοκιμαστές beta δεν παρατήρησαν τη συμπεριφορά, επομένως ανέβαλα την επιδιόρθωση.
Η δημιουργία του δικού σας ανεξάρτητου παιχνιδιού ατελείωτων δρομέων μπορεί να είναι μια υπέροχη εμπειρία. Και μόλις φτάσετε στο βήμα δημοσίευσης της διαδικασίας, μπορεί να είναι ένα υπέροχο συναίσθημα καθώς απελευθερώνετε τη δική σας δημιουργία στο φυσικό περιβάλλον.
Η διαδικασία ελέγχου μπορεί να κυμαίνεται από αρκετές ημέρες έως αρκετές εβδομάδες. Για περισσότερα, υπάρχει ένας χρήσιμος ιστότοπος εδώ που χρησιμοποιεί δεδομένα που προέρχονται από πλήθος για να εκτιμήσει τους τρέχοντες χρόνους ελέγχου.
Επιπλέον, προτείνω τη χρήση AppAnnie να εξετάσει διάφορες πληροφορίες σχετικά με όλες τις εφαρμογές στο App Store και να εγγραφείτε σε ορισμένες υπηρεσίες ανάλυσης όπως Flurry Analytics μπορεί επίσης να είναι χρήσιμο.
Και αν αυτό το παιχνίδι σας ενδιέφερε, φροντίστε να το ελέγξετε Αγώνας μελισσών στο μαγαζί.