<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Videogames Laboratory &#187; Ανάπτυξη βιντεοπαιχνιδιών</title>
	<atom:link href="http://videogameslab.wordpress.com/category/%ce%b1%ce%bd%ce%ac%cf%80%cf%84%cf%85%ce%be%ce%b7-%ce%b2%ce%b9%ce%bd%cf%84%ce%b5%ce%bf%cf%80%ce%b1%ce%b9%cf%87%ce%bd%ce%b9%ce%b4%ce%b9%cf%8e%ce%bd/feed/" rel="self" type="application/rss+xml" />
	<link>http://videogameslab.wordpress.com</link>
	<description>O συναρπαστικός κόσμος της ανάπτυξης βιντεοπαιχνιδιών</description>
	<lastBuildDate>Tue, 22 Dec 2009 09:49:02 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>el</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='videogameslab.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/255dbf67d2b39d909d863d39cc6cb572?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Videogames Laboratory &#187; Ανάπτυξη βιντεοπαιχνιδιών</title>
		<link>http://videogameslab.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://videogameslab.wordpress.com/osd.xml" title="Videogames Laboratory" />
		<item>
		<title>Σχεδιασμός βιντεοπαιχνιδιών</title>
		<link>http://videogameslab.wordpress.com/2009/12/22/videogame-design/</link>
		<comments>http://videogameslab.wordpress.com/2009/12/22/videogame-design/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 08:19:34 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>
		<category><![CDATA[Σχεδιασμός βιντεοπαιχνιδιών]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=491</guid>
		<description><![CDATA[Λαμβάνω συχνά εκδηλώσεις ενδιαφέροντος από άτομα με γνώσεις στο προγραμματισμό που θα ήθελαν να λάβουν μέρος στην ανάπτυξη ενός παιχνιδιού. Το ίδιο συνέβη για το διαγωνισμό Imagine Cup. Δυστυχώς όμως ο προγραμματισμός και μόνο δεν αρκεί για να φτιάξεις ένα παιχνίδι. Πρέπει καταρχάς να υπάρχει μια καλή ιδέα για παιχνίδι πάνω στην οποία θα σχεδιαστεί [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=491&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="font-family:Verdana;font-size:9pt;">Λαμβάνω συχνά εκδηλώσεις ενδιαφέροντος από άτομα με γνώσεις στο προγραμματισμό που θα ήθελαν να λάβουν μέρος στην ανάπτυξη ενός παιχνιδιού. Το ίδιο συνέβη για το διαγωνισμό Imagine Cup. Δυστυχώς όμως ο προγραμματισμός και μόνο δεν αρκεί για να φτιάξεις ένα παιχνίδι. Πρέπει καταρχάς να υπάρχει μια καλή ιδέα για παιχνίδι πάνω στην οποία θα σχεδιαστεί το σύστημα του παιχνιδιού. Ο σχεδιασμός ενός παιχνιδιού δεν έχει σχέση με το προγραμματισμό του, ούτε καν με την δημιουργία του περιεχομένου του (γραφικά, ήχος, κίνηση κλπ).</span><br />
<span id="more-491"></span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Ένα παιχνίδι, για να είναι παιχνίδι πρέπει καταρχάς να περιέχει τα παρακάτω στοιχεία:<br />
</span></p>
<ul>
<li><span style="font-family:Verdana;font-size:9pt;"><strong>Όρια</strong>: κάθε παιχνίδι λαμβάνει χώρα μέσα σε ένα φανταστικό κόσμο με καθορισμένα όρια<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;"><strong>Στόχος</strong>: ο παίκτης που συμμετέχει στο παιχνίδι έχει κάποια επιδίωξη, κάποιον απώτερο στόχο<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;"><strong>Διαδικασίες</strong>: οι διαδικασίες ενός παιχνιδιού είναι όλες οι κινήσεις που μπορεί να πραγματοποιήσει ένας παίκτης<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;"><strong>Κανόνες</strong>: οι κανόνες σε ένα παιχνίδι καθορίζουν ποιες κινήσεις και διαδικασίες επιτρέπεται να πραγματοποιηθούν και ποιες όχι<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;"><strong>Πόροι</strong>: πόρος σε ένα παιχνίδι είναι οποιοδήποτε αντικείμενο αξίας μπορεί να βοηθήσει τον παίκτη να πετύχει το σκοπό του<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;"><strong>Σύγκρουση</strong>: τα εμπόδια που ο παίκτης συναντά στη διαδρομή για την επίτευξη ενός στόχου<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;"><strong>Αποτέλεσμα</strong>: ένα παιχνίδι καταλήγει σε μια τελική κατάσταση με κάποιο αποτέλεσμα (νίκη ή μη) για το παίκτη<br />
</span></li>
</ul>
<p><span style="font-family:Verdana;font-size:9pt;">Τα συστατικά αυτά υπάρχουν σε όλα τα παιχνίδια, από το σκάκι και το Pong μέχρι το Halo 3. Χωρίς αυτά δεν μπορούν να δημιουργηθούν οι κατάλληλες συνθήκες για «παιχνίδι». Φανταστείτε για παράδειγμα να μην υπήρχε «Σύγκρουση» σε ένα παιχνίδι. Το παιχνίδι θα έπαυε να αποτελεί πρόκληση για το παίκτη και εκείνος θα το εγκατέλειπε γρήγορα.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Όταν λοιπόν ξεκινάμε την δημιουργία ενός παιχνιδιού πρέπει, πριν αρχίσουμε το προγραμματισμό ή την δημιουργία του περιεχομένου, να σχεδιάσουμε το παιχνίδι, να καθορίσουμε δηλαδή τα στοιχεία της παραπάνω λίστας. Αυτή είναι και η δυσκολότερη διαδικασία κατά την ανάπτυξη ενός παιχνιδιού, γιατί αν δεν καθοριστεί σωστά το σύστημα του παιχνιδιού τότε αυτό δεν θα είναι ψυχαγωγικό και δεν θα «εμπλέξει» το παίκτη, όσο καλά και αν είναι τα γραφικά του. Ο σχεδιασμός ενός παιχνιδιού είναι τέχνη και τεχνική μαζί.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Ας δοκιμάσουμε να σχεδιάσουμε ένα παιχνίδι ακολουθώντας το μοτίβο «μονοπάτι» σύμφωνα με το οποίο ο παίκτης πρέπει να μετακινηθεί από το σημείο A στο Β. Για να το κάνουμε αυτό πρέπει να σκεφτούμε τα εξής:<br />
</span></p>
<ul>
<li><span style="font-family:Verdana;font-size:9pt;">Που πηγαίνει ο παίκτης και γιατί;<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;">Πως πηγαίνει εκεί και τι μπορεί να χρησιμοποιήσει στη πορεία<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;">Τι εμπόδια θα συναντήσει, τι τον δυσκολεύει στη πορεία<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;">Τι αποτέλεσμα μπορεί να έχει το παιχνίδι<br />
</span></li>
</ul>
<p><span style="font-family:Verdana;font-size:9pt;">Το μοτίβο αυτό μπορεί να περιγράψει μια μεγάλη ποικιλία από παιχνίδια. Για παράδειγμα, ο παίκτης βρίσκεται σε μια καλύβα ψηλά σε ένα χιονισμένο βουνό και πρέπει να φτάσει στο πλησιέστερο νοσοκομείο. Γιατί πρέπει να το κάνει αυτό; Διότι ο/η σύντροφος του έχει ανάγκη από βοήθεια γιατρού. Πως θα φτάσει στο νοσοκομείο; Μπορεί να χρησιμοποιήσει το SUV, τα χιονοπέδιλα, ένα έλκηθρο κλπ. Τι εμπόδια θα συναντήσει στο πορεία; Του επιτίθενται λύκοι τους οποίους μπορεί να απομακρύνει με κάποιο κυνηγητικό όπλο, ή πρέπει να αποφεύγει δέντρα, ή κατολισθήσεις ή χιονοστιβάδες με το έλκηθρο ή το SUV στη ξέφρενη πορεία του προς το νοσοκομείο. Επίσης ενάντια στο παίκτη δρα και ο χρόνος, γιατί ο/η σύντροφος χειροτερεύει. Τι κατάληξη θα έχει το παιχνίδι; Είτε θα τα καταφέρει να φτάσει στο νοσοκομείο στην ώρα του, είτε θα γίνει λυκοτροφή, είτε θα αργήσει και θα πεθάνει ο/η σύντροφος.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Άλλο παράδειγμα: Ο παίκτης είναι στρατιώτης και πρέπει να καταλάβει το πύργο επικοινωνίας του εχθρού στην κορυφή του λόφου. Γιατί να το κάνει αυτό; Διότι έτσι θα διακόψει την επικοινωνία ενός μεγάλου τμήματος του αντίπαλου στρατού με τη κεντρική διοίκηση. Πως θα φτάσει στο πύργο; Είτε με τα πόδια, είτε με κάποιο άρμα μάχης, είτε με το τζιπ. Τι εμπόδια θα συναντήσει στη πορεία; Αντίπαλους στρατιώτες, κακή ορατότητα λόγω καιρικών συνθηκών, εχθρικά βομβαρδιστικά, κανόνια που βάλλουν εξ αποστάσεως. Τι κατάληξη θα έχει το παιχνίδι; Είτε θα χτυπηθεί από τον εχθρό, είτε θα χαθεί μέσα στην ομίχλη είτε θα καταφέρει να καταλάβει το πύργο.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Ο σχεδιασμός ενός παιχνιδιού είναι η καρδιά της δημιουργίας του. Δεν είναι ιδιαίτερα δύσκολο να σχεδιάσουμε παιχνίδια αν λάβουμε υπόψη τις παραπάνω απαιτήσεις (το αν θα είναι καλά παιχνίδια είναι άλλο θέμα). Δοκιμάστε το  και εσείς, αφήστε την φαντασία σας ελεύθερη και στείλτε μας τα δικά σχέδια και ιδέες για παιχνίδι, στα σχόλια του post.<br />
</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/491/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=491&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/12/22/videogame-design/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>
	</item>
		<item>
		<title>Senses: Πρόσκληση για βελτίωση παιχνιδιού</title>
		<link>http://videogameslab.wordpress.com/2009/12/14/senses-%cf%80%cf%81%cf%8c%cf%83%ce%ba%ce%bb%ce%b7%cf%83%ce%b7-%ce%b3%ce%b9%ce%b1-%ce%b2%ce%b5%ce%bb%cf%84%ce%af%cf%89%cf%83%ce%b7-%cf%80%ce%b1%ce%b9%cf%87%ce%bd%ce%b9%ce%b4%ce%b9%ce%bf%cf%8d/</link>
		<comments>http://videogameslab.wordpress.com/2009/12/14/senses-%cf%80%cf%81%cf%8c%cf%83%ce%ba%ce%bb%ce%b7%cf%83%ce%b7-%ce%b3%ce%b9%ce%b1-%ce%b2%ce%b5%ce%bb%cf%84%ce%af%cf%89%cf%83%ce%b7-%cf%80%ce%b1%ce%b9%cf%87%ce%bd%ce%b9%ce%b4%ce%b9%ce%bf%cf%8d/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 14:40:35 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=488</guid>
		<description><![CDATA[Πριν λίγες μέρες ανέβηκε στο Videogames Laboratory forum ένα post για το παιχνίδι Senses του Σταύρου Κοκκινέα. Σύμφωνα με το δημιουργό του, το concept του παιχνιδιού είναι το εξής: «Ξεκινάτε σε ένα δωμάτιο όπου πρέπει να &#8220;φάτε&#8221; όλες τις πληροφορίες που υπάρχουν γύρω σας. Στη συνέχεια παίζετε τις 5 αισθήσεις (Αφή, Όσφρηση, Γεύση, Όραση και [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=488&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="font-family:Verdana;font-size:9pt;">Πριν λίγες μέρες ανέβηκε στο Videogames Laboratory forum <a href="http://videogameslab.freeforums.org/senses-t33.html" target="_blank">ένα post για το παιχνίδι Senses</a> του Σταύρου Κοκκινέα. Σύμφωνα με το δημιουργό του, το concept του παιχνιδιού είναι το εξής: «Ξεκινάτε σε ένα δωμάτιο όπου πρέπει να &#8220;φάτε&#8221; όλες τις πληροφορίες που υπάρχουν γύρω σας. Στη συνέχεια παίζετε τις 5 αισθήσεις (Αφή, Όσφρηση, Γεύση, Όραση και Ακοή) μέχρι να φτάσετε στο τελευταίο επίπεδο όπου μπορείτε πλέον να νιώσετε (Feel).». Είναι ένα ενδιαφέρον, experimental, παιχνίδι που κάνει μια προσπάθεια μίξης αφήγησης και δράσης. Έχει μερικά προβλήματα στο χειρισμό, που οφείλονται σε ένα μεγάλο βαθμό στην πλατφόρμα GameMaker στο οποίο κατασκευάστηκε, και ο βαθμός δυσκολίας του ίσως αποτρέψει μερικούς (όπως και ο χρόνος να ξεκινήσει το παιχνίδι!).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Αν και στο blog αυτό δεν κάνω συνήθως παρουσιάσεις παιχνιδιών, αναφέρομαι στο παιχνίδι αυτό και στον δημιουργό για δυο λόγους.<br />
</span></p>
<p><span style="font-family:Verdana;"><span style="font-size:9pt;">Α) Ακούω από πολλούς (και φοιτητές μου) ότι ενδιαφέρονται να ακολουθήσουν μια επαγγελματική καριέρα στην βιομηχανία ανάπτυξης βιντεοπαιχνιδιών, όταν όμως τους ρωτώ πόσα παιχνίδια έχουν αναπτύξει στον ελεύθερο τους χρόνο (προγραμματισμό, σχεδιασμό ή περιεχόμενο) η απάντηση που λαμβάνω είναι σταθερά </span><span style="font-size:10pt;"><strong>0</strong></span><span style="font-size:9pt;">. Τα εν λόγω άτομα έχουν από ελάχιστες ως απειροελάχιστες πιθανότητες να εργαστούν πραγματικά στην βιομηχανία. Ο Σταύρος είναι ένα άτομο που ενδιαφέρεται να ασχοληθεί με την ανάπτυξη βιντεοπαιχνιδιών <strong>και κάνει κάτι για αυτό</strong>. Ξεκινώντας με απλά παιχνίδια αποκτά γνώσεις ανάπτυξης βιντεοπαιχνιδιών και χτίζει σταθερά ένα πολύτιμο portfolio για όταν θα έρθει η ώρα να κάνει αιτήσεις σε εταιρίες.<br />
</span></span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Β) Ο Σταύρος δεν έχει γνώσεις προγραμματισμού, για το λόγο αυτό βασίστηκε στη πλατφόρμα GameMaker. Γνωρίζω ότι το Videogames Laboratory παρακολουθούν πολλοί προγραμματιστές, που ίσως θα ενδιαφέρονταν να τον βοηθήσουν να αναπτύξει το ίδιο παιχνίδι σε κάποιο καλύτερο περιβάλλον. Το ΧΝΑ Game Studio είναι κατάλληλο για αυτό το παιχνίδι και οι γνώσεις που έχουμε αποκτήσει μέχρι στιγμής στα <a href="http://videogameslab.wordpress.com/index/">tutorial του blog</a> είναι υπερ-αρκετές. Το Flash είναι μια άλλη πιθανή πλατφόρμα. Φυσικά ο προγραμματιστής είναι ελεύθερος να χρησιμοποιήσει οποιοδήποτε περιβάλλον με το οποίο νιώθει μεγαλύτερη οικειότητα.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Ο ενδιαφερόμενος/ενδιαφερόμενη ας επικοινωνήσει μαζί μου μέσω της <a href="http://videogameslab.wordpress.com/contact/" target="_blank">φόρμας επικοινωνίας</a>. Με το <a href="http://videogameslab.wordpress.com/2009/10/20/imaginecup/" target="_blank">Imagine Cup</a> δεν υπήρξε αποτέλεσμα, μόνο από μερικοί προγραμματιστές δήλωσαν ενδιαφέρον. Ίσως είναι καιρός να αρχίσουμε τη συνεργασία μεταξύ προγραμματιστών-καλλιτεχνών από μερικά απλά παιχνίδια (2-3 δημιουργών) και να προχωρήσουμε από εκεί. Η περίπτωση του Senses είναι μια καλή ευκαιρία.<br />
</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/488/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/488/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/488/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/488/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/488/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/488/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/488/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/488/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/488/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/488/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=488&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/12/14/senses-%cf%80%cf%81%cf%8c%cf%83%ce%ba%ce%bb%ce%b7%cf%83%ce%b7-%ce%b3%ce%b9%ce%b1-%ce%b2%ce%b5%ce%bb%cf%84%ce%af%cf%89%cf%83%ce%b7-%cf%80%ce%b1%ce%b9%cf%87%ce%bd%ce%b9%ce%b4%ce%b9%ce%bf%cf%8d/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>
	</item>
		<item>
		<title>Διαλέξεις μαθήματος «Τεχνολογίες Ψυχαγωγικού Λογισμικού»</title>
		<link>http://videogameslab.wordpress.com/2009/12/10/videogame-lectures/</link>
		<comments>http://videogameslab.wordpress.com/2009/12/10/videogame-lectures/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 14:07:07 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>
		<category><![CDATA[Βιομηχανία βιντεοπαιχνιδιών]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=484</guid>
		<description><![CDATA[Πριν λίγο καιρό ανέβασα στην ιστοσελίδα του βιβλίου «Βιντεοπαιχνίδια: Βιομηχανία και Ανάπτυξη», ως συνοδευτικό υλικό, τις παρουσιάσεις (σε Powerpoint) που χρησιμοποιώ για τις διαλέξεις του μαθήματος «Τεχνολογίες Ψυχαγωγικού Λογισμικού» στο Τμήμα Πληροφορικής του Ιονίου Πανεπιστημίου. 
Οι διαλέξεις καλύπτουν θέματα όπως η Ιστορία και εξέλιξη των βιντεοπαιχνιδιών, η βιομηχανία βιντεοπαιχνιδιών σήμερα, τα είδη των παιχνιδιών, το [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=484&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="font-family:Verdana;font-size:9pt;">Πριν λίγο καιρό ανέβασα στην ιστοσελίδα του βιβλίου «<a href="http://videogamesbook.wordpress.com" target="_blank">Βιντεοπαιχνίδια: Βιομηχανία και Ανάπτυξη</a>», ως συνοδευτικό υλικό, <a href="http://videogamesbook.wordpress.com/extra/" target="_blank">τις παρουσιάσεις (σε Powerpoint)</a> που χρησιμοποιώ για τις διαλέξεις του μαθήματος «Τεχνολογίες Ψυχαγωγικού Λογισμικού» στο <a href="http://www.ionio.gr/depts/cs/" target="_blank">Τμήμα Πληροφορικής</a> του Ιονίου Πανεπιστημίου. </span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Οι διαλέξεις καλύπτουν θέματα όπως η Ιστορία και εξέλιξη των βιντεοπαιχνιδιών, η βιομηχανία βιντεοπαιχνιδιών σήμερα, τα είδη των παιχνιδιών, το προφίλ του χρήστη, διαθέσιμες πλατφόρμες παιχνιδιών, επιχειρηματικά μοντέλα και μάρκετινγκ, Internet και ψυχαγωγικό λογισμικό, διαδικτυακά παιχνίδια πολλών χρηστών (MMOGs), η οικονομία και παραοικονομία τους, εναλλακτικές εφαρμογές βιντεοπαιχνιδιών (serious games), ο κοινωνικός αντίκτυπος, θέματα εθισμού και βίας στα βιντεοπαιχνίδια. Επίσης παρουσιάζουν αρχές θεωρίας σχεδιασμού βιντεοπαιχνιδιών, τις φάσεις ανάπτυξης, την ομάδα ανάπτυξης και τις ειδικότητες που απαιτούνται για την ανάπτυξη βιντεοπαιχνιδιών. Τέλος εξετάζεται ο προγραμματισμός ψυχαγωγικού λογισμικού, διαθέσιμα εργαλεία, διαφορές για κάθε πλατφόρμα, οι μηχανές παιχνιδιών, η ανάπτυξη και διαχείριση ψηφιακού περιεχομένου.</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Αν και δεν έχουν όλες οι διαλέξεις άμεση σχέση με την ανάπτυξη βιντεοπαιχνιδιών, παρόλα αυτά ως δημιουργοί βιντεοπαιχνιδιών πρέπει να έχουμε μια συνολική θεώρηση της βιομηχανίας και τις επίδρασης των βιντεοπαιχνιδιών. <a href="http://videogamesbook.wordpress.com/extra/" target="_blank">Πιθανών να ενδιαφέρουν κάποιους από εσάς</a>.<br />
</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/484/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/484/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/484/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/484/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/484/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/484/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/484/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/484/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/484/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/484/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=484&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/12/10/videogame-lectures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>
	</item>
		<item>
		<title>Arkanoid: Σχεδιασμός πίστας</title>
		<link>http://videogameslab.wordpress.com/2009/12/07/arkanoid-level-design/</link>
		<comments>http://videogameslab.wordpress.com/2009/12/07/arkanoid-level-design/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 08:02:23 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[Arkanoid]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[XNA Game Studio]]></category>
		<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>
		<category><![CDATA[Προγραμματισμός]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=473</guid>
		<description><![CDATA[Κοιτάζοντας το πότε ανέβασα το τελευταίο άρθρο στο blog διαπιστώνω ότι έχει περάσει πάνω από ένας μήνας! Ακόμα περισσότερο έχουμε να ασχοληθούμε με το Arkanoid. Ήταν δύσκολες οι προηγούμενες εβδομάδες στο Πανεπιστήμιο με τις προθεσμίες για προτάσεις χρηματοδότησης και άρθρα  σε περιοδικά να διαδέχονται η μία την άλλη. Και ενώ είχα γράψει το κώδικα [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=473&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="font-family:Verdana;font-size:9pt;">Κοιτάζοντας το πότε ανέβασα το τελευταίο άρθρο στο blog διαπιστώνω ότι έχει περάσει πάνω από ένας μήνας! Ακόμα περισσότερο έχουμε να ασχοληθούμε με το Arkanoid. Ήταν δύσκολες οι προηγούμενες εβδομάδες στο Πανεπιστήμιο με τις προθεσμίες για προτάσεις χρηματοδότησης και άρθρα  σε περιοδικά να διαδέχονται η μία την άλλη. Και ενώ είχα γράψει το κώδικα για το σχεδιασμό πίστας στο Arkanoid δεν έβρισκα το χρόνο να γράψω το κείμενο. Τώρα όμως χαλάρωσαν λίγο τα πράγματα και επανερχόμαστε στην ενεργό δράση!<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Είχαμε αφήσει το Arkanoid σε μια σχετικά πλήρη μορφή με <a href="http://videogameslab.wordpress.com/category/arkanoid/" target="_blank">ανίχνευση συγκρούσεων, κίνηση μπάλας και ρακέτας, καταγραφή σκορ και απώλειας ζωής του παίκτη</a>. Επιπλέον είχαμε υλοποιήσει game state management με τις διάφορες οθόνες και καταστάσεις του παιχνιδιού (εισαγωγή, παιχνίδι, παύση, νίκη και αποτυχία παίκτη). Αυτό που λείπει είναι η δυνατότητα να σχεδιάζουμε τη πίστα του παιχνιδιού με περισσότερο φιλικό και εύχρηστο τρόπο, καθώς και η προσθήκη πολλών επιπέδων στο παιχνίδι.</span><br />
<span id="more-473"></span><br />
<span style="font-family:Verdana;font-size:9pt;">Μέχρι στιγμής στο Arkanoid χρησιμοποιούμε το παρακάτω κώδικα για να σχεδιάσουμε τη πίστα και να τοποθετήσουμε τα τουβλάκια στην οθόνη:<br />
</span></p>
<pre class="brush: csharp;">
for (int j = 0; j &lt; numOfRows; j++)
{
    for (int i = 0; i &lt; bricksPerRow; i++)
    {
        Rectangle rect = new Rectangle(i * (brickWidth + brickSpacing),
                                       rowStart + j * (brickHeight + brickSpacing),
                                       brickWidth, brickHeight);
        bricks[j * bricksPerRow + i] = new Brick(rect, Color.Red, whiteTile);
        numOfVisibleBricks++;
    }
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Με ένα for-loop δηλαδή τοποθετούμε τα τουβλάκια, ανά τακτά διαστήματα, σε γραμμές και στήλες. Αυτός το τρόπος σχεδιασμού πίστας (level design) είναι πολύ δύσχρηστος και επιβάλλει στο σχεδιαστή της πίστας να συνεργάζεται άμεσα με το προγραμματιστή έτσι ώστε να του υποδεικνύει τι αλλαγές πρέπει να γίνουν στο σχέδιο της πίστας και πού. Επίσης κάθε αλλαγή στο σχεδιασμό της πίστας συνεπάγεται compile του κώδικα του παιχνιδιού, μια χρονοβόρα διαδικασία. Επιπλέον είναι αρκετά δύσκολο να αλλάξεις το σχέδιο της πίστας σε κάτι άλλο από γραμμές με τουβλάκια. Από την άλλη είναι επιθυμητό ο σχεδιαστής να μην ασχολείται καθόλου με το κώδικα του παιχνιδιού, να σχεδιάζει με κάποιο τρόπο τη πίστα και να μεταφέρει το αποτέλεσμα στο προγραμματιστή για απεικόνιση. Η σχεδίαση δηλαδή να γίνεται με βάση τα δεδομένα (πχ αρχείο θέσεων) και όχι το κώδικα (data-driven development), όπως γίνεται άλλωστε και στη βιομηχανία ανάπτυξης βιντεοπαιχνιδιών.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Στο <a href="http://videogameslab.wordpress.com/2009/10/29/videogames-laboratory-challenge-2/" target="_blank">2<sup>ο</sup> Videogames Laboratory Challenge</a> είχα ζητήσει από τους αναγνώστες του blog να προτείνουν βελτιώσεις στο τρόπο αυτό σχεδιασμού της πίστας. Προτάθηκαν διάφορες λύσεις, από εύκολες, όπως να διαβάζουμε τις θέσεις των τούβλων από αρχείο μέχρι πιο πολύπλοκες, όπως ένα εξειδικευμένο πρόγραμμα που να επιτρέπει το σχεδιασμό της πίστας με οπτικό τρόπο (visual editor). Στα πλαίσια του άρθρου θα υλοποιήσουμε την απλούστερη λύση, δηλαδή να διαβάζει το παιχνίδι τη θέση των τούβλων από αρχείο. Στο μέλλον θα κάνουμε μια παρουσίαση πιο ολοκληρωμένων προτάσεων που βασίζονται σε editor.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Δεν είναι πολλές οι αλλαγές που πρέπει να κάνουμε στον υπάρχοντα κώδικα για να υλοποιήσουμε τη λειτουργία αυτή. Καταρχάς πρέπει να καθορίσουμε τη μορφή και το περιεχόμενο του αρχείου κειμένου που θα περιέχει το σχέδιο της πίστας. Κάνουμε τις εξής παραδοχές:<br />
</span></p>
<ul>
<li><span style="font-family:Verdana;font-size:9pt;">Μια γραμμή κειμένου στο αρχείο θα αντιστοιχεί σε μια γραμμή τούβλων στην οθόνη<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;">Οι γραμμές τούβλων στην οθόνη αρχίζουν από το πάνω μέρος (Υ=0)<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;">Χρησιμοποιούμε τους χαρακτήρες R, G, B, Y, W για να δηλώσουμε τη θέση τούβλων χρώματος κόκκινο, πράσινο, μπλε, κίτρινο και άσπρο<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;">Ο χαρακτήρας &#8216;.&#8217; υποδηλώνει κενό τούβλο<br />
</span></li>
<li><span style="font-family:Verdana;font-size:9pt;">Οι γραμμές κειμένου στο αρχείο πρέπει να έχουν όλες το ίδιο μέγεθος<br />
</span></li>
</ul>
<p><span style="font-family:Verdana;font-size:9pt;">Με βάση τις παραδοχές αυτές το αρχείο που περιγράφει μια πίστα στο παιχνίδι θα μπορούσε να είναι:<br />
</span></p>
<p><span style="font-family:Courier New;font-size:10pt;">&#8230;&#8230;&#8230;&#8230;.</span><br />
<span style="font-family:Courier New;font-size:10pt;">&#8230;&#8230;&#8230;&#8230;.</span><br />
<span style="font-family:Courier New;font-size:10pt;">..RRRRRRRRR..</span><br />
<span style="font-family:Courier New;font-size:10pt;">..GGGGGGGGG..</span><br />
<span style="font-family:Courier New;font-size:10pt;">&#8230;.BBBBB&#8230;.</span><br />
<span style="font-family:Courier New;font-size:10pt;">..BYBBBBBYB..</span><br />
<span style="font-family:Courier New;font-size:10pt;">..YY&#8230;..YY..</span><br />
<span style="font-family:Courier New;font-size:10pt;">..GGGGGGGGG..</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Θα αφήσουμε ελεύθερο τον αριθμό των τούβλων σε μια γραμμή (επιλογή σχεδιαστή) και θα προσαρμόζουμε το πλάτος του κάθε τούβλου ανάλογα. Με κάποιο πρόγραμμα επεξεργασίας κειμένου (καλύτερη επιλογή μάλλον το Notepad), φτιάχνουμε ένα αρχείο με το όνομα Level01.txt και σχεδιάζουμε τη πίστα με τις παραπάνω προδιαγραφές. Μπορείτε να κάνετε copy-paste το παραπάνω σχέδιο επίσης. Προσοχή, το αρχείο πρέπει να είναι απλό ASCII και όχι κάποιο άλλο format.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Στην συνέχεια, στο Content project του Arkanoid, επιλέγουμε δεξί-κλικ Add/Existing Item και επιλέγουμε το Level01.txt. Όταν το αρχείο εμφανιστεί στη λίστα του Content κάνουμε δεξί κλικ και επιλέγουμε Properties από το μενού. Στις ιδιότητες του αρχείου αυτού επιλέγουμε <strong>Build Action: None</strong> και <strong>Copy to Output: Copy if newer</strong>.<br />
</span></p>
<p><img src="http://videogameslab.files.wordpress.com/2009/12/120709_0802_arkanoid1.png" alt="" /><span style="font-family:Verdana;font-size:9pt;"><br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Ο λόγος που το κάνουμε αυτό είναι γιατί δεν θέλουμε να επεξεργαστεί το αρχείο αυτό το Content Pipeline του XNA, το οποίο θα του αλλάξει μορφοποίηση και θα συμπιέσει το περιεχόμενο του. Το θέλουμε ως απλό αρχείο κειμένου για να το διαβάσουμε κατά την αρχικοποίηση του παιχνιδιού. Είμαστε έτοιμη να φορτώσουμε το αρχείο με το σχέδιο πίστας.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Θα κάνουμε αρχικά μερικές μικρές αλλαγές στο κώδικα. Καταρχάς θα χρησιμοποιήσουμε ένα List για να αποθηκεύσουμε στη μνήμη τα τουβλάκια και όχι ένα πίνακα. Οι διαφορές μεταξύ των δύο είναι μικρές όσον αφορά τη λειτουργικότητα. Στην περίπτωση μας βολεύει η List γιατί δεν απαιτεί να ορίσω το μέγεθος της εκ των προτέρων όπως πρέπει σε ένα πίνακα. Μπορεί να δεσμεύσει περισσότερη μνήμη μόνη της αν χρειαστεί σύμφωνα με τον αριθμό των τούβλων που ορίζει το αρχείο.<br />
</span></p>
<pre class="brush: csharp;">
    public class Game1 : Microsoft.Xna.Framework.Game
    {
//υπόλοιπος κωδικας
        List&lt;string&gt; lines;
        List&lt;Brick&gt; bricks;
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Στην αρχή της κλάσης Game1 ορίζω 2 μεταβλητές List μια για τις γραμμές κειμένου του αρχείου (lines) και μια για τα τουβλάκια που θα αποθηκεύσω στη μνήμη. Στην Initialize(), δημιουργώ τα αντίστοιχα αντικείμενα List για τα lines και bricks. Οι λίστες είναι κενές σε αυτό το σημείο.<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Initialize()
        {
		//υπόλοιπος κωδικας
            lines = new List&lt;string&gt;();
            bricks = new List&lt;Brick&gt;();

            base.Initialize();
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Το αρχείο θα το διαβάσουμε στην LoadContent, όπως όλα τα αρχεία περιεχομένου (τεχνικά δεν χρειάζεται εδώ αλλά είναι καλή πρακτική).<br />
</span></p>
<pre class="brush: csharp;">
        protected override void LoadContent()
        {
		//υπόλοιπος κωδικας

            string path = Path.Combine(StorageContainer.TitleLocation, &quot;Content/Level01.txt&quot;);

            StreamReader reader = new StreamReader(path);
            string line = reader.ReadLine();
            while (line != null)
            {
                lines.Add(line);
                line = reader.ReadLine();
            }
            reader.Close();
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Καταρχάς συνθέτουμε τη διαδρομή που βρίσκεται το αρχείο level01.txt. Αυτό το κάνουμε προσθέτοντας το όνομα του αρχείου &#8220;Content/Level01.txt&#8221; στην εξορισμού τοποθεσία στην οποία αποθηκεύει το περιεχόμενο το XNA, StorageContainer.TitleLocation. Το αποτέλεσμα το κρατάμε σε μια μεταβλητή path.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Για να φορτώσουμε ένα αρχείο με τη χρήση C#/.NET θα χρησιμοποιήσουμε ένα αντικείμενο reader τύπου StreamReader το οποίο μπορεί να διαβάσει χαρακτήρες κειμένου. Το StreamReader παίρνει ως όρισμα το (πλήρες) όνομα του αρχείου κειμένου. Στην συνέχεια διαβάζουμε το αρχείο γραμμή-γραμμή (reader.ReadLine()) και προσθέτουμε τη κάθε γραμμή στη λίστα lines. Όταν διαβάσουμε όλο το αρχείο (line==null), τότε κλείνουμε το reader καλώντας τη μέθοδο του Close(), για να αποδεσμεύσουμε τους πόρους του συστήματος. Κατά την ανάγνωση του αρχείου δεν κάνουμε καμιά προσπάθεια να εξασφαλίσουμε το ότι ο αριθμός τούβλων είναι ίδιος σε κάθε γραμμή, χάριν ευκολίας, είναι όμως κάτι το οποίο θα πρέπει να έχουμε υπόψη μας.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Για να ολοκληρώσουμε το κώδικα πρέπει να αξιοποιήσουμε τη λίστα lines για να τοποθετήσουμε τα τουβλάκια στην οθόνη. Αυτό γίνεται στην resetGame().<br />
</span></p>
<pre class="brush: csharp;">
        private void resetGame()
        {
            paddle = new Rectangle(150, 550, 90, 15);
            paddleSpeed = 10;

            ball = new Rectangle(150, 400, 15, 15);
            ballDirection = new Vector2(1, -1);
            ballDirection.Normalize();
            ballSpeed = 5;

            lives = 3;
            score = 0;

            bricksPerRow = lines[0].Length;
            brickWidth = (viewWidth - (bricksPerRow - 1) * brickSpacing) / bricksPerRow;

            bricks.Clear();

            for (int j = 0; j &lt; lines.Count; j++)
            {
                for (int i = 0; i &lt; lines[j].Length; i++)
                {
                    Rectangle rect = new Rectangle(i * (brickWidth + brickSpacing),
                                                   j * (brickHeight + brickSpacing),
                                                   brickWidth, brickHeight);
                    switch (lines[j][i])
                    {
                        case 'R':
                            bricks.Add(new Brick(rect, Color.Red, whiteTile));
                            break;
                        case 'G':
                            bricks.Add(new Brick(rect, Color.Green, whiteTile));
                            break;
                        case 'B':
                            bricks.Add(new Brick(rect, Color.Blue, whiteTile));
                            break;
                        case 'Y':
                            bricks.Add(new Brick(rect, Color.Yellow, whiteTile));
                            break;
                        case 'W':
                            bricks.Add(new Brick(rect, Color.White, whiteTile));
                            break;

                    }
                }
            }
            numOfVisibleBricks = bricks.Count;
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Ο αριθμός των τούβλων ανά γραμμή καθορίζεται από το μήκος της πρώτης γραμμής κειμένου της λίστας list (list[0].Length). Το πλάτος κάθε τούβλου καθορίζεται τώρα με βάση αυτό. Στην συνέχεια, σε ένα διπλό for-loop, διατρέχουμε όλες τις γραμμές τις λίστας list και για κάθε γραμμή εξετάζουμε το κάθε χαρακτήρα της με ένα switch-statement. Αν ο χαρακτήρας είναι κάποιος από τους R, G, B, Y, W, τότε προσθέτουμε ένα τουβλάκι αντίστοιχου χρώματος στη λίστα bricks. Στην ουσία το αρχείο κειμένου με το σχέδιο της πίστας ουσιαστικά δημιουργεί ένα πλέγμα (grid), σε κάθε κελί του οποίου μπορεί να υπάρχει ή όχι ένα τουβλάκι. Επιπλέον το γεγονός ότι δημιουργούμε ένα Rectangle για κάθε θέση του πλέγματος, ανεξάρτητα από το αν αυτό περιέχει τουβλάκι ή όχι δεν είναι και πολύ αποδοτικό. Ο αριθμός numOfVisibleBricks τον οποίο χρησιμοποιούμε για να διαπιστώσουμε αν ο παίκτης έχει χτυπήσει όλα τα τουβλάκια στην οθόνη (μειώνοντας τον κατά ένα με κάθε σύγκρουση) είναι τώρα ίσος με τον αριθμό των τούβλων στη λίστα bricks. Τέλος μια παρατήρηση, ο χαρακτήρας &#8216;.&#8217; που θέσαμε ως κενό χαρακτήρα δεν χρησιμοποιείται στην πραγματικότητα είναι περισσότερο «οπτική διευκόλυνση» για εμάς που σχεδιάζουμε τη πίστα.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Τρέχοντας το παιχνίδι βλέπουμε τη νέα πίστα στην οθόνη μας όπως τη σχεδιάσαμε.<br />
</span></p>
<p><img src="http://videogameslab.files.wordpress.com/2009/12/120709_0802_arkanoid2.png" alt="" /><span style="font-family:Verdana;font-size:9pt;"><br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Ο κώδικας του παιχνιδιού είναι διαθέσιμος μέσω SVN από το <a href="http://code.google.com/p/videogameslab/" target="_blank">Code Repository</a> καθώς και σε <a href="http://videogameslab.googlecode.com/files/Arcanoid_part5.zip" target="_blank">zip μορφή</a>.</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Στο επόμενο και τελευταίο άρθρο στη σειρά ανάπτυξης του Arkanoid θα προσθέσουμε τη δυνατότητα για διαφορετικά επίπεδα (πίστες) στο παιχνίδι.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Μέχρι τότε μπορείτε να ανεβάσετε τα δικά σας ευφάνταστα σχέδια πίστας του Arkanoid στο <a href="http://videogameslab.freeforums.org/arkanoid-t14.html" target="_blank">forum</a>. Τα πιο πρωτότυπα θα χρησιμοποιηθούν ως πίστες στη τελική έκδοση του Arkanoid που θα δημιουργήσουμε στο επόμενο tutorial.<br />
</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/473/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/473/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/473/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/473/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/473/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/473/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/473/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/473/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/473/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/473/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=473&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/12/07/arkanoid-level-design/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>

		<media:content url="http://videogameslab.files.wordpress.com/2009/12/120709_0802_arkanoid1.png" medium="image" />

		<media:content url="http://videogameslab.files.wordpress.com/2009/12/120709_0802_arkanoid2.png" medium="image" />
	</item>
		<item>
		<title>Προγραμματίστε το δικό σας παιχνίδι</title>
		<link>http://videogameslab.wordpress.com/2009/11/05/pong-konsnos/</link>
		<comments>http://videogameslab.wordpress.com/2009/11/05/pong-konsnos/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 07:20:23 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[XNA Game Studio]]></category>
		<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>
		<category><![CDATA[Προγραμματισμός]]></category>
		<category><![CDATA[Στο Τύπο]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=466</guid>
		<description><![CDATA[Ο αναγνώστης του Videogames Laboratory konsnos έγραψε ένα πολύ καλό και πολύ επεξηγηματικό άρθρο στο PC WORLD σχετικά με την ανάπτυξη του Pong, βασισμένος στο κώδικα του παιχνιδιού που αναπτύξαμε στη πρώτη σειρά tutorial. Αν για κάποιο λόγο σας φάνηκαν τα tutorial εκείνα δύσκολα ή δυσνόητα αξίζει να ρίξετε μια ματιά στο άρθρο αυτό καθώς [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=466&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="font-family:Verdana;font-size:9pt;">Ο αναγνώστης του Videogames Laboratory konsnos έγραψε ένα πολύ καλό και πολύ επεξηγηματικό άρθρο στο PC WORLD σχετικά με την ανάπτυξη του Pong, βασισμένος στο κώδικα του παιχνιδιού που αναπτύξαμε στη <a href="http://videogameslab.wordpress.com/category/pong/" target="_blank">πρώτη σειρά tutorial</a>. Αν για κάποιο λόγο σας φάνηκαν τα tutorial εκείνα δύσκολα ή δυσνόητα αξίζει να ρίξετε μια ματιά στο άρθρο αυτό καθώς ο συγγραφέας παρουσιάζει το θέμα ακόμα πιο απλά και κατανοητά.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Μπορείτε να βρείτε το σχετικό άρθρο <a href="http://www.pcw.gr/Article/Latest/program_computer_game_pong_DIY_/179-4703.html" target="_blank">εδώ</a>.</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">ΥΓ: Υπάρχουν άλλες προτάσεις για το Videogames Laboratory Challenge #2;</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/466/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/466/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/466/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/466/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/466/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/466/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/466/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/466/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/466/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/466/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=466&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/11/05/pong-konsnos/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>
	</item>
		<item>
		<title>Videogames Laboratory Challenge #2</title>
		<link>http://videogameslab.wordpress.com/2009/10/29/videogames-laboratory-challenge-2/</link>
		<comments>http://videogameslab.wordpress.com/2009/10/29/videogames-laboratory-challenge-2/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 13:02:24 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Arkanoid]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Challenge]]></category>
		<category><![CDATA[XNA Game Studio]]></category>
		<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>
		<category><![CDATA[Προγραμματισμός]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=462</guid>
		<description><![CDATA[Η περίοδος αυτή αποδεικνύεται η πιο πολυάσχολη του χρόνου με τις προθεσμίες αιτήσεων για χρηματοδότηση έρευνας στο Πανεπιστήμιο να πλησιάζουν ταχύτατα. Αυτό έχει αντίκτυπο και στο blog μιας ο διαθέσιμος ελεύθερος χρόνος μου έχει συρρικνωθεί. Μέχρι να βρω λοιπόν το χρόνο να ολοκληρώσω τη σειρά tutorial για το Arkanoid, σκέφτηκα να εμπλέξω τους αναγνώστες του [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=462&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="font-family:Verdana;font-size:9pt;">Η περίοδος αυτή αποδεικνύεται η πιο πολυάσχολη του χρόνου με τις προθεσμίες αιτήσεων για χρηματοδότηση έρευνας στο Πανεπιστήμιο να πλησιάζουν ταχύτατα. Αυτό έχει αντίκτυπο και στο blog μιας ο διαθέσιμος ελεύθερος χρόνος μου έχει συρρικνωθεί. Μέχρι να βρω λοιπόν το χρόνο να ολοκληρώσω τη σειρά tutorial για το Arkanoid, σκέφτηκα να εμπλέξω τους αναγνώστες του blog με ένα Videogames Laboratory Challenge. Στην ουσία είναι το δεύτερο challenge μιας και το πρώτο αφορούσε την <a href="http://videogameslab.wordpress.com/2009/08/13/squash-the-bugs/" target="_blank">εκσφαλμάτωση ενός παιχνιδιού</a> (και για το οποίο έλαβα ελάχιστες απαντήσεις δυστυχώς).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Μέχρι στιγμής στο <a href="http://videogameslab.wordpress.com/category/arkanoid/" target="_blank">Arkanoid</a> χρησιμοποιούμε το παρακάτω κώδικα για να σχεδιάσουμε τη πίστα και να τοποθετήσουμε τα τουβλάκια στην οθόνη:<br />
</span></p>
<pre class="brush: csharp;">
            for (int j = 0; j &lt; numOfRows; j++)
            {
                for (int i = 0; i &lt; bricksPerRow; i++)
                {
                    Rectangle rect = new Rectangle(i * (brickWidth + brickSpacing),
                                                   rowStart + j * (brickHeight + brickSpacing),
                                                   brickWidth, brickHeight);
                    bricks[j * bricksPerRow + i] = new Brick(rect, Color.Red, whiteTile);
                    numOfVisibleBricks++;
                }
            }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Σε ένα for-loop δηλαδή τοποθετούμε τα τουβλάκια, ανά τακτά διαστήματα, σε γραμμές και στήλες. Αυτός το τρόπος σχεδιασμού πίστας (level design) είναι πολύ δύσχρηστος και επιβάλλει στο σχεδιαστή της πίστας να συνεργάζεται άμεσα με το προγραμματιστή έτσι ώστε να του υποδεικνύει τι αλλαγές πρέπει να γίνουν στο σχέδιο της πίστας και πού (και να γίνεται πάλι compile ο κώδικας με κάθε αλλαγή). Επιπλέον είναι αρκετά δύσκολο να αλλάξεις το σχέδιο της πίστας σε κάτι άλλο από γραμμές με τουβλάκια. Από την άλλη είναι επιθυμητό ο σχεδιαστής να μην ασχολείται καθόλου με το κώδικα του παιχνιδιού, να σχεδιάζει με κάποιο τρόπο τη πίστα και να μεταφέρει το αποτέλεσμα στο προγραμματιστή για απεικόνιση (data-driven development), όπως γίνεται άλλωστε και στη βιομηχανία ανάπτυξης βιντεοπαιχνιδιών.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Η πρόκληση λοιπόν αφορά το εξής:<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;"><strong>Προτείνετε τρόπους με τους οποίους μπορεί να γίνει ο σχεδιασμός της πίστας πιο εύκολος και ευέλικτος. Προσοχή, με τον όρο σχεδιασμό αναφέρομαι στο καθορισμό της τοποθεσίας που θα καταλήξει το κάθε τουβλάκι. Η τοποθέτηση και απεικόνιση καθαυτή θα γίνει με κώδικα αναγκαστικά.</strong><br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Αν ο τρόπος που προτείνετε είναι «καλύτερος» από αυτόν που έχω εγώ υπόψη (και σε λογικό επίπεδο δυσκολίας για ένα εισαγωγικό tutorial), θα γίνει υλοποίηση αυτού στο επόμενο tutorial (με τιμές και δάφνες στο άτομο που το πρότεινε). Σε κάθε περίπτωση μπορείτε και κάνετε την υλοποίηση οι ίδιοι και να ανεβάσετε το κώδικα στο <a href="http://videogameslab.wordpress.com/2009/07/23/code-repository-2/" target="_blank">Code Repository</a>. Απορίες και διευκρινίσεις στα σχόλια του post.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Περιμένουμε τις συμμετοχές σας!<br />
</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/462/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=462&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/10/29/videogames-laboratory-challenge-2/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>
	</item>
		<item>
		<title>Διαγωνισμός Imagine Cup 2010</title>
		<link>http://videogameslab.wordpress.com/2009/10/20/imaginecup/</link>
		<comments>http://videogameslab.wordpress.com/2009/10/20/imaginecup/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 07:18:15 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[XNA Game Studio]]></category>
		<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>
		<category><![CDATA[Νέα]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=460</guid>
		<description><![CDATA[Ξεκίνησε και φέτος ο διεθνής διαγωνισμός της Microsoft Imagine Cup ο οποίος έχει 4 κατηγορίες: Ανάπτυξη Λογισμικού, Προγραμματισμό Βιντεοπαιχνιδιών, Διαχείριση Συστημάτων και Δικτύων και Δημιουργία Ψηφιακού Βίντεο. Σύμφωνα με τη Microsoft, σκοπός του διαγωνισμού είναι να βοηθήσει τους φοιτητές να βελτιώσουν τον κόσμο μέσω τεχνολογικών λύσεων. Φέτος είναι η έβδομη χρονιά του διαγωνισμού.

Κάθε χρονιά ο [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=460&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="color:black;font-family:Verdana;font-size:9pt;">Ξεκίνησε και φέτος ο διεθνής διαγωνισμός της Microsoft Imagine Cup ο οποίος έχει 4 κατηγορίες: Ανάπτυξη Λογισμικού, <strong>Προγραμματισμό Βιντεοπαιχνιδιών</strong>, Διαχείριση Συστημάτων και Δικτύων και Δημιουργία Ψηφιακού Βίντεο. Σύμφωνα με τη Microsoft, σκοπός του διαγωνισμού είναι να βοηθήσει τους φοιτητές να βελτιώσουν τον κόσμο μέσω τεχνολογικών λύσεων. Φέτος είναι η έβδομη χρονιά του διαγωνισμού.<br />
</span></p>
<p><span style="color:black;font-family:Verdana;font-size:9pt;">Κάθε χρονιά ο διαγωνισμός έχει διαφορετικό θέμα, φέτος είναι: «Φανταστείτε έναν κόσμο όπου η τεχνολογία μας βοηθάει να λύσουμε τα μεγαλύτερα προβλήματα που αντιμετωπίζει ο κόσμος μας σήμερα». Τα Ηνωμένα Έθνη έχουν προσδιορίσει τα προβλήματα αυτά σαν τους «Στόχους της Χιλιετίας». Περισσότερες πληροφορίες σχετικά με τους στόχους της χιλιετίας, μπορείτε να βρείτε <a href="http://www.un.org/millenniumgoals/" target="_blank"><span style="text-decoration:underline;">εδώ</span></a>.<br />
</span></p>
<p><span style="color:black;font-family:Verdana;font-size:9pt;">Η χώρα μας έχει πετύχει στο παρελθόν σημαντικές διακρίσεις στο διαγωνισμό, με ομάδες να κατακτούν ακόμα και τη δεύτερη θέση στους παγκόσμιους τελικούς, οι οποίοι φέτος θα διεξαχθούν στην Πολωνία.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;"><span style="color:black;">Οι κατηγορίες του διαγωνισμού είναι 4:</span><br />
</span></p>
<ul>
<li><a href="http://imaginecup.com/Competition/mycompetitionportal.aspx?competitionId=37" target="_blank"><span style="color:black;font-family:Verdana;font-size:9pt;text-decoration:underline;">Software Design</span></a><span style="font-family:Verdana;font-size:9pt;"><span style="color:black;"> – Σχεδίαση/κατασκευή λογισμικού</span><br />
</span></li>
<li><a href="http://imaginecup.com/Competition/mycompetitionportal.aspx?competitionId=39" target="_blank"><span style="color:black;font-family:Verdana;font-size:9pt;text-decoration:underline;">Digital Media</span></a><span style="font-family:Verdana;font-size:9pt;"><span style="color:black;"> – Δημιουργία Animation/video</span><br />
</span></li>
<li><a href="http://imaginecup.com/Competition/mycompetitionportal.aspx?competitionId=38" target="_blank"><span style="color:black;font-family:Verdana;font-size:9pt;text-decoration:underline;">Game Design</span></a><span style="font-family:Verdana;font-size:9pt;"><span style="color:black;"> – προγραμματισμός παιχνιδιού </span><br />
</span></li>
<li>
<div><a href="http://imaginecup.com/Competition/mycompetitionportal.aspx?competitionId=41" target="_blank"><span style="color:black;font-family:Verdana;font-size:9pt;text-decoration:underline;">IT Challenge</span></a><span style="font-family:Verdana;font-size:9pt;"><span style="color:black;"> – Ανάπτυξη IT συστημάτων</span><br />
</span></div>
</li>
</ul>
<p><span style="color:black;font-family:Verdana;font-size:9pt;">Ειδικότερα, στόχος της κατηγορίας Game Design είναι η ανάπτυξη ενός παιχνιδιού χρησιμοποιώντας τόσο το XNA Game Studio όσο και το Visual Studio. Είναι μια ευκαιρία για τους συμμετέχοντες που ασχολούνται με game development να κατασκευάσουν ένα παιχνίδι το οποίο συμβάλλει στην ενημέρωση του πληθυσμού για τα προβλήματα του πλανήτη. Μπορείτε να δείτε παραδείγματα τέτοιων παιχνιδιών, τα επονομαζόμενα serious games <a href="http://www.gamesforchange.org/" target="_blank">εδώ</a>.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Δικαίωμα  συμμετοχής έχουν ομάδες από 1 μέχρι 4 άτομα και έναν υπεύθυνο καθηγητή. <span style="color:black;">Περισσότερες πληροφορίες για το διαγωνισμό μπορείτε να δείτε <a href="http://www.imaginecup.com/" target="_blank"><span style="text-decoration:underline;">εδώ</span></a>.<br />
</span></span></p>
<p><span style="color:black;font-family:Verdana;font-size:9pt;">Αν έχετε κάποια ιδέα για παιχνίδι σχετικό με το θέμα του διαγωνισμού αλλά δεν είστε μέλος ομάδας ανάπτυξης μπορείτε να <a href="http://videogameslab.wordpress.com/contact/" target="_blank">επικοινωνήσετε μαζί μου</a>. Επιπλέον αν θέλετε να συμμετάσχετε στην ανάπτυξη ενός τέτοιου παιχνιδιού ακόμα και αν δεν έχετε κάποια συγκεκριμένη ιδέα, μπορείτε και πάλι να επικοινωνήσετε μαζί μου. Ίσως μπορέσουμε να συγκεντρώσουμε ικανό αριθμό ατόμων για να φτιάξουμε μια ομάδα ανάπτυξης βιντεοπαιχνιδιού για το διαγωνισμό αυτό.</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/460/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/460/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/460/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/460/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/460/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/460/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/460/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/460/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/460/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/460/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=460&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/10/20/imaginecup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>
	</item>
		<item>
		<title>Arkanoid: Game State Management μέρος 2ο</title>
		<link>http://videogameslab.wordpress.com/2009/10/06/arkanoid-game-state-part2/</link>
		<comments>http://videogameslab.wordpress.com/2009/10/06/arkanoid-game-state-part2/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 10:00:46 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Arkanoid]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[XNA Game Studio]]></category>
		<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>
		<category><![CDATA[Προγραμματισμός]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=452</guid>
		<description><![CDATA[Στο προηγούμενο tutorial σχεδιάσαμε το game state management του Arkanoid και το υλοποιήσαμε για την διαδικασία Update του παιχνιδιού. Σήμερα θα το υλοποιήσουμε και για την διαδικασία Draw, συμπληρώνοντας παράλληλα το παιχνίδι με Εισαγωγική οθόνη, λειτουργία Pause και οθόνη επιτυχίας ή αποτυχίας του παίκτη.
Είχαμε αναφέρει ότι το game state management υλοποιείται στην απλή μορφή του [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=452&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="font-family:Verdana;font-size:9pt;">Στο <a href="http://videogameslab.wordpress.com/2009/10/02/arkanoid-part3/" target="_blank">προηγούμενο tutorial</a> σχεδιάσαμε το game state management του Arkanoid και το υλοποιήσαμε για την διαδικασία Update του παιχνιδιού. Σήμερα θα το υλοποιήσουμε και για την διαδικασία Draw, συμπληρώνοντας παράλληλα το παιχνίδι με Εισαγωγική οθόνη, λειτουργία Pause και οθόνη επιτυχίας ή αποτυχίας του παίκτη.</span><br />
<span id="more-452"></span><span style="font-family:Verdana;font-size:9pt;">Είχαμε αναφέρει ότι το game state management υλοποιείται στην απλή μορφή του με ένα switch-statement. Το ίδιο ακριβώς swith-statement (το σκελετό δηλαδή) που χρησιμοποιήσαμε στην Update θα χρησιμοποιήσουμε και στην Draw. Πριν αρχίσουμε όμως, χάριν ευαναγνωσιμότητας(!) του κώδικα, θα κάνουμε και πάλι μια μικρή αναδιοργάνωση του κώδικα της Draw, δημιουργώντας μια νέα μέθοδο renderWorld() η οποία θα απεικονίζει όλα τα αντικείμενα του παιχνιδιού (τουβλάκια, ρακέτα, μπάλα και σκορ) στην οθόνη:<br />
</span></p>
<pre class="brush: csharp;">
        private void renderWorld()
        {
            string message = String.Format(&quot;Lives: {0}, Score: {1}&quot;, lives, score);

            spriteBatch.DrawString(font, message, new Vector2(10, 10), Color.Yellow);

            foreach (Brick brick in bricks)
            {
                brick.Draw(spriteBatch);
            }

            spriteBatch.Draw(whiteTile, paddle, Color.White);
            spriteBatch.Draw(whiteTile, ball, Color.Yellow);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Όπως και στην updateWorld(), καμιά νέα λειτουργία δεν συμπεριλαμβάνεται στην renderWorld(). Ο κώδικας της Draw() γίνεται τώρα:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            renderWorld();
            spriteBatch.End();

            base.Draw(gameTime);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Τίποτα το συγκλονιστικό μέχρις εδώ. Προσθέτουμε τώρα το switch-statement που αναφέραμε παραπάνω:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();

            switch (gameState)
            {
                case GameState.Intro:

                    break;
                case GameState.Playing:

                    renderWorld();

                    break;
                case GameState.Paused:

                    break;
                case GameState.Won:

                    break;
                case GameState.Lost:

                    break;
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Αν παρατηρήσατε, μετακίνησα τη renderWorld() στο block του GameState.Playing, μια και λογικά πρέπει να απεικονίζουμε τα αντικείμενα του παιχνιδιού όταν ο παίκτης παίζει. Ας προσθέσουμε την εισαγωγική οθόνη τώρα. Σε ένα οποιοδήποτε σχεδιαστικό πρόγραμμα φτιάχνουμε με μεγάλα γράμματα το λογότυπο του παιχνιδιού. Εγώ το έφτιαξα σε Fireworks και το έσωσα ως logo.png. Μπορείτε επιπλέον να το αποθηκεύσετε ως jpg, gif και bmp.<br />
</span></p>
<p><img src="http://videogameslab.files.wordpress.com/2009/10/100609_1000_arkanoidgam1.png" alt="" /><span style="font-family:Verdana;font-size:9pt;"><br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Προσθέτουμε το αρχείο του λογότυπου στο Content project του παιχνιδιού (δεξί κλικ επάνω στο όνομα, Add/New Item).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Για να χρησιμοποιήσουμε την υφή στο παιχνίδι θα ορίσουμε μια μεταβλητή logoTexture στην κυρίως κλάση του παιχνιδιού:<br />
</span></p>
<pre class="brush: csharp;">
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        …

        Texture2D logoTexture;
        …
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Στην LoadContent φορτώνουμε την υφή ως συνήθως:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void LoadContent()
        {
       	 …

            whiteTile = Content.Load&lt;Texture2D&gt;(&quot;white_tile&quot;);
            logoTexture = Content.Load&lt;Texture2D&gt;(&quot;logo&quot;);

        	…
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Στην Draw τώρα, στο block GameState.Intro, απλά απεικονίζουμε την υφή με τη χρήση της spritebatch στην τοποθεσία (50,150):<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();

            switch (gameState)
            {
                case GameState.Intro:

                    spriteBatch.Draw(logoTexture, new Vector2(50,150), Color.White);

                    break;

                case GameState.Playing:
                    renderWorld();
                    break;

                case GameState.Paused:
                    break;

                case GameState.Won:
                    break;

                case GameState.Lost:
                    break;
            }

            spriteBatch.End();
            base.Draw(gameTime);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Προσοχή πρέπει να δοθεί στο τρόπο χρήσης της spriteBatch.Draw (), δεν έχω ορίσει Rectangle μέσα στο οποίο θα απεικονιστεί η υφή, την τοποθεσία στην οποία θα απεικονιστεί. Για το λόγο αυτό η spriteBatch.Draw() θα την απεικονίσει στο φυσικό της μέγεθος (χωρίς μεγέθυνση ή σμίκρυνση).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Αν τρέξουμε τώρα το παιχνίδι με F5, θα δούμε την εισαγωγική οθόνη του παιχνιδιού με το λογότυπο:<br />
</span></p>
<p><img src="http://videogameslab.files.wordpress.com/2009/10/100609_1000_arkanoidgam2.png" alt="" /><span style="font-family:Verdana;font-size:9pt;"><br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Επειδή έχουμε υλοποιήσει ήδη το state machine στην Update, αν πατήσουμε ENTER το παιχνίδι θα αρχίσει. Όμως ο παίκτης δεν το ξέρει αυτό και θα πρέπει να τον ενημερώσουμε με σχετικό μήνυμα. Γνωρίζουμε ήδη πώς να απεικονίζουμε κείμενο στην οθόνη με τη χρήση της spriteBatch.DrawString. Επειδή στο παιχνίδι θέλω σε πολλές περιπτώσεις να απεικονίζω κείμενο στο κέντρο της οθόνης, όσον αφορά τη Χ διάσταση σε οποιοδήποτε ύψος Υ, θα φτιάξω μια βοηθητική μέθοδο που θα το κάνει αυτόματα αυτό:<br />
</span></p>
<pre class="brush: csharp;">
        private void renderStringCentered(string message, int Y, Color color)
        {
            Vector2 msgSize = font.MeasureString(message);
            spriteBatch.DrawString(font, message, new Vector2((viewWidth - msgSize.X) / 2, Y), color);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Η μέθοδος renderStringCentered() παίρνει ως όρισμα το κείμενο, το ύψος Y στο οποίο θέλω να εμφανίζεται και το χρώμα του. Στην συνέχεια υπολογίζει το πλάτος του κειμένου με τη χρήση της μεθόδου font.MeasureString(). Το font είναι το αντικείμενο που περιέχει τη γραμματοσειρά που φορτώσαμε από το δίσκο και που χρησιμοποιούμε για να απεικονίσουμε κείμενο. Το αντικείμενο αυτό ξέρει το πλάτος και το ύψος κάθε χαρακτήρα της γραμματοσειράς. Οπότε αν του δώσουμε ως όρισμα το κείμενο που θέλουμε να απεικονίσουμε αυτό θα μας επιστρέψει το ύψος και το πλάτος του σε pixel, σε μια μεταβλητή τύπου Vector2. Τέλος η renderStringCentered() απεικονίζει το κείμενο στην οθόνη με τη χρήση της spriteBatch.DrawString() χρησιμοποιώντας το πλάτος του κειμένου που υπολογίσαμε προηγουμένως (msgSize.X) για να κεντράρει το κείμενο στην οθόνη.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Επιπλέον, για να κάνω την εισαγωγική οθόνη σχετική με το παιχνίδι θα απεικονίσω πίσω από το λογότυπο μερικές σειρές τουβλάκια:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();

            switch (gameState)
            {
                case GameState.Intro:

                    for (int j = 0; j &lt; 10; j++)
                    {
                        for (int i = 0; i &lt; bricksPerRow; i++)
                        {
                            Rectangle rect = new Rectangle(i * (brickWidth + brickSpacing),
                                                           100 + j * (brickHeight + brickSpacing),
                                                           brickWidth, brickHeight);

                            spriteBatch.Draw(whiteTile, rect, Color.LimeGreen);
                        }
                    }

                    spriteBatch.Draw(logoTexture, new Vector2(50,150), Color.White);
                    renderStringCentered( &quot;Press [Enter] to begin&quot;,430, Color.White);
                    break;

                case GameState.Playing:
                    renderWorld();
                    break;

                case GameState.Paused:
                    break;

                case GameState.Won:
                    break;

                case GameState.Lost:
                    break;
            }

            spriteBatch.End();
            base.Draw(gameTime);
        }
</pre>
<p><span style="font-size:9pt;"><span style="font-family:Verdana;">Απεικονίζουμε 10 σειρές τουβλάκια πίσω από το λογότυπο με πράσινο χρώμα. Επιπλέον απεικονίζουμε τη προτροπή στο χρήστη να πατήσει το ENTER για να ξεκινήσει το παιχνίδι (προτάσεις για καλύτερες επιλογές χρώματων δεκτές! </span><span style="font-family:Wingdings;">J</span><span style="font-family:Verdana;"> ).<br />
</span></span></p>
<p><img src="http://videogameslab.files.wordpress.com/2009/10/100609_1000_arkanoidgam3.png" alt="" /><span style="font-family:Verdana;font-size:9pt;"><br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Έχουμε μέχρι στιγμής υλοποιήσει τις καταστάσεις GameState.Intro και GameState.Playing. Οι υπόλοιπες καταστάσεις είναι ακόμα πιο απλές. Για τη Paused το μόνο που έχουμε να κάνουμε είναι να δείξουμε στο χρήστη ότι το παιχνίδι έχει «παγώσει».<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();

            switch (gameState)
            {
//υπόλοιπος κώδικας

                case GameState.Paused:
                    renderWorld();
                    renderStringCentered(&quot;PAUSED!&quot;, 270, Color.Yellow);
                    break;

//υπόλοιπος κώδικας
            }

            spriteBatch.End();
            base.Draw(gameTime);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Η κατάσταση αυτή μπορεί να λάβει χώρα όταν ο παίκτης παίζει το παιχνίδι, οπότε είναι καλό μαζί με το μήνυμα να απεικονίζουμε στο φόντο και τα αντικείμενα του παιχνιδιού (αλλιώς θα φαινόταν παράξενο να βλέπει το «PAUSED» σε μια μαύρη οθόνη). Το μόνο που έχουμε να κάνουμε είναι να καλέσουμε τη renderWorld() λίγο πριν απεικονίσουμε το κείμενο. Επειδή στην Update δεν ανανεώνουμε τις θέσεις των αντικειμένων του παιχνιδιού όταν το παιχνίδι βρίσκεται σε κατάσταση GameState.Paused, τα αντικείμενα δεν μετακινούνται και έτσι απλά υλοποιείται η λειτουργία Paused. Το παιχνίδι ξαναρχίζει όταν ο παίκτης πατήσει το πλήκτρο P ξανά.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Οι καταστάσεις GameState.Won και GameState.Lost έχουν ακριβώς την ίδια λογική:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();

            switch (gameState)
            {
//υπόλοιπος κώδικας

                case GameState.Won:
                    renderWorld();
                    renderStringCentered(&quot;YOU WIN!&quot;, 270, Color.Yellow);
                    renderStringCentered(&quot;Press Enter to play again&quot;, 300, Color.White);
                    break;

                case GameState.Lost:
                    renderWorld();
                    renderStringCentered(&quot;YOU LOSE!&quot;, 270, Color.Yellow);
                    renderStringCentered(&quot;Press Enter to play again&quot;, 300, Color.White);
                    break;
            }

            spriteBatch.End();
            base.Draw(gameTime);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Στις περιπτώσεις αυτές εμφανίζουμε το ανάλογο μήνυμα επιτυχίας ή αποτυχίας στο παίκτη και τον προτρέπουμε να πατήσει ENTER για να παίξει ξανά. Αν πατήσει το ESC το παιχνίδι θα τον μεταφέρει στην Εισαγωγική οθόνη.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Αυτό ήταν, το game state management, μαζί με τις διάφορες οθόνες του παιχνιδιού (σχεδόν) υλοποιήθηκε. Μένουν 2-3 (ουσιαστικές) λεπτομέρειες. Καταρχάς δεν έχουμε ορίσει ακόμα πως το παιχνίδι θα μεταβαίνει στη κατάσταση Won ή Lost. Η Lost είναι απλή, το μόνο που έχουμε να κάνουμε είναι να ελέγξουμε στην updateWorld αν ο παίκτης έχει χάσει όλες τις ζωές του.<br />
</span></p>
<pre class="brush: csharp;">
        private void updateWorld()
        {
            //υπόλοιπος κώδικας

            //check if player lost all lives
            if (lives &lt;= 0)
            {
                gameState = GameState.Lost;
            }
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Το αν κέρδισε είναι λίγο πιο πολύπλοκο, πρέπει να διαπιστώσουμε αν όλα τα τουβλάκια στην οθόνη έχουν καταστραφεί. Ο πιο απλός τρόπος να υλοποιήσουμε αυτή τη λειτουργία είναι να ορίσουμε μια μεταβλητή numOfVisibleBricks στη κλαση Game1 που να μειώνεται κατά ένα κάθε φορά που καταστρέφεται ένα τουβλάκι μέχρι να γίνει 0.<br />
</span></p>
<pre class="brush: csharp;">
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        int numOfVisibleBricks;
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Στην LoadContent αυξάνω τη τιμή της μεταβλητής κάθε φορά που δημιουργώ ένα νέο τουβλάκι με τη χρήση του τελεστή new:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void LoadContent()
        {
            //υπόλοιπος κώδικας

            for (int j = 0; j &lt; numOfRows; j++)
            {
                for (int i = 0; i &lt; bricksPerRow; i++)
                {
                    Rectangle rect = new Rectangle(i * (brickWidth + brickSpacing),
                                                   rowStart + j * (brickHeight + brickSpacing),
                                                   brickWidth, brickHeight);
                    bricks[j * bricksPerRow + i] = new Brick(rect, Color.Red, whiteTile);
                    numOfVisibleBricks++;
                }
            }
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Τέλος στην updateWorld, μειώνω την τιμή της κατά ένα, κάθε φορά που διαπιστώνω σύγκρουση μπάλας με τουβλάκι.<br />
</span></p>
<pre class="brush: csharp;">
       private void updateWorld()
        {
            //υπόλοιπος κώδικας

            //check ball-brick collision
            foreach (Brick brick in bricks)
            {
                if (brick.CheckHit(ball))
                {
                    numOfVisibleBricks--;
                    ballDirection.Y = -ballDirection.Y;
                    score += 1000;
                    if (score % 10000 == 0)
                    {
                        ballSpeed += 1;
                    }
                    break;
                }
            }

            //check if player lost all lives
            if (lives &lt;= 0)
            {
                gameState = GameState.Lost;
            }
            else if (numOfVisibleBricks &lt;= 0)
            {
                gameState = GameState.Won;
            }
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Παράλληλα, στο τέλος της updateWorld, ελέγχω μήπως ο αριθμός των ορατών bricks έχει φτάσει στο μηδέν. Σε μια τέτοια περίπτωση αλλάζω το state του παιχνιδιού σε GameState.Won και το παιχνίδι τελειώνει.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Υπάρχουν και πιο κομψοί τρόποι να υλοποιηθεί αυτό (από μια global μεταβλητή εννοώ). Γενικά στα παιχνίδια στα οποία υπάρχουν πολλά «όμοια» αντικείμενα (διαστημόπλοια, εχθροί, τουβλάκια, συστήματα σωματιδίων κλπ), συνήθως ορίζουμε ένα αντικείμενο-manager το οποίο αναλαμβάνει τη διαχείριση τους, το οποίο είναι υπεύθυνο και για πληροφορίες όπως αυτή που ζητάμε. Αυτό είναι όμως κάτι που θα γνωρίσουμε σε επόμενο παιχνίδι.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Αν τρέξετε το παιχνίδι τώρα και πατήσετε ΕΝΤΕR για να αρχίσει και P για να παγώσει, θα παρατηρήσετε ότι άλλες φορές ενεργοποιείται το πάγωμα και άλλες όχι. Αυτό συμβαίνει και με άλλες λειτουργίες στο παιχνίδι και οφείλεται στο ότι το παιχνίδι αλλάζει πολλές φορές state όσο ένα πλήκτρο (το P στην περίπτωση μας είναι πατημένο). Πρέπει συνεπώς να υλοποιήσουμε μια λειτουργία που να μου επιστρέφει true όταν το κάποιο πλήκτρο πατήθηκε για πρώτη φορά και false όσο είναι πατημένο.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Καταρχάς πρέπει να ορίσουμε μια μεταβλητή previousKeyboardState η οποία θα κρατά το keyboardState του προηγούμενου καρέ (frame) του παιχνιδιού:<br />
</span></p>
<pre class="brush: csharp;">
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        int numOfVisibleBricks;
        GameState gameState;
        KeyboardState keyboardState;
        KeyboardState previousKeyboardState;
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Στην συνέχεια, πριν ολοκληρώσουμε την Update του τρέχοντος καρέ, αποθηκεύουμε το keyboardState στην μεταβλητή αυτή:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Update(GameTime gameTime)
        {
            //υπόλοιπος κώδικας

            previousKeyboardState = keyboardState;

            base.Update(gameTime);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Τώρα είμαστε έτοιμοι να υλοποιήσουμε τη μέθοδο που να επιστρέφει true μόνο όταν το δεδομένο πληκτρο key πατιέται για πρώτη φορά.<br />
</span></p>
<pre class="brush: csharp;">
        private bool keyPressed(Keys key)
        {
            if (previousKeyboardState.IsKeyUp(key) &amp;&amp; keyboardState.IsKeyDown(key))
            {
                return true;
            }
            return false;
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Αν στο προηγούμενο καρέ το πλήκτρο key ήταν ελεύθερο (previousKeyboardState.IsKeyUp(key)) και στο τρέχον καρέ είναι πατημένο (keyboardState.IsKeyDown(key)), τότε επιστρέφουμε true, διαφορετικά false.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Θα αξιοποιήσουμε τη μέθοδο αυτή στην Update σε 3 game states:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Update(GameTime gameTime)
        {
            keyboardState = Keyboard.GetState();

            switch (gameState)
            {
                case GameState.Intro:
                    if (keyPressed(Keys.Escape))
                    {
                        this.Exit();
                    }
                    else if (keyboardState.IsKeyDown(Keys.Enter))
                    {
                        gameState = GameState.Playing;
                    }
                break;
                case GameState.Playing:
                    if (keyboardState.IsKeyDown(Keys.Escape))
                    {
                        gameState = GameState.Intro;
                    }
                    else if (keyPressed(Keys.P))
                    {
                        gameState = GameState.Paused;
                    }
                    else
                    {
                        updateWorld();
                    }
                    break;
                case GameState.Paused:
                    if (keyPressed(Keys.P))
                    {
                        gameState = GameState.Playing;
                    }
                    break;

               //υπόλοιπος κώδικας

            }

            previousKeyboardState = keyboardState;

            base.Update(gameTime);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Στο GameState.Intro, επειδή φτάνουμε στην κατάσταση αυτή με ESC από άλλες καταστάσεις (την ώρα που παίζει ο χρήστης, ή βρίσκεται σε οθόνη αποτυχίας), πρέπει να εξασφαλίσουμε ότι ο χρήστης πάτησε μια ακόμα φορά το ESC πριν κλείσουμε εντελώς το παιχνίδι (αλλιώς θα βγει από το παιχνίδι χωρίς να το έχει επιλέξει). Τέλος για τη λειτουργία Pause μιλήσαμε, πρέπει να ενεργοποιείται και απενεργοποιείται με διακριτά πατήματα του πλήκτρου P.<br />
</span></p>
<p><span style="font-size:9pt;"><span style="font-family:Verdana;">Όποιος έχει μείνει ζωντανός μέχρι σ&#8217;αυτό το σημείο το έχει κάνει από την αστείρευτη επιθυμία και επιμονή του να δει το παιχνίδι ολοκληρωμένο οπότε δεν μπορώ να του το στερήσω αυτό. Οι υπόλοιποι έχουν έτσι κι αλλιώς αποκοιμηθεί ή τα παρατήσει οπότε δεν θα τους πειράξει </span><span style="font-family:Wingdings;">J</span><span style="font-family:Verdana;">. Μένει ακόμα κάτι να υλοποιήσουμε πριν ολοκληρώσουμε το game state management και αυτό είναι η δυνατότητα του παίκτη να ξαναρχίζει τη πίστα από την αρχή. Χρειαζόμαστε ένα τρόπο να απεικονίζουμε ξανά τα τουβλάκια στις αρχικές τους θέσεις, να μηδενίζουμε το σκορ και να επαναρχικοποιουμε τις ζωές του παίκτη και να τοποθετούμε ρακέτα και μπάλα εκεί που ήταν αρχικά.<br />
</span></span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Μέχρι στιγμής αυτές τις λειτουργίες τις κάναμε εν μέρει στην μέθοδο Initialize() και εν μέρει στην LoadContent(). Αυτό που θα πρέπει να γίνει είναι να μεταφέρουμε όλες τις αρχικοποιήσεις σε μια μέθοδο την οποία θα μπορούμε να  καλούμε από οπουδήποτε:<br />
</span></p>
<pre class="brush: csharp;">
        private void resetGame()
        {
            paddle = new Rectangle(150, 550, 90, 15);
            paddleSpeed = 10;

            ball = new Rectangle(150, 400, 15, 15);
            ballDirection = new Vector2(1, -1);
            ballDirection.Normalize();
            ballSpeed = 5;

            lives = 3;
            score = 0;

            numOfVisibleBricks = 0;
            for (int j = 0; j &lt; numOfRows; j++)
            {
                for (int i = 0; i &lt; bricksPerRow; i++)
                {
                    Rectangle rect = new Rectangle(i * (brickWidth + brickSpacing),
                                                   rowStart + j * (brickHeight + brickSpacing),
                                                   brickWidth, brickHeight);
                    bricks[j * bricksPerRow + i] = new Brick(rect, Color.Red, whiteTile);
                    numOfVisibleBricks++;
                }
            }
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Η resetGame() πραγματοποιεί όλες τις αρχικοποιήσεις που αναφέραμε. Προσοχή πρέπει να δοθεί στο ότι οι αντίστοιχες αρχικοποιήσεις έχουν αφαιρεθεί από τις Initialize() και LoadContent().<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Την resetGame θα την καλέσουμε από την Update κάθε φορά που θέλουμε να αρχικοποιήσουμε τη πίστα:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Update(GameTime gameTime)
        {
            keyboardState = Keyboard.GetState();

            switch (gameState)
            {
                case GameState.Intro:
                    if (keyPressed(Keys.Escape))
                    {
                        this.Exit();
                    }
                    else if (keyboardState.IsKeyDown(Keys.Enter))
                    {
                        resetGame();
                        gameState = GameState.Playing;
                    }
                break;

               //υπόλοιπος κώδικας

                case GameState.Won:
                    if (keyboardState.IsKeyDown(Keys.Escape))
                    {
                        gameState = GameState.Intro;
                    }
                    else if (keyboardState.IsKeyDown(Keys.Enter))
                    {
                        resetGame();
                        gameState = GameState.Playing;
                    }
                    break;
                case GameState.Lost:
                    if (keyboardState.IsKeyDown(Keys.Escape))
                    {
                        gameState = GameState.Intro;
                    }
                    else if (keyboardState.IsKeyDown(Keys.Enter))
                    {
                        resetGame();
                        gameState = GameState.Playing;
                    }
                    break;
            }

            previousKeyboardState = keyboardState;

            base.Update(gameTime);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Τη πίστα την αρχικοποιούμε στο block GameState.Intro, όταν ο παίκτης πατήσει το ENTER για να αρχίσει το παιχνίδι, όπως και στα block GameState.Won και GameState.Lost για τον ίδιο λόγο (να δοκιμάσει την πίστα ξανά).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Αυτό ήταν, τελειώσαμε για σήμερα (αλήθεια!). Το παιχνίδι είναι πλήρες από λειτουργίες και ο παίκτης μπορεί να δοκιμάσει τη πίστα όσες φορές θέλει.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Σήμερα καλύψαμε πολύ έδαφος. Το συμπέρασμα της ημέρας πρέπει να είναι ότι όσο απλό και αν είναι ένα παιχνίδι, απαιτεί πολύ συνοδευτικό κώδικα για να υλοποιήθούν λειτουργίες που δεν έχουν άμεση σχέση με τη διαδικασία παιχνιδιού, άλλα είναι απαραίτητες για την καλή εμπειρία του χρήστη.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Ο κώδικας του tutorial βρίσκεται στο <a href="http://code.google.com/p/videogameslab/" target="_blank">Code Repository</a> μέσω SVN ή και σε <a href="http://videogameslab.googlecode.com/files/Arcanoid_part4.zip" target="_blank">zip μορφή</a>. Στο επόμενο tutorial θα δούμε πως μπορούμε να φτιάξουμε διαφορετικές πίστες στο παιχνίδι.<br />
</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/452/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/452/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/452/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/452/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/452/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/452/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/452/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/452/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/452/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/452/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=452&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/10/06/arkanoid-game-state-part2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>

		<media:content url="http://videogameslab.files.wordpress.com/2009/10/100609_1000_arkanoidgam1.png" medium="image" />

		<media:content url="http://videogameslab.files.wordpress.com/2009/10/100609_1000_arkanoidgam2.png" medium="image" />

		<media:content url="http://videogameslab.files.wordpress.com/2009/10/100609_1000_arkanoidgam3.png" medium="image" />
	</item>
		<item>
		<title>Arkanoid: Game State Management</title>
		<link>http://videogameslab.wordpress.com/2009/10/02/arkanoid-part3/</link>
		<comments>http://videogameslab.wordpress.com/2009/10/02/arkanoid-part3/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 17:47:06 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Arkanoid]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[XNA Game Studio]]></category>
		<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>
		<category><![CDATA[Προγραμματισμός]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=441</guid>
		<description><![CDATA[Μέχρι στιγμής στο παιχνίδι Arkanoid (μέρος 1, μέρος 2) έχουμε υλοποιήσει την κλάση που εκπροσωπεί τα τουβλάκια (Brick) έχουμε τοποθετήσει τα τουβλάκια στην σωστή θέση, έχουμε υλοποιήσει κίνηση της μπάλας και της ρακέτας, συγκρούσεις μεταξύ των αντικειμένων του παιχνιδιού και αυξάνουμε και το σκορ του παίκτη. Το παιχνίδι είναι λειτουργικό, μπορεί να ελέγξει ο παίκτης [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=441&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="font-family:Verdana;font-size:9pt;">Μέχρι στιγμής στο παιχνίδι Arkanoid (<a href="http://videogameslab.wordpress.com/2009/09/14/arkanoid-part-1/" target="_blank">μέρος 1</a>, <a href="http://videogameslab.wordpress.com/2009/09/24/arkanoid-part2/" target="_blank">μέρος 2</a>) έχουμε υλοποιήσει την κλάση που εκπροσωπεί τα τουβλάκια (Brick) έχουμε τοποθετήσει τα τουβλάκια στην σωστή θέση, έχουμε υλοποιήσει κίνηση της μπάλας και της ρακέτας, συγκρούσεις μεταξύ των αντικειμένων του παιχνιδιού και αυξάνουμε και το σκορ του παίκτη. Το παιχνίδι είναι λειτουργικό, μπορεί να ελέγξει ο παίκτης τη μπάλα και να καταστρέψει τα τουβλάκια, αλλά δεν έχουμε ορίσει το πότε νικά και πότε χάνει ο παίκτης έτσι ώστε να σταματάμε το παιχνίδι και να του εμφανίζουμε το ανάλογο μήνυμα. Για να το κάνουμε λίγο πιο εύκολο και κομψό αυτό, θα κάνουμε ένα βήμα πίσω και θα υλοποιήσουμε στο παιχνίδι κάτι που ονομάζεται game state management (διαχείριση καταστάσεων παιχνιδιού;).</span><br />
<span id="more-441"></span><br />
<span style="font-family:Verdana;font-size:9pt;">Το game state management βασίζεται σε κάτι που ονομάζεται μηχανή καταστάσεων (state machine), η οποία είναι ένα σύνολο από καταστάσεις και κανόνες που ορίζουν μεταβάσεις μεταξύ των. Αυτό δεν είναι τόσο τρομακτικό όσο ακούγεται και το εξηγώ με ένα παράδειγμα. Φανταστείτε μια μέρα από τη ζωή σας. Το βράδυ βρίσκεστε στο κρεβάτι σας και κοιμάστε. Στις 8 το πρωί χτυπά το ξυπνητήρι και ξυπνάτε. Αν πεινάτε, μπορεί να φάτε πρωινό ή μπορεί και να φύγετε αμέσως για την δουλειά/σχολείο/πανεπιστήμιο σας. Στο σχολείο (ας πούμε), παρακολουθείτε το μάθημα μέχρι να χτυπήσει το κουδούνι, και μετά βγαίνετε διάλλειμα. Μετά ξαναχτυπά το κουδούνι και μπαίνετε στην τάξη. Όταν έρθει 2 η ώρα πηγαίνετε σπίτι. Εκεί, αν πεινάτε τρώτε και κοιμάστε, διαφορετικά κοιμάστε απευθείας (βαρετή ζωή ομολογουμένως).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Αν μελετήσετε την παραπάνω αφήγηση, μπορείτε να διακρίνετε ότι αποτελείται από καταστάσεις στις οποίες εσείς βρίσκεστε (κοιμάμαι, τρώω, παρακολουθώ μάθημα) και συμβάντα (κανόνες) που προκαλούν αλλαγή στην κατάσταση σας (ξυπνητήρι, κουδούνι). Μπορούμε να ζωγραφίσουμε λοιπόν στο χαρτί ένα σχήμα (γράφος) που να περιγράφει εποπτικά την παραπάνω αφήγηση ως εξής:<br />
</span></p>
<p><img src="http://videogameslab.files.wordpress.com/2009/10/100209_1747_arkanoidgam1.png" alt="" /><span style="font-family:Verdana;font-size:9pt;"><br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Κάθε έλλειψη περιέχει μια κατάσταση στην οποία μπορεί να βρίσκεται ο αναγνώστης. Τα βελάκια δείχνουν μεταβάσεις από μια κατάσταση σε μια άλλη όταν λάβει χώρα το συμβάν με μαύρα γράμματα που υπάρχει δίπλα σε κάθε γραμμή μετάβασης. Από την κατάσταση «κοιμάμαι» θα μεταβώ στην κατάσταση «ξύπνησα» όταν χτυπήσει το ξυπνητήρι. Από την κατάσταση «Παρακολουθώ μάθημα» θα μεταβώ στην κατάσταση «Διάλλειμα» όταν χτυπήσει το κουδούνι, και το αντίστροφο.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Ο γράφος αυτός καταστάσεων, και μεταβάσεων μεταξύ τους, ονομάζεται state machine (μηχανή καταστάσεων). Και επειδή ο αριθμός των καταστάσεων είναι περιορισμένος (όχι άπειρος), ο γράφος ονομάζεται πιο συγκεκριμένα <strong>finite state machine</strong> (μηχανή πεπερασμένων καταστάσεων).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">To finite state machine είναι από τα πιο χρήσιμα εργαλεία για την ανάπτυξη βιντεοπαιχνιδιών. Αν σκεφτεί κανείς ένα οποιοδήποτε παιχνίδι, αυτό βρίσκεται ανά πάσα στιγμή σε μια προκαθορισμένη κατάσταση: Εισαγωγή/Τίτλοι, Μενού, Παίξιμο, Παύση (Pause), Οθόνη νίκης, Οθόνη αποτυχίας κλπ. Για να μεταβούμε από την μια κατάσταση σε μια άλλη συνήθως πατάμε κάποιο πλήκτρο στο χειριστήριο ή στο πληκτρολόγιο.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Μπορούμε να αξιοποιήσουμε ένα finite state machine στο Arkanoid λοιπόν για να του δώσουμε μια εισαγωγική οθόνη και οθόνες νίκης και αποτυχίας στο παίκτη. Για να το κάνουμε αυτό χρειαζόμαστε 2 πράγματα, μια απαρίθμηση των καταστάσεων και μια μεταβλητή που θα κρατά την τρέχουσα κατάσταση. Στο αρχείο Game1.cs προσθέτουμε στην κορυφή (εκτός της κλάσης Game1):<br />
</span></p>
<pre class="brush: csharp;">
namespace Arcanoid
{
    public enum GameState
    {
        Intro,
        Playing,
        Paused,
        Lost,
        Won
    };
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Ορίζουμε 5 καταστάσεις στις οποίες μπορεί να βρίσκεται το παιχνίδι, την εισαγωγή (Intro), το κανονικό παίξιμο (Playing), την παύση (Paused), την αποτυχία (Lost) και τη νίκη (Won) του παίκτη. Το enum ορίζει ουσιαστικά ένα τύπο δεδομένων GameState ο οποίο μπορεί να πάρει μόνο κάποια από τις 5 αυτές τιμές. Μπορώ να ορίσω μια μεταβλητή τύπου GameState ως εξής:<br />
</span></p>
<pre class="brush: csharp;">
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GameState gameState;

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont font;
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Η μεταβλητή gameState θα μπορεί να λάβει λοιπόν μια από τις 5 προκαθορισμένες τιμές που περιγράφουν τη κατάσταση του παιχνιδιού. Από τη στιγμή που έχουμε ορίσει τις καταστάσεις του παιχνιδιού πρέπει να ορίσουμε πως θα γίνεται η μετάβαση από τη μια στην άλλη. Φτιάχνουμε ένα finite state machine ανάλογο με αυτό που περιγράψαμε παραπάνω:<br />
</span></p>
<p><img src="http://videogameslab.files.wordpress.com/2009/10/100209_1747_arkanoidgam2.png" alt="" /><span style="font-family:Verdana;font-size:9pt;"><br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Οι ελλείψεις με έντονο περίγραμμα σηματοδοτούν την αρχική και τελική κατάσταση του παιχνιδιού. Έχουμε μια έλλειψη για κάθε κατάσταση παιχνιδιού που αναφέραμε και τις μεταξύ τους μεταβάσεις που ορίζονται από κανόνες. Για παράδειγμα αν είμαστε στην αρχική οθόνη και ο παίκτης πατήσει το πλήκτρο ENTER τότε το παιχνίδι θα αρχίσει (θα αλλάξει η κατάσταση του σε Playing δηλαδή). Αν το παιχνίδι τρέχει (Playing) και ο παίκτης πατήσει το πλήκτρο P τότε το παιχνίδι θα παγώσει (Paused) και θα επιστρέψει στην κατάσταση Playing μόνο αν ο παίκτης ξαναπατήσει το πλήκτρο P. Από τη κατάσταση Playing ο παίκτης θα μεταβεί στη Lost όταν χάσει όλες τις ζωές του (lives = 0). Από την κατάσταση Playing θα μεταβεί στην κατάσταση Won (κερδίσει) μόνο όταν χτυπήσει όλα τα τουβλάκια, και ούτω κάθε εξής.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Με βάση το state machine που δημιουργήσαμε παραπάνω μπορούμε εύκολα να υλοποιήσουμε το game state management του παιχνιδιού μας. Το μόνο που έχουμε να ελέγξουμε είναι το σε ποια κατάσταση είμαστε κάθε χρονική στιγμή (gameState) και αν συντρέχει κάποιος λόγος (πάτημα πλήκτρου κλπ) να μεταβούμε σε κάποια άλλη κατάσταση. Δυνητικά αυτό θα μπορούσε να υλοποιηθεί με μια σειρά από if-then-else αλλά γρήγορα θα δημιουργούσε κώδικα δυσανάγνωστο. Παράδειγμα για την μετάβαση από Intro σε Playing και μόνο, θα είχαμε:<br />
</span></p>
<pre class="brush: csharp;">
            if (gameState == GameState.Intro)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                {
                    this.Exit();
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                {
                    gameState = GameState.Playing;
                }
            }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Και για τις 5 καταστάσεις η αναγνωσιμότητα του κώδικα θα μειωνόταν σημαντικά. Επιπλέον πολλά παιχνίδια έχουν πολλές περισσότερες από 5 καταστάσεις (αν είχε μενού, προφίλ παίκτη, βοήθεια, inventory κλπ).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Για το λόγω αυτό θα χρησιμοποιήσουμε ένα συνδυασμό switch-statement και αναδιοργάνωσης κώδικα. Το switch-statement είναι μια πιο κομψή έκδοση του if-then-else και υπάρχει σε όλες τις γλώσσες από C/C++/Java, μέχρι και Visual Basic. Στη μορφή που θα το χρησιμοποιήσουμε μοιάζει ως εξής:<br />
</span></p>
<pre class="brush: csharp;">
            switch (gameState)
            {
                case GameState.Intro:

                    break;
                case GameState.Playing:

                    break;
                case GameState.Paused:

                    break;
                case GameState.Won:

                    break;
                case GameState.Lost:

                    break;
            }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Ανάλογα με την τιμή της gameState, η εκτέλεση του κώδικα θα συνεχίσει σε κάποιο από τα &#8220;case GameState.XXXX&#8221;. Όταν ο κώδικας συναντήσει την εντολή break η εκτέλεση του συγκεκριμένου block κώδικα θα διακοπεί και θα συνεχίσει μετά το τέλος του switch.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Πριν προσθέσω αυτό το switch-statement στην μέθοδο Update(), θα κάνω μια μικρή αναδιαμόρφωση του κώδικα, δημιουργώντας μια νέα μέθοδο updateWorld() στην οποία θα μεταφέρω όλο το κώδικα της Update() που ασχολείται με την κίνηση των αντικειμένων και την ανίχνευση συγκρούσεων. Ο κώδικας αυτός εκτελείται μόνο στην περίπτωση του το παιχνίδι βρίσκεται στην κατάσταση Playing (ο παίκτης μπορεί και παίζει δηλαδή) και δεν αφορά της άλλες καταστάσεις. Εξάγοντας τον σε μια ξεχωριστή μέθοδο κάνω την Update() και το switch-statement πιο ευανάγνωστο:<br />
</span></p>
<pre class="brush: csharp;">
        private void updateWorld()
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Left))
            {
                paddle.X -= (int)paddleSpeed;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Right))
            {
                paddle.X += (int)paddleSpeed;
            }

            ball.X += (int)(ballDirection.X * ballSpeed);
            ball.Y += (int)(ballDirection.Y * ballSpeed);

            //check paddle-wall collision
            if (paddle.Left &lt; 0)
            {
                paddle.X = 0;
            }
            else if (paddle.Right &gt; viewWidth)
            {
                paddle.X = viewWidth - paddle.Width;
            }

            //check ball-wall collision
            if (ball.Left &lt;= 0 || ball.Right &gt;= viewWidth)
            {
                ballDirection.X = -ballDirection.X;
            }
            else if (ball.Top &lt;= 0 || ball.Bottom &gt;= viewHeight)
            {
                ballDirection.Y = -ballDirection.Y;

                if (ball.Bottom &gt;= viewHeight)
                {
                    lives--;
                }
            }

            //check ball-paddle collision
            if (ballDirection.Y &gt; 0 &amp;&amp;
                ball.Bottom &gt;= paddle.Top &amp;&amp;
                ((ball.Left &gt;= paddle.Left &amp;&amp; ball.Left &lt;= paddle.Right) ||
                  (ball.Right &gt;= paddle.Left &amp;&amp; ball.Right &lt;= paddle.Right))
                )
            {
                ballDirection.Y = -ballDirection.Y;
            }

            //check ball-brick collision
            foreach (Brick brick in bricks)
            {
                if (brick.CheckHit(ball))
                {
                    ballDirection.Y = -ballDirection.Y;
                    score += 1000;
                    break;
                }
            }

        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Η μέθοδος updateWorld() δεν περιέχει καμιά νέα λειτουργία. Την ορίζω ως private γιατί δεν έχω σκοπό να την καλέσω εκτός του κυρίως αντικειμένου του παιχνιδιού (Game1).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Έπειτα ορίζω μια μεταβλητή τύπου KeyboardState στην οποία θα αποθηκεύσω την κατάσταση του πληκτρολογίου (για να μην την ζητώ συνέχεια από την μέθοδο Keyboard.GetState()).<br />
</span></p>
<pre class="brush: csharp;">
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GameState gameState;
        KeyboardState keyboardState;
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Είμαστε έτοιμοι τώρα να ορίσουμε τις μεταβάσεις μεταξύ των διάφορων καταστάσεων στην Update. Διαβάζοντας το παραπάνω state machine που δημιουργήσαμε και μεταφράζοντας το σε κώδικα έχουμε:<br />
</span></p>
<pre class="brush: csharp;">
        protected override void Update(GameTime gameTime)
        {
            keyboardState = Keyboard.GetState();

            switch (gameState)
            {
                case GameState.Intro:
                    if (keyboardState.IsKeyDown(Keys.Escape))
                    {
                        this.Exit();
                    }
                    else if (keyboardState.IsKeyDown(Keys.Enter))
                    {
                        gameState = GameState.Playing;
                    }
                break;
                case GameState.Playing:
                    if (keyboardState.IsKeyDown(Keys.Escape))
                    {
                        gameState = GameState.Intro;
                    }
                    else if (keyboardState.IsKeyDown(Keys.P))
                    {
                        gameState = GameState.Paused;
                    }

                    updateWorld();

                    break;
                case GameState.Paused:
                    if (keyboardState.IsKeyDown(Keys.P))
                    {
                        gameState = GameState.Playing;
                    }
                    break;
                case GameState.Won:
                    if (keyboardState.IsKeyDown(Keys.Escape))
                    {
                        gameState = GameState.Intro;
                    }
                    else if (keyboardState.IsKeyDown(Keys.Enter))
                    {
                        gameState = GameState.Playing;
                    }
                    break;
                case GameState.Lost:
                    if (keyboardState.IsKeyDown(Keys.Escape))
                    {
                        gameState = GameState.Intro;
                    }
                    else if (keyboardState.IsKeyDown(Keys.Enter))
                    {
                        gameState = GameState.Playing;
                    }
                    break;
            }

            base.Update(gameTime);
        }
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Είναι αρκετά ξεκάθαρο το τι συμβαίνει στο switch-statement. Αν για παράδειγμα το gameState είναι ίσο με GameState.Intro, τότε ελέγχουμε αν το πλήκτρο ESC έχει πατηθεί. Αν ναι τότε βγαίνουμε από το παιχνίδι εντελώς. Αλλιώς, αν έχουμε πατήσει το ENTER, τότε η κατάσταση του παιχνιδιού (gameState) αλλάζει σε GameState.Playing. Την επόμενη φορά που θα κληθεί η Update, το switch-statement θα εκτελέσει το block που αφορά το GameState.Playing. Εκεί θα γίνει ο έλεγχος αν ο παίκτης έχει πατήσει το πλήκτρο ESC και σε μια τέτοια περίπτωση η κατάσταση του παιχνιδιού (gameState) θα αλλάξει σε GameState.Intro. Αλλιώς ελέγχεται αν έχει πατηθεί το πλήκτρο P και αυτή τη περίπτωση το παιχνίδι μεταβαίνει στην κατάσταση GameState.Paused. Επίσης στο block αυτό (GameState.Playing)  και μόνο καλούμε και την μέθοδο updateWorld() για να κινήσουμε αντικείμενα και να υπολογίσουμε συγκρούσεις. Παρόμοια είναι και η λογική για τις υπόλοιπες καταστάσεις. Ανάλογα με το πια κατάσταση βρίσκεται το παιχνίδι κάθε φορά και ανάλογα με κάποια συνθήκη το παιχνίδια θα μεταβεί στην προκαθορισμένη κατάσταση.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Μένουν αρκετά να κάνουμε έτσι ώστε να ολοκληρώσουμε το game state management και το tutorial έγινε αρκετά μεγάλο οπότε θα σταματήσουμε εδώ για σήμερα. Ήταν αρκετά θεωρητικό το άρθρο, αλλά δημιουργήσαμε την υποδομή για να προσθέσουμε στο επόμενο tutorial πολλές λειτουργίες όπως αρχική οθόνη, λειτουργία Pause, και οθόνες επιτυχίας και αποτυχίας στο παιχνίδι.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Νέος κώδικας δεν υπάρχει στο Code Repository. Όμως για να μην μείνετε παραπονεμένοι και να σας ανοίξει η όρεξη για περισσότερα πάρτε μια μικρή γεύση από το επόμενο tutorial:<br />
</span><br />
<span style="font-family:Verdana;font-size:9pt;"><br />
<img src="http://videogameslab.files.wordpress.com/2009/10/100209_1747_arkanoidgam3.png" alt="" /><br />
</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/441/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/441/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/441/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/441/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/441/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/441/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/441/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/441/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/441/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/441/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=441&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/10/02/arkanoid-part3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>

		<media:content url="http://videogameslab.files.wordpress.com/2009/10/100209_1747_arkanoidgam1.png" medium="image" />

		<media:content url="http://videogameslab.files.wordpress.com/2009/10/100209_1747_arkanoidgam2.png" medium="image" />

		<media:content url="http://videogameslab.files.wordpress.com/2009/10/100209_1747_arkanoidgam3.png" medium="image" />
	</item>
		<item>
		<title>Arkanoid μέρος 2ο</title>
		<link>http://videogameslab.wordpress.com/2009/09/24/arkanoid-part2/</link>
		<comments>http://videogameslab.wordpress.com/2009/09/24/arkanoid-part2/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 07:07:19 +0000</pubDate>
		<dc:creator>Κώστας Αναγνώστου</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Arkanoid]]></category>
		<category><![CDATA[XNA Game Studio]]></category>
		<category><![CDATA[Ανάπτυξη βιντεοπαιχνιδιών]]></category>
		<category><![CDATA[Προγραμματισμός]]></category>

		<guid isPermaLink="false">http://videogameslab.wordpress.com/?p=421</guid>
		<description><![CDATA[Ξεκινήσαμε με το προηγούμενο άρθρο τη δεύτερη σειρά tutorial πάνω στην ανάπτυξη βιντεοπαιχνιδιών, εστιάζοντας στο παιχνίδι Arkanoid αυτή τη φορά. Το άρθρο βγήκε αναγκαστικά μεγάλο διότι έπρεπε να ορίσουμε ένα νέο αντικείμενο το οποίο θα αναπαριστά το τουβλάκι στο παιχνίδι, καθώς και την συμπεριφορά του (απεικόνιση και έλεγχος συγκρούσεων). Με βάση τη κλάση αυτή δημιουργήσαμε [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=421&subd=videogameslab&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="font-family:Verdana;font-size:9pt;">Ξεκινήσαμε με το προηγούμενο <a href="http://videogameslab.wordpress.com/2009/09/14/arkanoid-part-1/" target="_blank">άρθρο</a> τη δεύτερη σειρά tutorial πάνω στην ανάπτυξη βιντεοπαιχνιδιών, εστιάζοντας στο παιχνίδι Arkanoid αυτή τη φορά. Το άρθρο βγήκε αναγκαστικά μεγάλο διότι έπρεπε να ορίσουμε ένα νέο αντικείμενο το οποίο θα αναπαριστά το τουβλάκι στο παιχνίδι, καθώς και την συμπεριφορά του (απεικόνιση και έλεγχος συγκρούσεων). Με βάση τη κλάση αυτή δημιουργήσαμε και απεικονίσαμε τις σειρές με τα τουβλάκια στην οθόνη. Επιπλέον ορίσαμε και απεικονίσαμε τη ρακέτα και την μπάλα.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Στο σημερινό άρθρο, για να το κρατήσουμε σε λογικό μέγεθος, θα προσθέσουμε στο παιχνίδι μόνο κίνηση της μπάλας και της ρακέτας, ανίχνευση συγκρούσεων (collision detection) και σκορ παίκτη.<br />
<span id="more-421"></span></span><span style="font-family:Verdana;font-size:9pt;">Το πώς υλοποιούμε την κίνηση της ρακέτας και της μπάλας το εξηγήσαμε κατά την δημιουργία του <a href="http://videogameslab.wordpress.com/2009/07/13/hello-pong-part-3/" target="_blank">Pong</a>. Ορίζουμε ένα Rectangle paddle το οποίο περιγράφει την θέση και το μέγεθος της ρακέτας, και παρομοίως ένα Rectangle ball για τη μπάλα. Επιπλέον χρειαζόμαστε ένα διάνυσμα Vector2 με το όνομα ballDirection το οποίο δείχνει την κατεύθυνση κίνησης της μπάλας και μια μεταβλητή ballSpeed η οποία καθορίζει πόσο γρήγορα κινείται η μπάλα και μια αντίστοιχη paddleSpeed για τη ρακέτα.<br />
</span></p>
<pre class="brush: csharp;">
public class Game1 : Microsoft.Xna.Framework.Game
{
     GraphicsDeviceManager graphics;
     SpriteBatch spriteBatch;
     Texture2D whiteTile;
     Rectangle paddle;
     Vector2 paddleDirection;
     float paddleSpeed;
     Rectangle ball;
     Vector2 ballDirection;
     float ballSpeed;
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Η ρακέτα στο Arkanoid κινείται μόνο αριστερά δεξιά, όποτε για να πετύχουμε τη κίνηση αυτή πρέπει να μεταβάλλουμε τη μεταβλητή paddle.X στην μέθοδο Update ανάλογα με το αν ο παίκτη πατά το αριστερό ή το δεξί βελάκι (cursor key):<br />
</span></p>
<pre class="brush: csharp;">
protected override void Update(GameTime gameTime)
{
     // Allows the game to exit
     if (Keyboard.GetState().IsKeyDown(Keys.Escape))
     {
          this.Exit();
     }

     if (Keyboard.GetState().IsKeyDown(Keys.Left))
     {
          paddle.X -= (int)paddleSpeed;
     }

     if (Keyboard.GetState().IsKeyDown(Keys.Right))
     {
          paddle.X += (int)paddleSpeed;
     }

     base.Update(gameTime);
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Θυμίζω ότι για να διαπιστώσουμε ποιο πλήκτρο πατά ο χρήστης χρησιμοποιούμε τη μέθοδο GetState() του αντικειμένου Keyboard (το οποίο δημιουρυγεί εξορισμού το XNA).<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Για να μετακινήσουμε τη μπάλα, δεν έχουμε παρά να προσθέσουμε στις X και Y συντεταγμένες του Rectangle ball μια μετατόπιση που προκύπτει από το διάνυσμα κατευθυνσης ballDirection και τη ταχύτητα της μπάλας ballSpeed.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Στην Initialise αρχικοποιούμε τις δυο αυτές μεταβλητές ως:<br />
</span></p>
<pre class="brush: csharp;">
protected override void Initialize()
{
     viewHeight = graphics.GraphicsDevice.Viewport.Height;
     viewWidth = graphics.GraphicsDevice.Viewport.Width;

     paddle = new Rectangle(150, 550, 90, 15);
     paddleSpeed = 10;

     ball = new Rectangle(150, 400, 15, 15);
     ballDirection = new Vector2(1, -1);
     ballDirection.Normalize();
     ballSpeed = 5;
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Η αρχική κατεύθυνση της μπάλας είναι δηλαδή προς τα πάνω και δεξιά και η ταχύτητα της είναι 5. Επίσης κανονικοποιώ το διάνυσμα της κατεύθυνσης ballDirection με τη μέθοδο Normalize() ώστε αυτό να έχει μήκος ένα και η τελική μετατόπιση τη μπάλας να εξαρτάται μόνο από την ταχύτητα της ballSpeed.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Επιστροφή στην Update για υπολογισμό της νέας θέσης της μπάλας:<br />
</span></p>
<pre class="brush: csharp;">
protected override void Update(GameTime gameTime)
{
     // Allows the game to exit
     if (Keyboard.GetState().IsKeyDown(Keys.Escape))
     {
          this.Exit();
     }

     if (Keyboard.GetState().IsKeyDown(Keys.Left))
     {
          paddle.X -= (int)paddleSpeed;
     }

     if (Keyboard.GetState().IsKeyDown(Keys.Right))
     {
          paddle.X += (int)paddleSpeed;
     }

     ball.X += (int)(ballDirection.X * ballSpeed);
     ball.Y += (int)(ballDirection.Y * ballSpeed);
     base.Update(gameTime);
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Αν τρέξουμε τώρα το παιχνίδι (με F5), θα μπορούμε να ελέγξουμε την κίνηση της ρακέτας αριστερά-δεξιά και η μπάλα θα κινηθεί προς τα πάνω-δεξιά μέχρι να βγει εκτός των ορίων της πίστας (χωρίς να συγκρουστεί με κανένα τουβλάκι). Αυτό που μας λείπει είναι η ανίχνευση συγκρούσεων.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Καταρχάς ας περιορίσουμε τη κίνηση της ρακέτας μέσα στα όρια της πίστας:<br />
</span></p>
<pre class="brush: csharp;">
protected override void Update(GameTime gameTime)
{
     // υπόλοιπος κώδικας

     ball.X += (int)(ballDirection.X * ballSpeed);
     ball.Y += (int)(ballDirection.Y * ballSpeed);

     //check paddle-wall collision
     if ( paddle.Left&lt;0)
     {
          paddle.X = 0;
     }
     else if (paddle.Right &gt; viewWidth)
     {
          paddle.X = viewWidth - paddle.Width;
     }
     base.Update(gameTime);
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Αυτό γίνεται εύκολα με το να μην αφήσουμε τη Left μεταβλητή του paddle να γίνει μικρότερη του μηδενός και την Right μεγαλύτερη του viewWidth (πλάτος πίστας) μείον το μήκος της ρακέτας.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Παρόμοια είναι και η λογική για τη μπάλα μόνο που πρέπει να ελέγξουμε εκτός από τα αριστερά και δεξιά τοιχώματα και τα πάνω και κάτω:<br />
</span></p>
<pre class="brush: csharp;">
protected override void Update(GameTime gameTime)
{
     // υπόλοιπος κώδικας

     //check paddle-wall collision
     if ( paddle.Left &lt; 0)
     {
          paddle.X = 0;
     }
     else if (paddle.Right &gt; viewWidth)
     {
          paddle.X = viewWidth - paddle.Width;
     }

     //check ball-wall collision
     if (ball.Left &lt;= 0 || ball.Right &gt;= viewWidth)
     {
          ballDirection.X = -ballDirection.X;
     }
     else if (ball.Top &lt;= 0 || ball.Bottom &gt;= viewHeight)
     {
          ballDirection.Y = -ballDirection.Y;
     }
     base.Update(gameTime);
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Σε περίπτωση που η μπάλα συγκρουστεί με κάποιο κάθετο τοίχωμα απλά αλλάζουμε τη κατεύθυνση στο Χ άξονα, διαφορετικά στο Υ. Επιπλέον πρέπει να ελέγξουμε αν η μπάλα συγκρούστηκε με τη ρακέτα:<br />
</span></p>
<pre class="brush: csharp;">
protected override void Update(GameTime gameTime)
{
     // υπόλοιπος κώδικας

     //check ball-wall collision
     if (ball.Left &lt;= 0 || ball.Right &gt;= viewWidth)
     {
          ballDirection.X = -ballDirection.X;
     }
     else if (ball.Top &lt;= 0 || ball.Bottom &gt;= viewHeight)
     {
          ballDirection.Y = -ballDirection.Y;
     }

     //check ball-paddle collision
     if (ballDirection.Y &gt; 0 &amp;&amp;
          ball.Bottom &gt;= paddle.Top &amp;&amp;
          ((ball.Left &gt;= paddle.Left &amp;&amp; ball.Left &lt;= paddle.Right) ||
          (ball.Right &gt;= paddle.Left &amp;&amp; ball.Right &lt;= paddle.Right))
     )
     {
          ballDirection.Y = -ballDirection.Y;
     }
     base.Update(gameTime);
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Η λογική της ανίχνευσης σύγκρουσης με τη ρακέτα είναι ανάλογη με αυτή του Pong. Καταρχάς εξασφαλίζουμε ότι η μπάλα έχει τη σωστή κατεύθυνση (προς τα κάτω, δηλαδή ballDirection.Y &gt; 0). Έπειτα ελέγχουμε αν υπάρχει επικάλυψη. Αν ισχύουν και τα δύο, τότε απλά αλλάζουμε τη κατεύθυνση της μπάλας στο Υ άξονα και η μπάλα αναπηδά προς τα πάνω.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Τρέχοντας τώρα το παιχνίδι (F5), η ρακέτα και η μπάλα κινούνται εντός ορίων και επιπλέον η μπάλα αναπηδά πάνω στην ρακέτα. Αυτό που απομένει τώρα είναι τα μπορέσουμε επιτέλους να καταστρέψουμε και κανένα τουβλάκι. Αυτό γίνεται εύκολα με την λειτουργικότητα που έχουμε προσθέσει στη κλάση Brick στο προηγούμενο άρθρο. Το μόνο που έχουμε να κάνουμε είναι να διατρέξουμε όλο το πίνακα με τα τουβλάκια (bricks) και να καλέσουμε την μέθοδο CheckHit του κάθε brick περνώντας το Rectangle της μπάλας ως όρισμα:<br />
</span></p>
<pre class="brush: csharp;">
protected override void Update(GameTime gameTime)
{
     // υπόλοιπος κώδικας

     //check ball-brick collision
     foreach (Brick brick in bricks)
     {
          if (brick.CheckHit(ball))
          {
               ballDirection.Y = -ballDirection.Y;
               break;
          }
     }

     base.Update(gameTime);
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Πάλι χρησιμοποιώ ένα for-each loop για να διατρέξω στο πίνακα. Δεν έχει ιδιαίτερες διαφορές με το κλασσικό for-loop απλά στη περίπτωση αυτή είναι πιο βολικό. Η μέθοδος CheckHit() θα ελέγξει αν υπάρχει επικάλυψη μεταξύ του τρέχοντος brick και της μπάλας. Αν ναι τότε θα κάνει το brick αόρατο (visible = false;) και θα επιστρέψει τη τιμή true. Διαφορετικά θα επιστρέψει false.<br />
</span></p>
<pre class="brush: csharp;">
public bool CheckHit(Rectangle ball)
{
     if (visible &amp;&amp; Intersects(ball))
     {
          visible = false;
          return true;
     }
     return false;
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Σε περίπτωση του η μέθοδος CheckHit() επιστρέψει true, το if-statement θα είναι αληθές και θα αλλάξει την κάθετη κατεύθυνση της μπάλας έτσι ώστε αυτή να αναπηδήσει από το τουβλάκι. Κάτι τελευταίο, όταν ανιχνεύσουμε σύγκρουση με ένα τουβλάκι (το if-statement είναι αληθές δηλαδή), καλούμε την εντολή break. Η εντολή αυτή σταματά άμεσα την επανάληψη σε οποιοδήποτε loop. Από τη στιγμή που υπήρξε σύγκρουση με ένα τουβλάκι δεν υπάρχει λόγος να συνεχίσω την ανίχνευση για αυτό το frame.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Τώρα μπορούμε να τρέξουμε το παιχνίδι και να παίξουμε κανονικά καταστρέφοντας τουβλάκια. Λείπουν μόνο το σκορ και η συνθήκη τερματισμού του παιχνιδιού.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Για το σκορ προσθέτουμε μια μεταβλητή score στη κλάση του παιχνιδιού Game1. Επιπλέον προθέτουμε μια μεταβλητή για τον αριθμό ζώων του παίκτη:<br />
</span></p>
<pre class="brush: csharp;">
public class Game1 : Microsoft.Xna.Framework.Game
{
     //υπόλοιπος κώδικας

     int score;
     int lives;
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Την μεταβλητή lives την αρχικοποιούμε σε 3 στην μέθοδο Intialize(). Κάθε φορά που ανιχνεύουμε μια σύγκρουση της μπάλας με το κάτω μέρος της πίστας αφαιρούμε μια ζωή. Κάθε φορά που ανιχνεύουμε μια σύγκρουση της μπάλας με ένα τουβλάκι αυξάνουμε το σκορ:<br />
</span></p>
<pre class="brush: csharp;">
protected override void Update(GameTime gameTime)
{
     // υπόλοιπος κώδικας

     //check ball-wall collision
     if (ball.Left &lt;= 0 || ball.Right &gt;= viewWidth)
     {
          ballDirection.X = -ballDirection.X;
     }
     else if (ball.Top &lt;= 0 || ball.Bottom &gt;= viewHeight)
     {
          ballDirection.Y = -ballDirection.Y;

          if (ball.Bottom &gt;= viewHeight)
          {
               lives--;
          }
     }

     // υπόλοιπος κώδικας

     //check ball-brick collision
     foreach (Brick brick in bricks)
     {
          if (brick.CheckHit(ball))
          {
               ballDirection.Y = -ballDirection.Y;
               score += 1000;
               break;
          }
     }

     base.Update(gameTime);
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Αυξάνουμε το σκορ κατά 1000 κάθε φορά που ο παίκτης καταστρέφει ένα τουβλάκι. Ο λόγος που αυξάνουμε τόσο πολύ, αντί για +1 τη φορά είναι ότι ένας παίκτης πάντα αισθάνεται μεγαλύτερη ικανοποίηση όταν πετυχαίνει μεγάλο σκορ, παρά μικρό έστω και αν αυτό το σκορ είναι φαινομενικά μεγάλο. Είναι εντυπωσιακότερο να καταστρέφω 100 τουβλάκια και να πετυχαίνω σκορ 100.000 πάρα να καταστρέφω 100 τουβλάκια και να πετυχαίνω σκορ 100.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Πρέπει τέλος να απεικονίσουμε το σκορ και τις ζωές στην οθόνη. Προσθέτουμε ένα font στο project Content του παιχνιδιού με τον τρόπο που <a href="http://videogameslab.wordpress.com/2009/07/17/hello-pong-part4/" target="_blank">περιγράψαμε εδώ</a>. Το ονομάζουμε Arial. Επιπλέον, ανοίγουμε το αρχείο του font (Arial.spritefont) και αλλάζουμε το μέγεθος σε 25 (γραμμή</span><span style="font-family:Courier New;font-size:10pt;"><span style="color:blue;"> &lt;</span><span style="color:#a31515;">Size</span><span style="color:blue;">&gt;</span>14<span style="color:blue;">&lt;/</span><span style="color:#a31515;">Size</span><span style="color:blue;">&gt;).<br />
</span></span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Για να φορτώσουμε το font ορίζουμε μια μεταβλητή SpriteFont:<br />
</span></p>
<pre class="brush: csharp;">
public class Game1 : Microsoft.Xna.Framework.Game
{
     GraphicsDeviceManager graphics;
     SpriteBatch spriteBatch;
     SpriteFont font;
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Τέλος φορτώνουμε το font στην μέθοδο Load όπως κάθε άλλο αρχείο περιεχομένου:<br />
</span></p>
<pre class="brush: csharp;">
protected override void LoadContent()
{
     // Create a new SpriteBatch, which can be used to draw textures.
     spriteBatch = new SpriteBatch(GraphicsDevice);
     font = Content.Load(&quot;arial&quot;);
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Στην μέθοδο Draw τώρα, απεικονίζουμε το σκορ και τις ζωές με τη χρήση της spriteBatch.DrawString():<br />
</span></p>
<pre class="brush: csharp;">
protected override void Draw(GameTime gameTime)
{
     GraphicsDevice.Clear(Color.Black);

     string message = String.Format(&quot;Lives: {0}, Score: {1}&quot;, lives, score);
     spriteBatch.Begin();

     spriteBatch.DrawString(font, message, new Vector2(10, 10), Color.Yellow);

     foreach (Brick brick in bricks)
     {
          brick.Draw(spriteBatch);
     }

     spriteBatch.Draw(whiteTile, paddle, Color.White);
     spriteBatch.Draw(whiteTile, ball, Color.Yellow);

     spriteBatch.End();

     base.Draw(gameTime);
}
</pre>
<p><span style="font-family:Verdana;font-size:9pt;">Δημιουργούμε ένα νέο string το οποίο θα αποθηκεύσει το κείμενο που θέλουμε να απεικονίσουμε. Χρησιμοποιούμε την String.Format η οποία έχει το χαρακτηριστικό να αντικαθιστά ότι επισημάνσεις του στυλ «{X}» βρει στο κείμενο με τις τιμές των μεταβλητών που της δίνουμε ως όρισμα (η String.Format μοιάζει λίγο με την printf της C για όποιον είναι γνώστης). Στην περίπτωση μας θα αντικαταστήσει το {0} με τη τιμής της lives και το {1} με την τιμή της μεταβλητής score.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Στο τέλος τυπώνουμε το κείμενο στην οθόνη με τη χρήση της spriteBatch.DrawString(), στη θέση (10,10), με χρώμα κίτρινο.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Θα σταματήσουμε το tutorial εδώ, το παιχνίδι είναι λειτουργικό σε μεγάλο βαθμό, το σκορ του παίκτη αυξάνεται όταν χτυπά τα τουβλάκια και οι ζωές ελαττώνονται όταν χάνει τη μπάλα αλλά ουσιαστικά το παιχνίδι δεν τελειώνει. Αυτό, μαζί με άλλες βελτιώσεις θα τα υλοποιήσουμε το επόμενο άρθρο.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;">Μπορείτε να βρείτε το κώδικα που αναπτύξαμε μέχρι στιγμής σε <a href="http://videogameslab.googlecode.com/files/Arcanoid_part2.zip" target="_blank">.zip</a> αλλά και μέσω SVN στο <a href="http://videogameslab.wordpress.com/2009/07/23/code-repository-2/" target="_blank">Code Repository</a>.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:9pt;"><br />
</span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/videogameslab.wordpress.com/421/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/videogameslab.wordpress.com/421/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/videogameslab.wordpress.com/421/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/videogameslab.wordpress.com/421/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/videogameslab.wordpress.com/421/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/videogameslab.wordpress.com/421/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/videogameslab.wordpress.com/421/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/videogameslab.wordpress.com/421/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/videogameslab.wordpress.com/421/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/videogameslab.wordpress.com/421/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=videogameslab.wordpress.com&blog=5040448&post=421&subd=videogameslab&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://videogameslab.wordpress.com/2009/09/24/arkanoid-part2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4bd00ab99710c6e67ef0a28c68628aad?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">thinkinggamer</media:title>
		</media:content>
	</item>
	</channel>
</rss>