基于python文本的RPG创建技能

时间:2016-02-25 14:19:59

标签: python oop

我正在创建基于文本的RPG,目的是在Python中学习更多关于OOP的知识。现在事情进展顺利,但我面临一个问题,我不能找到一个好的答案:技能实施。我也认为我将面临与物品类似的问题。

目前我有3个班级(专业):FighterRogueMage。这些类中的每一个都应该有自己的技能,但是技能有类似的东西(名称,描述,MP用法),所以我创建了一个BasicSkill类和3个子类:PassiveSkill,{{1} }和ActiveSkill

解释:ChanelledSkill是不需要MP使用的技能,总是活跃的,并且在大多数情况下,给予玩家增益,如双持,更多阻力等。{{1}是需要使用MP的技能,并且在大多数情况下会造成伤害或瞬间增益。最后,PassiveSkill是需要使用超过一个回合的技能,比其他回合花费更多的MP,并且可以被中断

但是,当谈到技能创造时,我只能想到这样的事情:

ActiveSkill

我认为这并不是我的目标,因为我每次使用时都要实例化它,或者是同一行中的东西。

我希望以一种需要较少实例化的方式创建技能,并且还可以更多地投射。此外,所有角色(玩家,npc和敌人)都可以施放技能。

这个项目中有很多文件,所以我会在这里发布我认为更相关的文件,如果你愿意,你可以查看项目here

这是我的ChanelledSkill课程:

def hack_and_slash(self):
        """This is a Fighter skill, it's melee and has no cool down."""
        from skills import ActiveSkill
        hack_and_slash = ActiveSkill("Hack n' Slash", "A powerful double attack that has a chance of causing bleeding.",
                                     8, 3)
        self.mp -= hack_and_slash.
        # more about the skill goes here, like what it does in terms of damaging, buffing, etc.

这是我的Player课程:

from character import Character


# TODO implementation of player basic attacks and abilities
# TODO implementation of a D&D style skill system(diplomacy, stealth, streetwise, etc)

class Player(Character):
    LEVEL_UP = 100  # initial XP to lvl up
    COMMANDS = {'attack': 'a', 'character': 'c', 'inventory': 'i'}  # commands available for the player
    # in future this skills will be used inside and outside combat situations, for like take out an enemy in stealth,
    # or convince a guard to let you in a closed door
    SKILLS = {'persuasion': 0, 'intimidation': 0, 'stealth': 0, 'perception': 0}
    DAILY_SELF_HEALS = 4  # each ingame day player can use 4 self heals, it resets after getting the rested status
    ATTRIBUTES = {'strenght': 0, 'constitution': 0, 'dexterity': 0, 'intelligence': 0, 'wisdom': 0, 'charisma': 0}

    def __init__(self, armor_class):
        super().__init__(input("Tell us your name, hero:\n>"), 20, 10, {'gold': 10, 'torch': 1}, armor_class, 1)
        self.exp = 0
        self.max_hp = self.hp  # max HP of the player
        self.max_mp = self.mp  # max MP of the player
        self._strength = 0  # should I change it to dictionary with the attributes instead?
        self._constitution = 0
        self._dexterity = 0
        self._intelligence = 0
        self._wisdom = 0
        self._charisma = 0

    def level_up(self):
        if self.exp >= self.LEVEL_UP:
            self.lvl += 1
            self.LEVEL_UP *= 1.25
            self.LEVEL_UP = int(self.LEVEL_UP)
            self.exp = 0
            stat_choice = input(
                "You have 2 points to spend in your attributes!\nType which attributes you want to raise up: ")
            stat_choice = stat_choice.split(',')
            self.ATTRIBUTES[stat_choice[0]] += 1
            self.ATTRIBUTES[stat_choice[1]] += 1
            self.max_hp = int(self.max_hp * 1.1)
            self.max_mp = int(self.max_mp * 1.1)
            return True
        else:
            return False

    def gain_exp(self, exp):
        self.exp += exp
        print("You gained %d XP" % exp)
        if self.level_up():
            print("Congratulations, you gained a level!\nYour current level is %d\n" % self.lvl)
        else:
            print("Your current XP is %d/%d\n" % (self.exp, self.LEVEL_UP))

    def get_loot(self, enemy):
        # buggy right now, problem with remove inventory from dead enemy
        for item in enemy.inventory:
            while True:
                get_item = input("You found %s! do you want to get it?(Y=yes/N=no/A=all items)" % item)
                if get_item.lower() == "a":
                    self.inventory.update(enemy.inventory)
                    enemy.inventory = {}
                    return
                elif get_item.lower() == "y":
                    self.inventory[item] = enemy.inventory[item]
                    enemy.inventory.pop(item, None)
                    break
                elif get_item.lower() == "n":
                    break
                else:
                    print("Unfortunately, you don't have this choice hero, take a look again...")

    def combat(self, enemy):
        """
        the combat between two entities(player and enemy)
        :param enemy: the enemy of current character
        :return:
        """
        if super().combat(enemy):
            self.gain_exp(10)
            self.get_loot(enemy)
        else:
            print("\t\t[GAME OVER...]\t\t")

    def self_heal(self):
        if self.DAILY_SELF_HEALS > 0:
            self.DAILY_SELF_HEALS -= 1
            self.hp += int(self.max_hp / 4)

    def rest(self):
        rest_time = input("\tHow much time would you like to rest? ")
        if rest_time >= 6:
            self.STATUS['rested'] = True

    def __str__(self):
        str_info = "\tName: [%s]\tLEVEL: %d\n\tHP: %2d\t\tMP: %2d" % (self.name, self.lvl, self.hp, self.mp)
        str_stats = "\t\tSTR: %2d\n\t\tCON: %2d\n\t\tDEX: %2d\n\t\tINT: %2d\n\t\tWIS: %2d\n\t\tCHA: %2d\n" % (
            self._strength, self._constitution, self._dexterity, self._intelligence, self._wisdom,
            self._charisma)
        return "|%s|\n%s" % (str_info, str_stats)

Character类:

# all character, being Player, NPC, or Enemy content should be implemented here
from utils import Dice


    class Character:
        """
        Main character class, all living entities derivate from it
        """

        # a dictionary of possible status of player, the idea is that this status change gameplay/combat in the future.
        # By default all characters are rested.
        STATUS = {'rested': True, 'hunger': False, 'poisoned': False, 'bleeding': False, 'blind': False, 'frozen': False,
                  'paralyzed': False, 'dead': False}
        # Right now there are only four equipment slot, which one should receive an armor object, not yet implemented
        EQUIPMENT_SLOTS = {'head': None, 'chest': None, 'legs': None, 'boots': None}

        def __init__(self, name, hp, mp, inventory, armor_class, lvl):
            """
            Constructor for a character
            :param name: name for the character
            :type name: str
            :param hp: hit points(health) for the character
            :type hp: int
            :param mp: magic points(mana) for the character
            :type mp: int
            :param inventory: inventory of character(gold, items, equips)
            :type inventory: dict
            :param armor_class: main defense
            :type armor_class: int
            :param lvl: level of character
            :type lvl: int
            :return: Character object
            """
            self.name = name
            self.hp = hp
            self.mp = mp
            self.inventory = inventory
            self.armor_class = armor_class
            self.lvl = lvl
            self.atk_bonus = 1
            self.atk_dmg = 4
            self.movement_speed = 6

        def take_dmg(self, dmg):
            self.hp -= dmg
            if self.hp <= 0:
                print("\n[%s has died!]" % self.name)
                self.STATUS['dead'] = True
            else:
                print("\n[%s has %d health left" % (self.name, self.hp))

        def attack(self, enemy):
            """
            All characters can attack, so this is the main attack(physical) method
            :param enemy: Enemy that is in combat with character
            :return:
            """
            d20 = Dice(20)
            dmg = self.atk_dmg
            if d20.roll() + self.atk_bonus >= enemy.armor_class:
                if d20 == 20:
                    print("CRITICAL HIT!")
                    dmg *= 2
                else:
                    dice_dmg = Dice(self.atk_dmg)
                    dmg = dice_dmg.roll()
                print("\n[%s hit %s for %d damage]" % (self.name, enemy.name, dmg))
                enemy.take_dmg(dmg)
                if enemy.STATUS['dead']:
                    return
            else:
                print("\n[%s missed]" % self.name)

        def combat(self, enemy):
            while True:
                self.attack(enemy)
                if enemy.STATUS['dead']:
                    return True
                enemy.attack(self)
                if self.STATUS['dead']:
                    break
            return False

        def equip_armor(self, armor_piece):
            """
            Equip a piece of armor in the correspondent slot
            :param armor_piece: armor piece to equip
            :type armor_piece: object
            :return:
            """
            replace_equip = input(
                "Would you like to replace %s with %s?(Y/N)" % (self.EQUIPMENT_SLOTS['head'], armor_piece.name))
            if replace_equip.lower() == "y":
                self.EQUIPMENT_SLOTS['head'] = armor_piece
                return
            else:
                return

        def list_inventory(self):
            """
            list a character's inventory
            :return:
            """
            print("\t\t[%s] INVENTORY:\t\t\n" % self.name)
            for item in self.inventory:
                print("%s:\t%d" % (item, self.inventory[item]))

,例如,Skill类,所有类/专业都以类似的方式实现:

# All basic skill implementation should be here


    class BasicSkill:
        SKILL_TYPE = {'passive': False, 'active': False, 'channeled': False}

        def __init__(self, name, description, skill_type, skill_dmg=0, skill_range=0):
            """
            Basic Skill class
            :param name: skill name
            :type name: string
            :param description: description
            :type description: string
            :param skill_type: passive, active or channeled
            :type skill_type: string
            :param skill_dmg: default=0, meaning it's passive
            :type skill_dmg: int
            :param skill_range: default=0, meaning it's personal
            :type skill_range: int
            :return:
            """
            self._name = name
            self._description = description
            self.SKILL_TYPE[skill_type] = True
            self.skill_dmg = skill_dmg
            self.skill_range = skill_range


    class PassiveSkill(BasicSkill):
        def __init__(self, name, description, skill_type='passive'):
            super().__init__(name, description, skill_type)


    class ActiveSkill(BasicSkill):
        def __init__(self, name, description, skill_dmg, mp_use, cooldown=1, skill_type='active', skill_range=1):
            super().__init__(name, description, skill_type, skill_dmg, skill_range)
            self.mp_use = mp_use
            self.cooldown = cooldown


    class ChanneledSkill(BasicSkill):
        def __init__(self, name, description, skill_dmg, channeling_time, cooldown=2, skill_type='chanelled',
                     skill_range=1):
            super().__init__(name, description, skill_type, skill_dmg, skill_range)
            self.channeling_time = channeling_time
            self.cooldown = cooldown

欢迎任何想法,以及代码改进技巧。我试图找出一个很好的方法来制作这个技能实现系统,但我找不到一个。我努力的唯一选择是技能词典,但我不知道它会如何运作。无论如何,谢谢你的帮助。

0 个答案:

没有答案