portaldacalheta.pt
  • Κύριος
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
Τεχνολογία

Τελικός οδηγός για τη γλώσσα επεξεργασίας Μέρος II: Δημιουργία ενός απλού παιχνιδιού



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

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



Δημιουργήστε ένα απλό παιχνίδι με τη γλώσσα επεξεργασίας.



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



Tutorial Processing: Ένα απλό παιχνίδι

Το παιχνίδι σε αυτό το εκπαιδευτικό σεμινάριο επεξεργασίας είναι ένας συνδυασμός Flappy Bird, Pong και Brick Breaker. Ο λόγος που διάλεξα ένα παιχνίδι σαν αυτό είναι ότι έχει τις περισσότερες από τις έννοιες με τις οποίες οι αρχάριοι αγωνίζονται όταν μαθαίνουν την ανάπτυξη παιχνιδιών. Αυτό βασίζεται στην εμπειρία μου από τότε που ήμουν βοηθός διδασκαλίας, βοηθώντας τους νέους προγραμματιστές να μάθουν πώς να χρησιμοποιούν την Επεξεργασία. Αυτές οι έννοιες περιλαμβάνουν βαρύτητα, συγκρούσεις, διατήρηση σκορ, χειρισμό διαφορετικών οθονών και αλληλεπιδράσεις πληκτρολογίου / ποντικιού. Ο Flappy Pong τα έχει όλα.

Παίξτε το παιχνίδι τώρα!



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

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



Ας ξεκινήσουμε.

Κτίριο Flappy Pong

Επεξεργασία Tutorial Βήμα # 1: Αρχικοποίηση & Χειρισμός Διαφορετικών Οθόνων

Το πρώτο βήμα είναι η προετοιμασία του έργου μας. Για αρχάριους, θα γράψουμε τις ρυθμίσεις μας και θα σχεδιάσουμε μπλοκ ως συνήθως, τίποτα δεν είναι φανταχτερό ή καινούργιο. Στη συνέχεια, θα χειριστούμε διαφορετικές οθόνες (αρχική οθόνη, οθόνη παιχνιδιού, παιχνίδι πάνω από οθόνη κ.λπ.). Έτσι προκύπτει το ερώτημα, πώς κάνουμε την Επεξεργασία να εμφανίζει τη σωστή σελίδα τη σωστή ώρα;



Η ολοκλήρωση αυτής της εργασίας είναι αρκετά απλή. Θα έχουμε μια καθολική μεταβλητή που αποθηκεύει τις πληροφορίες της τρέχουσας ενεργής οθόνης. Στη συνέχεια σχεδιάζουμε τα περιεχόμενα της σωστής οθόνης ανάλογα με τη μεταβλητή. Στο μπλοκ κλήρωσης, θα έχουμε μια δήλωση if που ελέγχει τη μεταβλητή και εμφανίζει τα περιεχόμενα της οθόνης ανάλογα. Όποτε θέλουμε να αλλάξουμε την οθόνη, θα αλλάξουμε αυτή τη μεταβλητή στο αναγνωριστικό της οθόνης που θέλουμε να εμφανίζεται. Με αυτό είπε, εδώ είναι ο κώδικας του σκελετού μας:

/********* VARIABLES *********/ // We control which screen is active by settings / updating // gameScreen variable. We display the correct screen according // to the value of this variable. // // 0: Initial Screen // 1: Game Screen // 2: Game-over Screen int gameScreen = 0; /********* SETUP BLOCK *********/ void setup() { size(500, 500); } /********* DRAW BLOCK *********/ void draw() { // Display the contents of the current screen if (gameScreen == 0) { initScreen(); } else if (gameScreen == 1) { gameScreen(); } else if (gameScreen == 2) { gameOverScreen(); } } /********* SCREEN CONTENTS *********/ void initScreen() { // codes of initial screen } void gameScreen() { // codes of game screen } void gameOverScreen() { // codes for game over screen } /********* INPUTS *********/ public void mousePressed() { // if we are on the initial screen when clicked, start the game if (gameScreen==0) { startGame(); } } /********* OTHER FUNCTIONS *********/ // This method sets the necessary variables to start the game void startGame() { gameScreen=1; }

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



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

Στο void mousePressed(){...} μέρος, ακούμε τα κλικ του ποντικιού και εάν η ενεργή οθόνη είναι 0, η αρχική οθόνη, καλούμε το startGame() μέθοδος που ξεκινά το παιχνίδι όπως θα περίμενε κανείς. Η πρώτη γραμμή αυτής της μεθόδου αλλάζει gameScreen μεταβλητή σε 1, την οθόνη του παιχνιδιού.



Εάν αυτό γίνει κατανοητό, το επόμενο βήμα είναι να εφαρμόσουμε την αρχική μας οθόνη. Για να γίνει αυτό, θα επεξεργαζόμαστε το initScreen() μέθοδος. Ορίστε:

void initScreen() { background(0); textAlign(CENTER); text('Click to start', height/2, width/2); }

Τώρα η αρχική μας οθόνη έχει ένα μαύρο φόντο και ένα απλό κείμενο, 'Click to start', που βρίσκεται στη μέση και ευθυγραμμισμένο με το κέντρο. Αλλά όταν κάνουμε κλικ, δεν συμβαίνει τίποτα. Δεν έχουμε καθορίσει ακόμη περιεχόμενο για την οθόνη του παιχνιδιού μας. Η μέθοδος gameScreen() δεν έχει τίποτα σε αυτό, επομένως δεν καλύπτουμε τα προηγούμενα περιεχόμενα που αντλήθηκαν από την τελευταία οθόνη (το κείμενο) έχοντας background() ως η πρώτη γραμμή κλήρωσης. Αυτός είναι ο λόγος για τον οποίο το κείμενο εξακολουθεί να υπάρχει, παρόλο που το text() η γραμμή δεν καλείται πλέον (ακριβώς όπως το παράδειγμα της κινούμενης μπάλας από το τελευταίο μέρος που άφησε ίχνος πίσω) . Το φόντο είναι ακόμα μαύρο για τον ίδιο λόγο. Ας προχωρήσουμε και ξεκινήστε να εφαρμόζουμε την οθόνη του παιχνιδιού.

void gameScreen() { background(255); }

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

Επεξεργαστικός οδηγός Βήμα 2: Δημιουργία της μπάλας και εφαρμογή βαρύτητας

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

Αρχικά, ας προσθέσουμε τα εξής:

έγινε δεν είναι συνάρτηση
... int ballX, ballY; int ballSize = 20; int ballColor = color(0); ... void setup() { ... ballX=width/4; ballY=height/5; } ... void gameScreen() { ... drawBall(); } ... void drawBall() { fill(ballColor); ellipse(ballX, ballY, ballSize, ballSize); }

Ορίσαμε τις συντεταγμένες ως καθολικές μεταβλητές, δημιουργήσαμε μια μέθοδο που τραβάει την μπάλα, που καλείται από οθόνη οθόνης μέθοδος. Το μόνο που πρέπει να προσέξουμε εδώ είναι ότι εμείς αρχικοποιήθηκε συντεταγμένες, αλλά τις ορίσαμε σε setup(). Ο λόγος που το κάναμε είναι ότι θέλαμε να ξεκινήσει η μπάλα στο ένα τέταρτο από τα αριστερά και το ένα πέμπτο από την κορυφή. Δεν υπάρχει κανένας συγκεκριμένος λόγος που το θέλουμε, αλλά αυτό είναι ένα καλό σημείο για να ξεκινήσει η μπάλα. Επομένως, χρειαζόμασταν να πάρουμε το width και height του σκίτσου δυναμικά. Το μέγεθος του σκίτσου ορίζεται στο setup(), μετά την πρώτη γραμμή. width και height δεν έχουν οριστεί πριν setup() τρέχει, γι 'αυτό δεν θα μπορούσαμε να το επιτύχουμε αν ορίσαμε τις μεταβλητές στην κορυφή.

Βαρύτητα

Τώρα η εφαρμογή της βαρύτητας είναι στην πραγματικότητα το εύκολο μέρος. Υπάρχουν μόνο μερικά κόλπα. Εδώ είναι η εφαρμογή πρώτα:

... float gravity = 1; float ballSpeedVert = 0; ... void gameScreen() { ... applyGravity(); keepInScreen(); } ... void applyGravity() { ballSpeedVert += gravity; ballY += ballSpeedVert; } void makeBounceBottom(float surface) { ballY = surface-(ballSize/2); ballSpeedVert*=-1; } void makeBounceTop(float surface) { ballY = surface+(ballSize/2); ballSpeedVert*=-1; } // keep ball in the screen void keepInScreen() { // ball hits floor if (ballY+(ballSize/2) > height) { makeBounceBottom(height); } // ball hits ceiling if (ballY-(ballSize/2) <0) { makeBounceTop(0); } }

Και το αποτέλεσμα είναι:

Μια μπάλα που αναπηδά επ

Κρατήστε τα άλογά σας, φυσικός. Ξέρω ότι δεν είναι πώς λειτουργεί η βαρύτητα στην πραγματική ζωή . Αντίθετα, αυτό είναι περισσότερο μια διαδικασία κινούμενης εικόνας από οτιδήποτε άλλο. Η μεταβλητή που ορίσαμε ως gravity είναι απλώς μια αριθμητική τιμή — a float ώστε να μπορούμε να χρησιμοποιήσουμε δεκαδικές τιμές, όχι μόνο ακέραιους αριθμούς - που προσθέτουμε στο ballSpeedVert σε κάθε βρόχο. Και ballSpeedVert είναι η κατακόρυφη ταχύτητα της μπάλας, η οποία προστίθεται στη συντεταγμένη Υ της μπάλας (ballY) σε κάθε βρόχο. Παρακολουθούμε τις συντεταγμένες της μπάλας και βεβαιώνουμε ότι παραμένει στην οθόνη. Αν δεν το κάναμε, η μπάλα θα πέσει στο άπειρο. Προς το παρόν, η μπάλα μας κινείται μόνο κάθετα. Έτσι βλέπουμε τα όρια του δαπέδου και της οροφής της οθόνης. Με keepInScreen() μέθοδος, ελέγχουμε εάν ballY ( + η ακτίνα) είναι μικρότερη από height και παρόμοια ballY ( - η ακτίνα) είναι μεγαλύτερη από 0. Εάν οι προϋποθέσεις δεν πληρούνται, κάνουμε την μπάλα να αναπηδά (από κάτω ή πάνω) με makeBounceBottom() και makeBounceTop() μεθόδους. Για να κάνουμε την μπάλα να αναπηδήσει, απλώς μετακινούμε την μπάλα στην ακριβή θέση όπου έπρεπε να αναπηδήσει και να πολλαπλασιάσει την κατακόρυφη ταχύτητα (ballSpeedVert) με -1 (πολλαπλασιάζοντας με -1 αλλάζει το σύμβολο). Όταν η τιμή ταχύτητας έχει ένα σύμβολο μείον, προσθέτοντας Y συντεταγμένη, η ταχύτητα γίνεται ballY + (-ballSpeedVert), που είναι ballY - ballSpeedVert. Έτσι η μπάλα αλλάζει αμέσως την κατεύθυνση με την ίδια ταχύτητα. Στη συνέχεια, καθώς προσθέτουμε gravity έως ballSpeedVert και ballSpeedVert έχει αρνητική τιμή, αρχίζει να πλησιάζει στο 0, τελικά γίνεται 0 και αρχίζει να αυξάνεται ξανά. Αυτό κάνει την μπάλα να ανέβει, να ανεβαίνει πιο αργά, να σταματά και να αρχίζει να πέφτει.

Μια μπάλα που αναπηδά επ

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

... float airfriction = 0.0001; float friction = 0.1; ... void applyGravity() { ... ballSpeedVert -= (ballSpeedVert * airfriction); } void makeBounceBottom(int surface) { ... ballSpeedVert -= (ballSpeedVert * friction); } void makeBounceTop(int surface) { ... ballSpeedVert -= (ballSpeedVert * friction); }

Και τώρα η διαδικασία κινουμένων σχεδίων μας παράγει αυτό:

Μια μπάλα που αναπηδά αλλά έρχεται σε στάση λόγω τριβής.

Όπως υποδηλώνει το όνομα, friction είναι η επιφανειακή τριβή και airfriction είναι η τριβή του αέρα. Προφανώς λοιπόν, friction πρέπει να εφαρμόζεται κάθε φορά που η μπάλα αγγίζει οποιαδήποτε επιφάνεια. airfriction Ωστόσο, πρέπει να εφαρμόζεται συνεχώς. Αυτό κάναμε λοιπόν. applyGravity() Η μέθοδος εκτελείται σε κάθε βρόχο, οπότε αφαιρούμε 0.0001 τοις εκατό της τρέχουσας τιμής από ballSpeedVert σε κάθε βρόχο. makeBounceBottom() και makeBounceTop() Οι μέθοδοι εκτελούνται όταν η μπάλα αγγίζει οποιαδήποτε επιφάνεια. Έτσι, σε αυτές τις μεθόδους, κάναμε το ίδιο πράγμα, μόνο αυτή τη φορά με friction .

Επεξεργασία Tutorial Βήμα # 3: Δημιουργία του Racket

Τώρα χρειαζόμαστε μια ρακέτα για να αναπηδήσει η μπάλα. Πρέπει να ελέγξουμε τη ρακέτα. Ας το κάνουμε ελεγχόμενο με το ποντίκι. Εδώ είναι ο κωδικός:

... color racketColor = color(0); float racketWidth = 100; float racketHeight = 10; ... void gameScreen() { ... drawRacket(); ... } ... void drawRacket(){ fill(racketColor); rectMode(CENTER); rect(mouseX, mouseY, racketWidth, racketHeight); }

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

Τώρα που δημιουργήσαμε τη ρακέτα, πρέπει να κάνουμε την μπάλα να αναπηδήσει.

... int racketBounceRate = 20; ... void gameScreen() { ... watchRacketBounce(); ... } ... void watchRacketBounce() { float overhead = mouseY - pmouseY; if ((ballX+(ballSize/2) > mouseX-(racketWidth/2)) && (ballX-(ballSize/2)

Και εδώ είναι το αποτέλεσμα:

Μια μπάλα που αναπηδά σε μια ρακέτα αλλά σταματά λόγω της τριβής.

Λοιπόν τι watchRacketBounce() είναι να διασφαλίζει ότι η ρακέτα και η μπάλα συγκρούονται. Υπάρχουν δύο πράγματα που πρέπει να ελέγξετε εδώ, δηλαδή εάν η μπάλα και η ρακέτα παρατάσσονται κάθετα και οριζόντια. Η πρώτη αν η δήλωση ελέγχει εάν η συντεταγμένη Χ της δεξιάς πλευράς της μπάλας είναι μεγαλύτερη από τη συντεταγμένη Χ της αριστεράς πλευράς της ρακέτας (και το αντίστροφο). Εάν είναι, η δεύτερη δήλωση ελέγχει εάν η απόσταση μεταξύ της μπάλας και της ρακέτας είναι μικρότερη ή ίση με την ακτίνα της μπάλας (που σημαίνει ότι συγκρούονται) . Επομένως, εάν πληρούνται αυτές οι προϋποθέσεις, makeBounceBottom() καλείται μέθοδος και η μπάλα αναπηδά στη ρακέτα μας (στο mouseY, όπου βρίσκεται η ρακέτα).

Έχετε παρατηρήσει τη μεταβλητή overhead που υπολογίζεται με mouseY - pmouseY; pmouseX και pmouseY Οι μεταβλητές αποθηκεύουν τις συντεταγμένες του ποντικιού στο προηγούμενο καρέ. Καθώς το ποντίκι μπορεί να κινηθεί πολύ γρήγορα, υπάρχει μια καλή πιθανότητα να μην εντοπίσουμε σωστά την απόσταση μεταξύ της μπάλας και της ρακέτας μεταξύ των πλαισίων εάν το ποντίκι κινείται προς την μπάλα αρκετά γρήγορα. Λοιπόν, λαμβάνουμε τη διαφορά των συντεταγμένων του ποντικιού μεταξύ των πλαισίων και το λαμβάνουμε υπόψη κατά τον εντοπισμό της απόστασης. Όσο πιο γρήγορα κινείται το ποντίκι, τόσο μεγαλύτερη είναι αποδεκτή η απόσταση.

Χρησιμοποιούμε επίσης overhead για έναν άλλο λόγο. Εντοπίζουμε με ποιον τρόπο κινείται το ποντίκι ελέγχοντας το σύμβολο του overhead. Εάν τα γενικά έξοδα είναι αρνητικά, το ποντίκι ήταν κάπου πιο κάτω στο προηγούμενο πλαίσιο, έτσι το ποντίκι μας (ρακέτα) κινείται προς τα πάνω. Σε αυτήν την περίπτωση, θέλουμε να προσθέσουμε μια επιπλέον ταχύτητα στη μπάλα και να την μετακινήσουμε λίγο πιο πέρα ​​από την κανονική αναπήδηση για να προσομοιώσουμε το αποτέλεσμα του χτυπήματος της μπάλας με τη ρακέτα. Εάν overhead είναι μικρότερο από 0, το προσθέτουμε στο ballY και ballSpeedVert για να κάνει την μπάλα να ανέβει ψηλότερα και πιο γρήγορα. Έτσι, όσο πιο γρήγορα η ρακέτα χτυπά τη μπάλα, τόσο υψηλότερη και ταχύτερη θα κινείται προς τα πάνω.

Επεξεργασία Tutorial Βήμα # 4: Οριζόντια Κίνηση & Έλεγχος της μπάλας

Σε αυτήν την ενότητα, θα προσθέσουμε οριζόντια κίνηση στην μπάλα. Στη συνέχεια, θα επιτρέψουμε τον έλεγχο της μπάλας οριζόντια με τη ρακέτα μας. Ορίστε:

... // we will start with 0, but for we give 10 just for testing float ballSpeedHorizon = 10; ... void gameScreen() { ... applyHorizontalSpeed(); ... } ... void applyHorizontalSpeed(){ ballX += ballSpeedHorizon; ballSpeedHorizon -= (ballSpeedHorizon * airfriction); } void makeBounceLeft(float surface){ ballX = surface+(ballSize/2); ballSpeedHorizon*=-1; ballSpeedHorizon -= (ballSpeedHorizon * friction); } void makeBounceRight(float surface){ ballX = surface-(ballSize/2); ballSpeedHorizon*=-1; ballSpeedHorizon -= (ballSpeedHorizon * friction); } ... void keepInScreen() { ... if (ballX-(ballSize/2) width){ makeBounceRight(width); } }

Και το αποτέλεσμα είναι:

Μια μπάλα που αναπηδά τώρα οριζόντια επίσης.

Η ιδέα εδώ είναι η ίδια με αυτή που κάναμε για κάθετη κίνηση. Δημιουργήσαμε μια οριζόντια μεταβλητή ταχύτητας, ballSpeedHorizon. Δημιουργήσαμε μια μέθοδο για την εφαρμογή οριζόντιας ταχύτητας στο ballX και αφαιρέστε την τριβή του αέρα. Προσθέσαμε δύο ακόμη αν δηλώσεις στο keepInScreen() μέθοδος που θα παρακολουθεί τη μπάλα για να χτυπήσει το αριστερό και το δεξί άκρο της οθόνης. Τέλος δημιουργήσαμε makeBounceLeft() και makeBounceRight() μέθοδοι χειρισμού των αναπήδησης από αριστερά και δεξιά.

Τώρα που προσθέσαμε οριζόντια ταχύτητα στο παιχνίδι, θέλουμε να ελέγξουμε τη μπάλα με τη ρακέτα. Όπως στο διάσημο παιχνίδι Atari Ξεμπλοκάρισμα και σε όλα τα άλλα παιχνίδια σπάζοντας τούβλα, η μπάλα πρέπει να πηγαίνει αριστερά ή δεξιά, σύμφωνα με το σημείο της ρακέτας που χτυπά. Οι άκρες της ρακέτας πρέπει να δίνουν στην μπάλα πιο οριζόντια ταχύτητα ενώ η μέση δεν πρέπει να έχει κανένα αποτέλεσμα. Κωδικός πρώτα:

void watchRacketBounce() { ... if ((ballX+(ballSize/2) > mouseX-(racketWidth/2)) && (ballX-(ballSize/2)

Το αποτέλεσμα είναι:

Οριζόντια φυσική τύπου breakout.

Προσθήκη αυτής της απλής γραμμής στο watchRacketBounce() έκανε τη δουλειά. Αυτό που κάναμε είναι να προσδιορίσουμε την απόσταση του σημείου που η μπάλα χτυπά από το κέντρο της ρακέτας με ballX - mouseX. Στη συνέχεια, το κάνουμε την οριζόντια ταχύτητα. Η πραγματική διαφορά ήταν πάρα πολύ, γι 'αυτό το δοκίμασα και κατάλαβα ότι το ένα δέκατο της αξίας αισθάνεται το πιο φυσικό.

Επεξεργασία Tutorial Βήμα # 5: Δημιουργία των Τειχών

Το σκίτσο μας αρχίζει να μοιάζει περισσότερο με ένα παιχνίδι με κάθε βήμα. Σε αυτό το βήμα, θα προσθέσουμε τοίχους που κινούνται προς τα αριστερά, όπως στο Flappy Bird:

... int wallSpeed = 5; int wallInterval = 1000; float lastAddTime = 0; int minGapHeight = 200; int maxGapHeight = 300; int wallWidth = 80; color wallColors = color(0); // This arraylist stores data of the gaps between the walls. Actuals walls are drawn accordingly. // [gapWallX, gapWallY, gapWallWidth, gapWallHeight] ArrayList walls = new ArrayList(); ... void gameScreen() { ... wallAdder(); wallHandler(); } ... void wallAdder() { if (millis()-lastAddTime > wallInterval) { int randHeight = round(random(minGapHeight, maxGapHeight)); int randY = round(random(0, height-randHeight)); // {gapWallX, gapWallY, gapWallWidth, gapWallHeight} int[] randWall = {width, randY, wallWidth, randHeight}; walls.add(randWall); lastAddTime = millis(); } } void wallHandler() { for (int i = 0; i

Και αυτό είχε ως αποτέλεσμα:

Μια μπάλα που αναπηδά σε επίπεδο με τοίχους.

Παρόλο που ο κώδικας φαίνεται μακρύς και εκφοβιστικός, υπόσχομαι ότι δεν υπάρχει τίποτα δύσκολο να κατανοηθεί. Το πρώτο πράγμα που πρέπει να προσέξετε είναι ArrayList. Για όσους από εσάς δεν ξέρετε τι είναι ArrayList είναι, είναι απλώς μια εφαρμογή της λίστας που λειτουργεί σαν Array, αλλά έχει κάποια πλεονεκτήματα από αυτήν. Έχει δυνατότητα αλλαγής μεγέθους, έχει χρήσιμες μεθόδους όπως list.add(index), list.get(index) και list.remove(index). Διατηρούμε τα δεδομένα τοίχου ως ακέραιους πίνακες στη λίστα πίνακα. Τα δεδομένα που διατηρούμε στις συστοιχίες αφορούν το κενό μεταξύ δύο τοίχων. Οι πίνακες περιέχουν τις ακόλουθες τιμές:

[gap wall X, gap wall Y, gap wall width, gap wall height]

Οι πραγματικοί τοίχοι σχεδιάζονται με βάση τις τιμές των διαχωριστικών τοίχων. Σημειώστε ότι όλα αυτά θα μπορούσαν να αντιμετωπιστούν καλύτερα και πιο καθαρά χρησιμοποιώντας τάξεις, αλλά επειδή η χρήση του Προγραμματισμένου Προγράμματος (OOP) δεν εμπίπτει στο πεδίο αυτού του σεμιναρίου Επεξεργασίας, έτσι θα το χειριστούμε. Έχουμε δύο βασικές μεθόδους για τη διαχείριση των τοίχων, wallAdder() και wallHandler.

wallAdder() Η μέθοδος προσθέτει απλά νέους τοίχους σε κάθε wallInterval χιλιοστά του δευτερολέπτου στη λίστα πίνακα. Έχουμε μια καθολική μεταβλητή lastAddTime που αποθηκεύει το χρόνο προσθήκης του τελευταίου τείχους (σε χιλιοστά του δευτερολέπτου) . Εάν το τρέχον χιλιοστό του δευτερολέπτου millis() μείον την τελευταία προσθήκη χιλιοστών του δευτερολέπτου lastAddTime είναι μεγαλύτερη από την τιμή του διαστήματός μας wallInterval, σημαίνει ότι είναι πλέον καιρός να προσθέσετε ένα νέο τείχος. Στη συνέχεια δημιουργούνται μεταβλητές τυχαίου κενού με βάση τις καθολικές μεταβλητές που ορίζονται στην κορυφή. Στη συνέχεια, ένας νέος τοίχος (ακέραιος πίνακας που αποθηκεύει τα δεδομένα τείχους κενού) προστίθεται στη λίστα πίνακα και στο lastAddTime έχει οριστεί στο τρέχον χιλιοστό του δευτερολέπτου millis().

πώς να βρείτε πελάτες για συμβουλευτικές επιχειρήσεις

wallHandler() βρόχους μέσω των τρεχουσών τειχών που βρίσκονται στη λίστα. Και για κάθε στοιχείο σε κάθε βρόχο, καλεί wallRemover(i), wallMover(i) και wallDrawer(i) από την τιμή ευρετηρίου της λίστας πίνακα. Αυτές οι μέθοδοι κάνουν αυτό που προτείνει το όνομά τους. wallDrawer() σχεδιάζει τους πραγματικούς τοίχους με βάση τα δεδομένα τοίχου κενού. Παίρνει τον πίνακα δεδομένων τοίχου από τη λίστα πίνακα και καλεί rect() μέθοδος για να σχεδιάσετε τους τοίχους στο σημείο που θα έπρεπε να είναι. wallMover() Η μέθοδος αρπάζει το στοιχείο από τη λίστα πίνακα, αλλάζει τη θέση Χ με βάση το wallSpeed καθολική μεταβλητή. Τέλος, wallRemover() αφαιρεί τους τοίχους από τη λίστα πίνακα που βρίσκονται εκτός της οθόνης. Εάν δεν το κάναμε, η Επεξεργασία θα τους αντιμετώπιζε καθώς εξακολουθούν να βρίσκονται στην οθόνη. Και αυτό θα ήταν τεράστια απώλεια στην απόδοση. Επομένως, όταν αφαιρείται ένα τείχος από τη λίστα, δεν τραβάει τους επόμενους βρόχους.

Το τελευταίο προκλητικό πράγμα που πρέπει να κάνετε είναι να εντοπίσετε συγκρούσεις μεταξύ της μπάλας και των τοίχων.

void wallHandler() { for (int i = 0; i wallTopX) && (ballX-(ballSize/2)wallTopY) && (ballY-(ballSize/2)wallBottomX) && (ballX-(ballSize/2)wallBottomY) && (ballY-(ballSize/2)

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

Επεξεργασία φροντιστηρίου Βήμα # 6: Υγεία και Βαθμολογία

Τώρα που μπορούμε να εντοπίσουμε τις συγκρούσεις της μπάλας και των τοίχων, μπορούμε να αποφασίσουμε για τη μηχανική του παιχνιδιού. Μετά από λίγο συντονισμό στο παιχνίδι, κατάφερα να κάνω το παιχνίδι κάπως παιγμένο. Όμως, ήταν πολύ δύσκολο. Η πρώτη μου σκέψη στο παιχνίδι ήταν να το κάνω σαν το Flappy Bird, όταν η μπάλα αγγίζει τους τοίχους, το παιχνίδι τελειώνει. Αλλά τότε συνειδητοποίησα ότι θα ήταν αδύνατο να παίξω. Εδώ λοιπόν σκέφτηκα:

Πρέπει να υπάρχει μπάρα υγείας στην κορυφή της μπάλας. Η μπάλα θα πρέπει να χάσει την υγεία ενώ αγγίζει τους τοίχους. Με αυτήν τη λογική, δεν έχει νόημα να αναπηδήσει η μπάλα από τους τοίχους. Επομένως, όταν η υγεία είναι 0, το παιχνίδι θα πρέπει να τελειώσει και θα πρέπει να στραφούμε στο παιχνίδι πάνω από την οθόνη. Ορίστε λοιπόν:

int maxHealth = 100; float health = 100; float healthDecrease = 1; int healthBarWidth = 60; ... void gameScreen() { ... drawHealthBar(); ... } ... void drawHealthBar() { // Make it borderless: noStroke(); fill(236, 240, 241); rectMode(CORNER); rect(ballX-(healthBarWidth/2), ballY - 30, healthBarWidth, 5); if (health > 60) { fill(46, 204, 113); } else if (health > 30) { fill(230, 126, 34); } else { fill(231, 76, 60); } rectMode(CORNER); rect(ballX-(healthBarWidth/2), ballY - 30, healthBarWidth*(health/maxHealth), 5); } void decreaseHealth(){ health -= healthDecrease; if (health <= 0){ gameOver(); } }

Και εδώ είναι μια απλή εκτέλεση:

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

Δημιουργήσαμε μια καθολική μεταβλητή health για να διατηρήσετε την υγεία της μπάλας. Και μετά δημιούργησα μια μέθοδο drawHealthBar() που αντλεί δύο ορθογώνια πάνω από την μπάλα. Η πρώτη είναι η βασική γραμμή υγείας, η άλλη είναι η ενεργή που δείχνει την τρέχουσα υγεία. Το πλάτος του δεύτερου είναι δυναμικό και υπολογίζεται με healthBarWidth*(health/maxHealth), την αναλογία της τρέχουσας υγείας μας σε σχέση με το πλάτος της γραμμής υγείας. Τέλος, τα χρώματα πλήρωσης ρυθμίζονται σύμφωνα με την αξία της υγείας. Τελευταίο αλλά εξίσου σημαντικό, σκορ :

... void gameOverScreen() { background(0); textAlign(CENTER); fill(255); textSize(30); text('Game Over', height/2, width/2 - 20); textSize(15); text('Click to Restart', height/2, width/2 + 10); } ... void wallAdder() { if (millis()-lastAddTime > wallInterval) { ... // added another value at the end of the array int[] randWall = {width, randY, wallWidth, randHeight, 0}; ... } } void watchWallCollision(int index) { ... int wallScored = wall[4]; ... if (ballX > gapWallX+(gapWallWidth/2) && wallScored==0) { wallScored=1; wall[4]=1; score(); } } void score() { score++; } void printScore(){ textAlign(CENTER); fill(0); textSize(30); text(score, height/2, 50); }

Χρειαζόμασταν να σκοράρουμε όταν η μπάλα περνάει από έναν τοίχο. Αλλά πρέπει να προσθέσουμε το μέγιστο 1 σκορ ανά τείχος. Δηλαδή, εάν η μπάλα περάσει από έναν τοίχο από ό, τι επιστρέφει και περάσει ξανά, δεν πρέπει να προστεθεί άλλο σκορ. Για να το επιτύχουμε, προσθέσαμε μια άλλη μεταβλητή στον πίνακα διαχωριστικών τοίχων στη λίστα πίνακα. Οι νέες μεταβλητές αποθηκεύουν 0 αν η μπάλα δεν πέρασε ακόμη εκείνο το τείχος και 1 αν το έκανε. Στη συνέχεια, τροποποιήσαμε το watchWallCollision() μέθοδος. Προσθέσαμε μια συνθήκη που ενεργοποιεί score() μέθοδο και σηματοδοτεί τον τοίχο ως περασμένο όταν η μπάλα περνά έναν τοίχο που δεν έχει περάσει πριν.

Είμαστε τώρα πολύ κοντά στο τέλος. Το τελευταίο πράγμα που πρέπει να κάνετε είναι να εφαρμόσετε click to restart στο παιχνίδι πάνω από την οθόνη. Πρέπει να ορίσουμε όλες τις μεταβλητές που χρησιμοποιήσαμε στην αρχική τους τιμή και να επανεκκινήσουμε το παιχνίδι. Εδώ είναι:

... public void mousePressed() { ... if (gameScreen==2){ restart(); } } ... void restart() { score = 0; health = maxHealth; ballX=width/4; ballY=height/5; lastAddTime = 0; walls.clear(); gameScreen = 0; }

Ας προσθέσουμε μερικά ακόμη χρώματα.

Το ολοκληρωμένο Flappy Pong σε πλήρες χρώμα.

Βόιλα! Έχουμε το Flappy Pong!

Μπορείτε να βρείτε τον πλήρη κώδικα παιχνιδιού επεξεργασίας εδώ .

Μεταφορά του κώδικα επεξεργασίας παιχνιδιού στον Ιστό χρησιμοποιώντας p5.js

σελ. 5 είναι μια βιβλιοθήκη JavaScript με ένα πολύ παρόμοια σύνταξη με αυτήν της γλώσσας προγραμματισμού επεξεργασίας. Δεν είναι βιβλιοθήκη που μπορεί απλώς να εκτελεί υπάρχοντα κώδικα επεξεργασίας. Αντίθετα, το p5.js απαιτεί τη σύνταξη πραγματικού κώδικα JavaScript — παρόμοια με τη θύρα JavaScript της Επεξεργασίας γνωστή ως Επεξεργασία.js . Η αποστολή μας είναι να μετατρέψουμε τον κώδικα επεξεργασίας σε JavaScript χρησιμοποιώντας το API p5.js. Η βιβλιοθήκη έχει ένα σύνολο λειτουργιών και σύνταξης παρόμοιας με την Επεξεργασία και πρέπει να κάνουμε ορισμένες αλλαγές στον κώδικά μας για να τις κάνουμε να λειτουργούν σε JavaScript — αλλά επειδή τόσο η Επεξεργασία όσο και η JavaScript μοιράζονται ομοιότητες με την Java, είναι λιγότερο άλμα απ 'ότι ακούγεται . Ακόμα κι αν δεν είστε Προγραμματιστής JavaScript , οι αλλαγές είναι πολύ ασήμαντες και θα πρέπει να μπορείτε να ακολουθήσετε μια χαρά.

Πρώτα απ 'όλα, πρέπει να δημιουργήσουμε ένα απλό index.html και προσθέστε p5.min.js στην κεφαλίδα μας. Πρέπει επίσης να δημιουργήσουμε ένα άλλο αρχείο που ονομάζεται flappy_pong.js που θα φιλοξενήσει τον κωδικό μετατροπής μας.

Flappy Pong canvas { box-shadow: 0 0 20px lightgray; }

Η στρατηγική μας κατά τη μετατροπή του κώδικα πρέπει να αντιγράφει και να επικολλά όλους τους κωδικούς σε flappy_pong.js και έπειτα κάνοντας όλες τις αλλαγές. Και αυτό έκανα. Και εδώ είναι τα βήματα που έκανα για να ενημερώσω τον κώδικα:

  • Το Javascript είναι μια μη πληκτρολογημένη γλώσσα (δεν υπάρχουν δηλώσεις τύπου όπως int και float). Πρέπει λοιπόν να αλλάξουμε όλες τις δηλώσεις τύπου σε var.

  • Δεν υπάρχει void σε Javascript. Πρέπει να αλλάξουμε όλα σε function.

  • Πρέπει να καταργήσουμε τις δηλώσεις τύπου των ορισμάτων από τις υπογραφές της συνάρτησης. (δηλ. void wallMover(var index) { έως function wallMover(index) {)

  • Δεν υπάρχει ArrayList σε JavaScript. Αλλά μπορούμε να επιτύχουμε το ίδιο πράγμα χρησιμοποιώντας πίνακες JavaScript. Κάνουμε τις ακόλουθες αλλαγές:

    • ArrayList walls = new ArrayList(); έως var walls = [];
    • walls.clear(); έως walls = [];
    • walls.add(randWall); έως walls.push(randWall);
    • walls.remove(index); έως walls.splice(index,1);
    • walls.get(index); έως walls[index]
    • walls.size() έως walls.length
  • Αλλάξτε τη δήλωση του πίνακα var randWall = {width, randY, wallWidth, randHeight, 0}; έως var randWall = [width, randY, wallWidth, randHeight, 0];

  • Κατάργηση όλων public λέξεις-κλειδιά.

  • Μετακίνηση όλων color(0) δηλώσεις σε function setup() επειδή color() δεν θα καθοριστεί πριν από το setup() κλήση.

  • Αλλαγή size(500, 500); έως createCanvas(500, 500);

  • Μετονομασία function gameScreen(){ σε κάτι άλλο όπως function gamePlayScreen(){ επειδή έχουμε ήδη μια καθολική μεταβλητή που ονομάζεται gameScreen. Όταν εργαζόμασταν με την Επεξεργασία, το ένα ήταν μια λειτουργία και το άλλο ήταν int μεταβλητός. Ωστόσο, το JavaScript τα συγχέει αφού είναι άτυπες.

  • Το ίδιο ισχύει για score(). Το μετονόμασα σε addScore().

Μπορείτε να βρείτε τον πλήρη κώδικα JavaScript που καλύπτει τα πάντα σε αυτό το σεμινάριο επεξεργασίας εδώ .

Επεξεργασία κώδικα παιχνιδιού: Μπορείτε να το κάνετε πάρα πολύ

Σε αυτό το σεμινάριο επεξεργασίας, προσπάθησα να εξηγήσω πώς να φτιάξω ένα πολύ απλό παιχνίδι. Ωστόσο, αυτό που κάναμε σε αυτό το άρθρο είναι μόνο η κορυφή του παγόβουνου. Με τη γλώσσα προγραμματισμού επεξεργασίας, σχεδόν οτιδήποτε μπορεί να επιτευχθεί. Κατά τη γνώμη μου, είναι το καλύτερο εργαλείο για να προγραμματίσετε αυτό που φαντάζεστε. Η πραγματική μου πρόθεση με αυτό το σεμινάριο επεξεργασίας ήταν να μην διδάξω την Επεξεργασία και να δημιουργήσω ένα παιχνίδι, για να αποδείξω ότι ο προγραμματισμός δεν είναι τόσο δύσκολος. Η δημιουργία του δικού σας παιχνιδιού δεν είναι απλώς ένα όνειρο. Θα ήθελα να σας δείξω ότι με λίγη προσπάθεια και ενθουσιασμό, μπορείτε να το κάνετε. Ελπίζω πραγματικά ότι αυτά τα δύο άρθρα εμπνέουν τον καθένα να κάνει τον προγραμματισμό ένα πλάνο.

Κατανόηση των βασικών

Σε τι βασίζεται η γλώσσα επεξεργασίας;

Η επεξεργασία βασίζεται σε Java. Δεδομένου ότι το JavaScript μοιάζει επίσης με το Java στην επιφάνεια, η μεταφορά κώδικα επεξεργασίας στον Ιστό είναι αρκετά απλή χρησιμοποιώντας τη βιβλιοθήκη JavaScript p5.js.

Τι είναι το «εγκεφαλικό επεισόδιο» στην Επεξεργασία;

Το εγκεφαλικό επεισόδιο αναφέρεται στο περίγραμμα που σχεδιάζεται γύρω από ένα σχήμα.

Τι κάνει το float στην Επεξεργασία;

Ένα float κρατά μια δεκαδική τιμή. Αντίθετα, ένα int μπορεί να διατηρεί μόνο ακέραιες τιμές (θετικοί ή αρνητικοί ακέραιοι αριθμοί.)

Η ApeeScape συνεργάζεται με Global Guide για να προσφέρει κατ 'απαίτηση πρόσβαση στο Elite Network of Freelancers

Αλλα

Η ApeeScape συνεργάζεται με Global Guide για να προσφέρει κατ 'απαίτηση πρόσβαση στο Elite Network of Freelancers
Τρεις βασικές αρχές της στρατηγικής χαρτοφυλακίου επιχειρηματικών κεφαλαίων

Τρεις βασικές αρχές της στρατηγικής χαρτοφυλακίου επιχειρηματικών κεφαλαίων

Επενδυτές & Χρηματοδότηση

Δημοφιλείς Αναρτήσεις
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
 
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Διευθυντής έργου και διαχείρισης προϊόντων
Διευθυντής έργου και διαχείρισης προϊόντων
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Δημοφιλείς Αναρτήσεις
  • αρχές σχεδιαστικής ενότητας και ποικιλίας
  • Επιτυχής βαθμολογία αρχιτέκτονας λύσεων aws
  • απόδοση φοινικέλαιου ανά εκτάριο
  • Ruby on Rails σεμινάριο ηλεκτρονικού εμπορίου
  • Οδηγός .net core web api
  • ποιοι είναι οι διαφορετικοί τύποι llc
Κατηγορίες
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
  • © 2022 | Ολα Τα Δικαιώματα Διατηρούνται

    portaldacalheta.pt