Logika mapek w grze cRPG Django/Python

Prace nad "Wyspą Mrozu" posuwają się do przodu. Obecnie implementuję poszczególne elementy mapy, po której porusza się postać. System zakłada wykorzystanie mini-map podzielonych na kwadratowe klocki (tile) we współrzędnych x,y...

Prace nad "Wyspą Mrozu" posuwają się do przodu. Obecnie implementuję poszczególne elementy mapy, po której porusza się postać. System zakłada wykorzystanie mini-map podzielonych na kwadratowe klocki (tile) we współrzędnych x,y...

Oto przykład mapy z naniesioną siatką:
icetiled
Mapa opisana jest za pomocą kilku prostych JSONów zawierających współrzędne obszarów po których można się poruszać (z podziałem na strefy), obszary akcji (wywoływana jest akcja o podanym ID), pola generowania mięsa armatniego, czy też pola z lokacją już istniejących postaci (gracza, jak i wrogów, NPC):
class BigTile(models.Model):
	"""
	Model minimap złożonych z tilów
	"""
	name = models.CharField(max_length=255, verbose_name='Nazwa')
	img = models.ImageField(upload_to='ice/bigtiles/', verbose_name='Grafika')
	size = models.IntegerField(default=100, verbose_name='Rozmiar Klocka')
	movable_tiles = models.TextField(verbose_name=u'Obszary Ruchu')
	entry_tiles = models.TextField(verbose_name=u'Obszary Wejścia/Wyjścia')
	spawn_tiles = models.TextField(blank=True, verbose_name=u'Obszary Spawnowania')
	action_tiles = models.TextField(blank=True, verbose_name=u'Obszary Zdarzeń')
	char_locations =  models.TextField(blank=True, verbose_name=u'Lokacje NPC')
	class Meta:
		verbose_name = u'BigTile'
		verbose_name_plural = u'8. BigTile'
		db_table = 'ice_bigtile'
	def __str__(self):
		return self.name
	def __unicode__(self):
		return self.name

class BigTileCopy(models.Model):
	"""
	Model kopii minimap dla danego usera/questa
	"""
	mapa = models.ForeignKey(BigTile, verbose_name=u'Mapa rodzic')
	movable_tiles = models.TextField(verbose_name=u'Obszary Ruchu')
	entry_tiles = models.TextField(verbose_name=u'Obszary Wejścia/Wyjścia')
	spawn_tiles = models.TextField(blank=True, verbose_name=u'Obszary Spawnowania')
	action_tiles = models.TextField(blank=True, verbose_name=u'Obszary Zdarzeń')
	char_locations =  models.TextField(blank=True, verbose_name=u'Lokacje postaci i przeciwników')
	class Meta:
		verbose_name = u'BigTile Kopia'
		verbose_name_plural = u'9a. BigTile Kopie'
		db_table = 'ice_bigtilecopy'
	def __str__(self):
		return str(self.mapa)
	def __unicode__(self):
		return unicode(self.mapa)


class QuestCopy(models.Model):
	"""
	Model kopii questu dla danego usera
	"""
	quest = models.ForeignKey(Quest, verbose_name=u'Quest')
	char = models.ForeignKey(Character, verbose_name=u'Postać')
	maps = models.ManyToManyField(BigTileCopy, verbose_name='Mapy/Stan dla usera', related_name='maps')
	current_map = models.ForeignKey(BigTileCopy, verbose_name=u'Obecna mapa', related_name='current_map')
	class Meta:
		verbose_name = u'Quest'
		verbose_name_plural = u'9b. Questy Kopie'
		db_table = 'ice_questcopy'
	def __str__(self):
		return str(self.quest)
	def __unicode__(self):
		return unicode(self.quest)
Wcześniej zaprezentowana mapa ma tylko jeden obszar ruchu:
{"1": ["3,0", "4,0", "2,1", "3,1", "4,1", "2,2", "3,2", "4,2", "5,2", "2,3", "3,3", "4,3", "5,3", "6,3", "2,4", "3,4", "4,4", "5,4", "2,5", "3,5", "4,5", "5,5"]}

Przykładowo mając pośrodku mapy zamknięte drzwi - po jednej stronie byłby jeden obszar ruchu, a po drugiej stronie - drugi. Postać może poruszać się tylko w obrębie własnego obszaru ruchu. Po otworzeniu drzwi pola z drugiego obszaru zostałyby dołączone do pierwszego i postać mogłaby przejść dalej (Modele-kopie umożliwiają tu bezproblemową edycję JSONów dla danego questu/gracza).

Podobnie to wygląda dla innych pól, ale o tym później. Poruszanie zrobione jest w dość prosty sposób. Mapa wyświetlana jest jako tło diva. Natomiast postacie i inne elementy orientowane są w przestrzeni DIVa za pomocą absolutnej pozycji. Lokacja 3,0 odpowiada left/top 3*rozmiar tila,0*rozmiar tila. Wokół postaci (sąsiadujące tile) rysowane są przeźroczyste grafiki z zielonym obramowaniem oznaczające pola na jakie postać może przejść (uwzględniając czy współrzędne są w obszarze ruchu). Kliknięcie w takie pole wysyła żądanie AJAXem do Django w celu zwalidowania ruchu i zmiany pozycji postaci. Zwracane są nowe grafiki i koordynaty dla awatara postaci i umieszczane w tym DIVie:

<div style="background-image:url(/site_media/ice/bigtiles/room_.png); background-repeat:no-repeat;width:576px;height:576px;position:relative;" id="map">

<img src="/site_media/ice/good.png" class="good" alt="2,3" style="position:absolute;left:144px;top:216px;" />
<img src="/site_media/ice/good.png" class="good" alt="3,3" style="position:absolute;left:216px;top:216px;" />
<img src="/site_media/ice/good.png" class="good" alt="3,4" style="position:absolute;left:216px;top:288px;" />
<img src="/site_media/ice/good.png" class="good" alt="3,5" style="position:absolute;left:216px;top:360px;" />
<img src="/site_media/ice/good.png" class="good" alt="2,5" style="position:absolute;left:144px;top:360px;" />
<img src="/site_media/ice/action.png" title="Skrzynia" alt="1" style="position:absolute;left:72px;top:288px;" class="action" />
<img src="/site_media/ice/token4.png" title="Czesiek" alt="Czesiek" style="position:absolute;left:149px;top:296px;" />
<img src="/site_media/ice/token3.png" title="Ubogi rozbójnik" alt="Ubogi rozbójnik" style="position:absolute;left:365px;top:368px;" />
</div>
W przeglądarce wygląda to tak:
icemap
Obsługa JavaScriptowa jest dość prosta i realizowana za pomocą jQuery:
$(document).ready(function(){
	// Update character position
	$(".good").live("click", function(){
		$.ajax({
			url: "/ice/qmap_update/{{ qc.id }}/?move_on="+this.alt,
			cache: false,
			success: function(html){
				$("#map").html(html);
			}
		});
	});
	// Show action tile content
	$(".action").live("click", function(){
		$.ajax({
			url: "/ice/qmap_update/{{ qc.id }}/?action_on="+this.alt,
			cache: false,
			success: function(html){
				// tutaj ladnie to trzeba będzie wyświetlić...
// 				$("#map").html(html);
				alert(html);
			}
		});
	});

});
Demo pojawi się pewnie w weekend/po weekendzie na crpg.rk.edu.pl/ice/, a kod pewnie też ujży światło dzienne w tych okolicach jak go trochę ogarnę coby używał i18n.
blog comments powered by Disqus

Kategorie

Strony