Zelda

Du hast eine Idee für ein Projekt?
Antworten
MilesTeg
User
Beiträge: 8
Registriert: Donnerstag 2. Februar 2006, 02:51

Hi Leute

ich hab gerade überlegt ein eigenes Game-projekt zu beginnen. Dachte dabei vor allem an eine art Zelda-Klon. Im Freeware-Bereich gibts da schon Zelda Classic, aber das ist leider nicht OSS. Dann gibts noch OpenLynks, aber das ist kurz nach dem Übergang auf SDL eingeschlafen (C++).

Bin jetzt am überlegen, was sinnvoller ist: mich mal an die Wiederbelebung von OpenLynks zu wagen oder das ganze mit pygame anzugehen,

Als Endziel wäre es schön eine freie Alternative zu Zelda Classic zu haben, aber mir gehts vorerst eher mal ums Programmieren aus Spass.

http://openlynks.sourceforge.net/
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Ich glaube, ein verwaistes Projekt umzustricken macht lange nicht so viel Spaß wie alles neu zu schreiben. :)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

mkallas hat geschrieben:Ich glaube, ein verwaistes Projekt umzustricken macht lange nicht so viel Spaß wie alles neu zu schreiben. :)
Also mein Zelda-Klon mit Pygame ist schon seit Ewigkeiten tot.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Leonidas hat geschrieben:
mkallas hat geschrieben:Ich glaube, ein verwaistes Projekt umzustricken macht lange nicht so viel Spaß wie alles neu zu schreiben. :)
Also mein Zelda-Klon mit Pygame ist schon seit Ewigkeiten tot.
Du hast mal ein Spiel programmiert?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hyperion hat geschrieben:Du hast mal ein Spiel programmiert?
Ich bin über Spieleprogrammierung überhaupt erst zu Python gekommen. Nicht dass ich da jemals irgendwas interessantes zusammengebracht habe 8)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Hatte gestern einen Text geschrieben, der behandelte, dass ich die Schwierigkeit bei einen Spiel wie Zelda (was ich nie gespielt habe - ich beziehe mein Wissen von Roguelike-Spielen, die ebenfalls Mitte der 80er populär waren) nicht in der Darstellung sondern im Spielprinzip sehe. Hatte mir weiterhin Regel ausgedacht und beschrieben, leider hat mein TextMate das eben alles in die ewigen Speichergründe gerissen, weil ich DOOF nicht gespeichert hatte.

Habe nur noch den Python-Code, der da lautet:

Code: Alles auswählen

class Creature(object):
    def __init__(self, combat, magick, health):
        self._combat, self._magick, self._health = combat, magick, health
        self._defense, self._soak = 2, 0
        self.weapon, self.armor, self.focus = None, None, None
        
    @property
    def combat(self):
        return self._combat + (self.weapon.combat if self.weapon else 0)
        
    @property
    def magick(self):
        return self._magick + (self.focus.magick if self.focus else 0)
        
    @property
    def defense(self):
        return self._defense + self._combat / 3
    
    @property
    def soak(self):
        return self._soak + (self.armor.soak if self.armor else 0)
    
    def attack(self, opponent):
        damage = roll(self.combat - opponent.defense)
        opponent.health -= max(damage - opponent.soak, 0)
        return opponent.health > 0
        
    def cast(self, spell):
        spell.effect(roll(self.magick - spell.magick))
        
class Item(object):
    def __init__(self, name, combat=0, magick=0, soak=0):
        self.name, self.combat, self.magick, self.soak = name, combat, magick, soak
Erklärung: Jede Kreatur (Helden, Monster, usw.) hat drei primäre Eigenschaften: Wie gut kann sie kämpfen, wie gut zaubern und wie verletzlich ist sie. Gegenstände können diese Werte beeinflussen. Waffen erhöhen so den Kampfwert, Zauberfoci den Zauberwert und Rüstungen reduzieren den Schaden.

Ich benutze 7-seitige Würfel, einfach weil ich's kann:

Code: Alles auswählen

def roll(n):
    successes = 0
    if n < 1:
        while True:
            r = random.randrange(7)
            if r < 6: break
            successes += 1
    else:
        while n > 0:
            r = random.randrange(7)
            if r > 4:
                successes += 1
            if r < 6:
                n -= 1
    return successes
Erklärung: Ich werfe n Würfel. Eine 6 oder 7 ist ein Erfolg, bei 7 würfle ich den Würfel erneut. Soll ich weniger als einen Würfel werden, nehme ich einen "Schicksalswürfel", wo nur eine 7 (die aber öfters) ein Erfolg ist.

Und hier ist mein Beispiel:

Code: Alles auswählen

hero = Creature(7, 3, 11)
hero.weapon = Item("Breitschwert", combat=5)
hero.armor = Item("Lederrüstung", soak=1)

skeletons = [Creature(8, 6, 6) for i in range(3)]
while hero.health > 0 and skeletons:
    skeleton = random.choice(skeletons)
    if hero.attack(skeleton):
        skeleton.attack(hero)
    else:
        skeletons.remove(skeleton)
Und ein Totenbeschwörer kann neue Skelette erschaffen:

Code: Alles auswählen

necromancer = Creature(3, 11, 8)
necromancer.weapon = Item("Knochenstab", combat=3, magick=8, soak=1)
necromancer.armor = necromancer.focus = necromancer.weapon

def raise_skeletons_effect(power):
    for i in range(power):
        skeletons.append(Creature(8, 6, 3 + power))

raise_skeletons_spell = Item("Skelett beleben", magick=6, effect=raise_skeletons_effect)

necromancer.cast(raise_skeletons_spell)
Dazu kommen jetzt noch einige Funktionen, um Gegenstände aufzuheben, wegzuwerfen, zu benutzen und jede Menge Kreativität für besondere Gegenstände, Monster und Zaubersprüche. Packt man Monster und Gegenstände auf ein Spielbrett, hat man eigentlich ein Roguelike-Spiel, wie zum Beispiel Zelda.

Stefan
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Die meiste Arbeit macht vor allem, eine fortlaufende Geschichte zu erarbeiten, die Spielwelt mit den NPC, Levels mit aufsteigendem Schwierigkeitsgrad, Raetsel etc. Zelda hatte z.B. auch immer das Prinzip, dass man in jedem Level eine neue Waffe/einen neuen magischen Gegenstand bekam, mit dem man dann neue Gebiete der Spielwelt erschliessen kann, sodass man nach und nach die Spielwelt kennen lernt etc.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Rebecca hat geschrieben:Zelda hatte z.B. auch immer das Prinzip, dass man in jedem Level eine neue Waffe/einen neuen magischen Gegenstand bekam, mit dem man dann neue Gebiete der Spielwelt erschliessen kann, sodass man nach und nach die Spielwelt kennen lernt etc.
Das schöne war, dass man eigentlich ganz oft durch die selben Orte ging und je nachdem was man schon für Gegenstände hatte weiter und weiter gehen konnte. Am schluss ging das so weit, dass bereits in der Gameboy-Classic-Version Teleporter eingeführt worden, weil man sonst nur noch am laufen gewesen wäre.

Zelda hat mit Roguelike-Spielen wenig zu tun, der Kampf ist einfacher, weil ein Treffer mit einer Waffe (Schwert oder der Bumerang, Bogen, oder auch mit rumstehenden Vasen, Elefantenstatuen, Eistenkugeln, etc.) dem Gegner einen Trefferpunkt abzieht. Vorrausgesetzt man trifft ihn an einer verwundbaren Stelle und auch mit der richtigen Waffe. Das L2-Schwert teilt doppelt so starke Treffer aus, der Wirbelklingen-Angriff verdoppelt unabhängig vom Schwert-Level die Angriffspunkte. Wenn der Gegner 0 Trefferpunkte hat, verschwindet er und lässt unter Umständen einen Gegenstand übrig. In neueren Zelda-Versionen (auf dem Handhelf, die Konsolen-Versionen sind wiederrum etwas anders) konnte man den Wirbelklingen-Angriff nicht nur einmal ausführen sondern beliebig oft hintereinander wirbeln. Das System ist eigentlich ganz simpel, da Treffer gleich Treffer ist, es gibt keine Rettungswürfe etc. das einzige was durch Würfeln bestimmt wird ist ob Gegner Gegenstände liegen lassen, aber das war je nach Gegner und benutzer Waffe unterschiedlich warscheinlich.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
MilesTeg
User
Beiträge: 8
Registriert: Donnerstag 2. Februar 2006, 02:51

so, hab den code von Leonidas mal ein wenig umgeschrieben. Hab aber keine Ahnung, wo ich so ein Projekt hausen lassen soll - BerliOS ? Leonidas meinte SF wäre mitlerweile out - bin da nicht so auf dem neusten Stand (schon garnicht was python angeht).

Link tänzelt jetzt lustig im Fenster herum :)


@Spielsystem. Also interessanter finde ich da die Kollisionabfrage. Bei Zelda 3 war es soweit ich mich erinnere möglich nur das Schwert des Gegners zu treffen (Schwert an Schwert) - somit war das wohl selbst noch ein eigenes Objekt (?)

Ich find auch in den Grundzügen gleicht Zelda einem Rogue-Game. Aber die genannten Elemente lassen es dann doch zu was besonderem werden.
Hab mir jedenfalls keine zu hohe Messlatte gesetzt, da bei Zelda doch einiges zusammenkommt. Ich versuch mich demnächst mal am Kampfsystem.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

MilesTeg hat geschrieben:so, hab den code von Leonidas mal ein wenig umgeschrieben. Hab aber keine Ahnung, wo ich so ein Projekt hausen lassen soll - BerliOS ? Leonidas meinte SF wäre mitlerweile out - bin da nicht so auf dem neusten Stand (schon garnicht was python angeht).
Google Code war letztens populär, alternativ auch Origo. Vielleicht reicht ja auch das was Github oder Bitbucket zur Verfügung stellen?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Rebecca hat geschrieben:Die meiste Arbeit macht vor allem, eine fortlaufende Geschichte zu erarbeiten
Ja, diese war bei Hack und Co zugegeben dünn: Hole das Amulett von Yendor ("), töte alles, was sich bewegt, überlebe :)

Die von Leonidas angesprochenen Orte sind doch aber nur 2D-Karten mit schachbrettartigen Feldern, die betretbar oder unbetretbar sind und Gegenstände und/oder Monster enthalten können. Man könnte bestimmte Gegenstände wie Tore haben, die einen dann (vielleicht nur, wenn man einen bestimmten Gegenstand besitzt) zu einem anderen Ort auf der Karte (oder einer anderen Karte) transportiert.

Wenn es darauf ankommt, wo man einen Gegner trifft, ist Zelda komplexer als Rogue, denn dort lief man einfach auf den Gegner, was zu einem Angriff mit der aktuell geführten Waffe führt, wobei so krude D&D-Regeln gelten, d.h. es werden n x-seitige Würfel geworfen, addiert, davon der Rüstungsschutz des Gegners subtrahiert und der Rest von dessen Lebenspunkten abgezogen. Doch wie kann man bei der auf dem Screenshot abgebildeten Klötzchengrafik zielen?
Leonidas hat geschrieben:Das System ist eigentlich ganz simpel, da Treffer gleich Treffer ist, es gibt keine Rettungswürfe etc. das einzige was durch Würfeln bestimmt wird ist ob Gegner Gegenstände liegen lassen, aber das war je nach Gegner und benutzer Waffe unterschiedlich warscheinlich.
Ich verstehe das nicht so ganz: Ich kann also angreifen (sagen wir, mit einer bestimmten Taste) und richtige automatisch einen Punkt Schaden an. Sagen wir, der Gegner muss 3x getroffen werden. Schlägt er zurück? Richtet er auch automatisch Schaden an? Dann lebt er doch einfach 3 Runde, richtet dabei 3 Punkte Schaden an und man könnte mir doch einfach die 3 Punkte von meinen eigenen Lebenspunkten abziehen. Wo ist da ein Spiel? Und wieso hängt es von meiner Waffe ab, was der Gegner für einen Gegenstand besitzt?

Ich glaube, ich finde meinen Roguelike-Ansatz besser ;)

Stefan
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

sma hat geschrieben:Ich verstehe das nicht so ganz: Ich kann also angreifen (sagen wir, mit einer bestimmten Taste) und richtige automatisch einen Punkt Schaden an. Sagen wir, der Gegner muss 3x getroffen werden. Schlägt er zurück?
Natürlich schlägt er zurück. Er greift auch von selbst an, wenn er dich sieht.
sma hat geschrieben:Richtet er auch automatisch Schaden an? Dann lebt er doch einfach 3 Runde, richtet dabei 3 Punkte Schaden an und man könnte mir doch einfach die 3 Punkte von meinen eigenen Lebenspunkten abziehen.
Nein, er richtet nur schaden an, wenn er dich auch trifft und du nicht den Schild nutzt. Aber man kann ja durchaus auch den Waffen der Gegner ausweichen, etwa durch davonlaufen oder springen. Das ist möglich, weil Zelda eben nicht rundenbasiert ist sondern in Realtime läuft.

Baldurs Gate zwar auch, aber dort hat man die AD&D-Regeln und bis auf Waffe auswählen, Kämpfen anklicken hat man dort recht wenig und nur indirekten Einfluss auf das Kampfgeschehen. In Zelda steuert man Link, die Spielfigur direkt.
sma hat geschrieben:Und wieso hängt es von meiner Waffe ab, was der Gegner für einen Gegenstand besitzt?
Das war wohl ein Goodie in Links Awakening, dass wenn man die Schaufel gegen einen Bumerang eintauscht und mit dem Bumerang bestimmte Gegner in Verließen erledigt (die außer vom Bumerang gar nicht verwundet werden können), dann kommt eine Fee, die mehr Lebenspunkte zurückgibt als ein Herz.
Ok, gut stimmt - die Waffe beeinträchtigt nicht, was der Gegner liegenlässt, da habe ich mich geirrt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

sma hat geschrieben:Wenn es darauf ankommt, wo man einen Gegner trifft, ist Zelda komplexer als Rogue, denn dort lief man einfach auf den Gegner, was zu einem Angriff mit der aktuell geführten Waffe führt, wobei so krude D&D-Regeln gelten, d.h. es werden n x-seitige Würfel geworfen, addiert, davon der Rüstungsschutz des Gegners subtrahiert und der Rest von dessen Lebenspunkten abgezogen. Doch wie kann man bei der auf dem Screenshot abgebildeten Klötzchengrafik zielen?
Mmh, mit so einem 2D-Schachbrett muesste man das bei Zelda aber hinbekommen. (Zumindest, was ich vom GameBoy classic kenne). Bei den meisten Gegnern ist es egal, wo man sie trifft. Dann gibt es einige, die kann man nur von einer Seite treffen (oder von einer Seite nicht treffen, weil sie da z.B. ein Schild halten), das passt aber auch in das Schachbrettmuster). Dann gab es noch Wuermer, die mehrere Felder einnahmen, die man nur am Schwanz treffen konne, was wahrscheinlich auch wieder einem Feld entspricht. Dann gibt's Gegner, die kann man nicht immer treffen (weil sie dann z.B. in die Luft springen oder sich "einigeln"), und viele Gegner, bei denen man nur mit speziellen Gegenstaenden etwas bewirken kann.

Ich verstehe das nicht so ganz: Ich kann also angreifen (sagen wir, mit einer bestimmten Taste) und richtige automatisch einen Punkt Schaden an. Sagen wir, der Gegner muss 3x getroffen werden. Schlägt er zurück? Richtet er auch automatisch Schaden an? Dann lebt er doch einfach 3 Runde, richtet dabei 3 Punkte Schaden an und man könnte mir doch einfach die 3 Punkte von meinen eigenen
Waehrend du versuchtst, den Gegner zu treffen, versucht er wiederum, dich zu treffen oder zu beruehren, und wenn du nicht ausweichst oder dein Schild zueckst, nimmst du Schaden. Da ist Zelda eben mehr Action-Spiel als Rollenspiel, der Kampf wird nicht ausgewuerfelt, sondern richtig ausgespielt.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
MilesTeg
User
Beiträge: 8
Registriert: Donnerstag 2. Februar 2006, 02:51

sma hat geschrieben:Man könnte bestimmte Gegenstände wie Tore haben, die einen dann (vielleicht nur, wenn man einen bestimmten Gegenstand besitzt) zu einem anderen Ort auf der Karte (oder einer anderen Karte) transportiert.
ganz einfach wie bei SuperMarioWorld oder Metroid: Es gibt bestimmte Map-Tiles, die nach einem Trigger verschwinden (Bei Mario warens gelbe, blaue grüne Blöcke etc.) oder die man mit einer speziellen Waffe zerstören kann (harte Steinwände bei Metroid)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich dachte eher an so was:

Code: Alles auswählen

class Tile(object):
    def __init__(self, creature=None, items=None):
        self.creature, self.items = creature, items or []
        if creature: creature.tile = self
        for item in self.items: item.tile = self
    
    def can_enter(self, creature):
        return not self.creature and all(item.allow_enter(creature) for item in self.items)
    
    def enter(self, creature):
        if creature.tile:
            creature.tile.leave(creature)
        creature.tile = self
        for item in self.items: item.notify_enter(creature)
        
    def leave(self, creature):
        for item in self.items: item.notify_leave(creature)
        creature.tile = None

class Item(object):
    pass

class PortalItem(Item):
    def allow_enter(self, creature):
        return creature.has_item_of_type(KeyItem)
    
    def notify_enter(self, creature):
        creature.move_to(self.dest_tile)
    
    def notify_leave(self, creature):
        pass

class KeyItem(Item):
    pass

class Creature(object):
    def __init__(self, items=None):
        self.items = items or []
    
    def add_item(self, item):
        self.items.append(item)
        
    def has_item_of_type(self, cls):
        return any(isinstance(item, cls) for item in self.items)
    
    def move_to(self, tile):
        if self.tile != tile:
            if tile.can_enter(self):
                tile.enter(self)
                return True

hero = Creature()
portal = PortalItem()
t1 = Tile(hero)
t2 = Tile(None, [portal])
t3 = Tile()
portal.dest_tile = t3
print hero.move_to(t2), hero.tile
hero.add_item(KeyItem())
print hero.move_to(t2), hero.tile
Und wenn ich jetzt meinen `Tile`s Koordinaten gebe und sie auf einer `TileMap` anordne, kann ich mich sogar richtig bewegen:

Code: Alles auswählen

class TileMap(object):
    def __init__(self):
        self.tiles = {}
    
    def __setitem__(self, index, tile):
        self.tiles[index] = tile
        tile.coord = index
        tile.tilemap = self
    
    def __getitem__(self, index):
        return self.tiles[index]

class Tile...
    def east(self):
        x, y = self.coord; return self.tilemap[x + 1, y]

class Creature...
    def move_east(self):
        return self.move_to(self.tile.east())

hero = Creature()
portal = PortalItem()
tilemap = TileMap()
tilemap[0, 1] = Tile(hero)
tilemap[1, 1] = Tile(None, [portal])
tilemap[3, 3] = portal.dest_tile = Tile()

print hero.tile.coord
hero.move_east()
print hero.tile.coord
hero.add_item(KeyItem())
hero.move_east()
print hero.tile.coord
Vielleicht noch einen Wächter für das Portal?

Code: Alles auswählen

class Guardian(Creature):
    pass

tilemap[1, 1] = Tile(Guardian(), [portal])

hero.move_to(tilemap[0, 1])
print hero.move_east()
Und dazu jetzt ein simples Kampfsystem: Jeder Angriff vom Helden ohne Waffe: 1 Punkt Schaden, mit Waffe entsprechend mehr. Jetzt hat ein Held ohne Schwert keine Chance gegen den Wächter, der ihn tötet, bevor der dritte Angriff erfolgt.

Code: Alles auswählen

Item.damage = 0

class Creature(object):
    tile = None
    health = 3
    damage = 1
    
    def __init__(self, items=None):
        self.items = items or []
    
    def combat(self, opponent):
        self.attack(opponent)
        if opponent.health > 0:
            opponent.attack(self)
            if self.health < 1:
                raise SystemExit
        else:
            opponent.remove()

    def attack(self, opponent):
        opponent.health -= self.damage
        if self.items:
            opponent.health -= max(item.damage for item in self.items)
    
    def remove(self):
        if self.tile: self.tile.leave(self)
 
class Guardian(Creature):
    health = 4
    damage = 2

class Hero(Creature):
    health = 3
    damage = 1

hero = Hero([])
guardian = Guardian()
hero.combat(guardian)
hero.combat(guardian) # hero died!
Mit Schwert jedoch sieht es anders aus:

Code: Alles auswählen

class SwordItem(Item):
    damage = 1

hero = Hero([SwordItem()])
guardian = Guardian()
hero.combat(guardian)
hero.combat(guardian) # guardian defeated
Hey, das macht Spass :)

Stefan
MilesTeg
User
Beiträge: 8
Registriert: Donnerstag 2. Februar 2006, 02:51

Hab unter den Gamelets noch etwas nettes gefunden: Adventure of Einar
http://www.pygame.org/gamelets/

Da ist schon viel eingebaut. Werd mir definitiv das eine oder andere abschauen :)

Beim Kampfsystem werd ich mich in jedem Fall stark an Zelda orientieren (also so ähnlich wie bei AoEinar zu sehen).
Benutzeravatar
jonas
User
Beiträge: 156
Registriert: Dienstag 9. September 2008, 21:03

Hi Leute!
Ich würde gerne am Zelda Projekt mitarbeiten, aber :

-> Ich habe noch nicht so viel Erfahrung mit python.
-> Ich habe nicht SO viel Zeit.

d.h. ich weiß nicht wie viel Zeit ich dafür pro Tag / Woche aufwenden
könnte.

Ich denke am Tag so 1-2 Stunden max.

Bei Interesse oder eben keinem Interesse bitte
einfach eine PN an mich.

MfG Jonas
Antworten