5
\$\begingroup\$

I recently picked up a copy of Learn Python 3 The Hard Way, but found that editing and revamping other peoples code was a lot easier for me to learn. I've done a couple so far, but am having a really hard time understanding classes.

I decided to make an RPG Game to both help in my understanding, and to give me a goal to push me to keep learning. My end goal is to have a working RPG in Pygame. I want to be able to walk around a map and display global variables such as health, mana, etc.

For now I am focused on creating the main part of my game -- I've found tons and tons of example codes for battling, items, etc, but I wanted to build it from the ground up, and am having trouble with my character creation.

Short term goal -- run the script, and have each characters' stats pop up, along with a prompt on which you want to create (numbers 1-3). Each character has a list of 3 attacks which do different amounts of damage, spend energy + mana, or arrows.

Heres's my current, basic, main page of code, which I really wanted help with.

I plan on having enemy monsters drop arrows, and mana potions, with energy being restored on each fight:

class PlayerClass:
    def __init__(self, hp = 100, damage = 0, energy = 100, strength = 0, mana = 0, arrows = 0):
        self.hp = int(hp)
        self.damage = int(damage)
        self.energy = int(energy)
        self.strength = int(strength)
        self.mana = int(mana)
        self.arrows = int(arrows)
pc = PlayerClass()
pcStats = [pc.hp, pc.damage, pc.energy, pc.strength, pc.mana, pc.arrows]

class Swordsman(PlayerClass):
    def __init__(self, hp = 100, damage = 50, energy = 100, strength = 100):
        self.hp = int(hp)
        self.damage = int(damage)
        self.energy = int(energy)
        self.strength = int(strength)
s = Swordsman()
sStats = [s.hp, s.damage, s.energy, s.strength]

class Mage(PlayerClass):
    def __init__(self, hp = 100, damage = 30, energy = 100, mana = 500):
        self.hp = int(hp)
        self.damage = int(damage)
        self.energy = int(energy)
        self.mana = int(mana)
m = Mage()
mStats = [m.hp, m.damage, m.energy, m.mana]

class Archer(PlayerClass):
    def __init__(self, hp = 100, damage = 30, energy = 100, arrows = 500):
        self.hp = int(hp)
        self.damage = int(damage)
        self.energy = int(energy)
        self.arrows = int(arrows)
a = Archer()
aStats = [a.hp, a.damage, a.energy, a.arrows]

Here are the attacks I wanted to add, but didn't really know where to start:

{"1. Slash: "
            "2. Chop: "
            "3. Hack: "
            }

{"1. Fire Blast: "
            "2. Shadowball: "
            "3. Arcane Presence: "
            }

{"1. Long Shot: "
            "2. Rapid Fire: "
            "3. Arrow Barrage: "
            }
\$\endgroup\$
1
  • 3
    \$\begingroup\$ on Codereview there are rules about what is on/off topic. And "Here are the attacks I wanted to add" is asking about code not yet written, which is frowned upon. You might want to remove that from the question. But I'm sure you will get a few decent answers. \$\endgroup\$
    – Ludisposed
    Commented Nov 17, 2017 at 9:01

2 Answers 2

5
\$\begingroup\$

You don't have much code written, so I'm not really sure how much help you're likely to get here.

A couple of points:

  1. There's no reason to call it PlayerClass. Just call it Player since the word class appears right next to it.

  2. You are using PlayerClass as the base class for your other three classes. But you are not calling super in your initializer function, and not taking advantage of inheritance. Try this:

    class Swordsman(Player):
        def __init__(self, *, damage=50, strength=100, **kwargs):
            super().__init__(damage=damage, strength=strength, **kwargs)
    

    And see Raymond Hettinger's guide to using super for more pro-tips. The idea here is to override the default attribute values on a per-class basis (dmg and str, in this case) but have the root class do all the attribute-setting, since it's all the same except for the values.

\$\endgroup\$
1
\$\begingroup\$

Review

  1. Use inheritence, they derive from the same super class, but for now they have different constructors. Alot more typing ;)
  2. You could use a __str__ to get a visual representation of the stats, these can also be handled by the parent Class.
  3. If you use Python3.6 you could use the fancy f"string", see the relevant PEP article.

@Austin Hastings has the right idea, using **kwargs to do all the attribute setttings.

I recommend to look up inheritence, and Python __magic__ methods.

Code changes

import textwrap


class Player:
    def __init__(self, name, hp=100, damage=30, energy=100, strength=0, mana=0, arrows=0):
        self.name = name
        self.hp = hp
        self.damage = damage
        self.energy = energy
        self.strength = strength
        self.mana = mana
        self.arrows = arrows        

    def __str__(self):
        return textwrap.dedent(f"""\
                                Name: {self.name}
                                HP: {self.hp}
                                Damage: {self.damage}
                                Energy {self.energy}
                                Strength {self.strength}
                                Mana {self.mana}
                                Arrows {self.arrows}\n""")

class Swordsman(Player):
    def __init__(self, name="Sowrdsman", damage=50, strength=100, **kwargs):
        super().__init__(name=name, damage=damage, strength=strength, **kwargs)

    def __str__(self):
        return super().__str__()

class Mage(Player):
    def __init__(self, name="Mage", mana=500, **kwargs):
        super().__init__(name=name, mana=mana, **kwargs)

    def __str__(self):
        return super().__str__()

class Archer(Player):
    def __init__(self, name="Archer", arrows=500, **kwargs):
        super().__init__(name=name, arrows=arrows, **kwargs)

    def __str__(self):
        return super().__str__()

if __name__ == '__main__':
    archer = Archer()
    print(archer)

    swordsman = Swordsman()
    print(swordsman)

    mage = Mage()
    print(mage)
\$\endgroup\$
2
  • \$\begingroup\$ since a mage or swordman don't have arrows, I would set these to default 0 on Player, and not on the subclasses that don't need them. If later you want a Swordsman with arrows, you can pass this on via the **kwargs \$\endgroup\$ Commented Nov 17, 2017 at 9:45
  • 1
    \$\begingroup\$ Maybe link f"string" to PEP498? \$\endgroup\$
    – Daniel
    Commented Nov 17, 2017 at 11:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.