Python ile PvP tarzında bir oyun

Herkese merhaba ! Son zamanlarda kendimi OOP üzerinde geliştirmek gibi bir amacım vardı.
Ben de bunun en güzel yolunun bir proje yapmak olduğunu düşündüğüm için hemen kolları sıvadım.
Yaklaşık 1 haftadır üzerinde uğraştığım projemi paylaşmak istiyorum sizlerle.
Github:
https://github.com/TaylanOzturk23/PvP-Game
Tanıtım videosu:


Videoda hemen her şeyi anlatıyorum. Bir de burada özet geçeyim.
PvP (player vs player) tarzında bir oyun yaptım.
Oyunda tam olarak 100 adet stage bulunuyor. Her stage’de karşımızda yeni bir düşmanımız oluyor.
10’un katları olan stage’lerde Grandmaster olarak hitap ettiğimiz bosslar karşımıza çıkıyor. Bu stage’lerin dışında 5’in katı olan seviyelerde de karşımıza Master olarak hitap ettiğimiz bosslar çıkıyor.
yani:
Grandmaster’ların çıktığı stage’ler:

print(list(filter(lambda x: False if x % 10 else True, range(1, 100+1))))

Master’ların çıktığı stage’ler:

print(list(filter(lambda x: True if x % 5 == 0 and not x % 2 == 0 else False, range(1, 100+1))))

Her düşman yenişimizde, dolayısıyla stage atladığımızda +1 skill point kazanıyoruz. Skill point’ler aracılığıyla skillerimizi geliştiriyoruz ve böylece her yeni stage’de çok daha güçlü bir hal alıyoruz.
Aynı şey düşmanlarımız için de geçerli.
Oyunun genel olarak içeriği bu. Savaş sırasında neler dönüyor ?
Saldırı stilleri ve tipleri bulunuyor.
Stiller:
Quick
Power
Critical

Tipler:
Fiziksel hasar
Büyülü hasar


Quick’in hasarı düşüktür ancak isabetlilik oranı daha fazladır.
Power’ın hasarı Quick’ten daha fazladır ancak isabetlilik oranı daha düşüktür
Critical’ın hasarı en fazladır ancak isabetlilik oranı da en düşük olan saldırı stilidir.


Fiziksel hasar: isabetliliği daha fazla fakat hasarı daha düşük
Büyülü hasar: İsabetliliği daha düşük fakat hasar daha fazla


Stilimizi ve tipimizi seçerek saldırı yapıyoruz. Rakip de aynı şekilde stilini ve tipini seçerek bize saldırıyor.
İsabetlilik oranı (accuracy)'den bahsedeyim bir de. İsabetlilik oranı yüksek ise rakibin bizim vuruşumuzu bloklama şansı daha düşüktür. İsabetlilik oranımız az ise rakibin bizim vuruşumuzu bloklama şansı daha fazladır.
Hasarların, isabetlilik oranının vs. matematiksel dengesini kodları inceleyerek görebilirsiniz.
Mesela bossların hangi levellerde geleceğini yukarıda belirtmiştim. Bunu kodlarda da görebilirsiniz şu şekilde:


Kodları inceleyerek oyundaki matematiksel dengeyi analiz edebilirsiniz. Fiziksel hasar neye göre hesaplanıyor ? İsabetlilik oranı neye göre hesaplanıyor gibi soruların hepsinin cevabını kodları inceleyerek görebilmeniz mümkün.

self.player_figth_statistics = {
            "Accuracy": self.player_statistics[self.coordination["Attack"]] - self.enemy_statistics[self.coordination["Defence"]],
            "Physical Damage": self.player_statistics[self.coordination["Strength"]] - self.enemy_statistics[self.coordination["Stamina"]],
            "Magical Damage": self.player_statistics[self.coordination["Magic"]] * 2.5 - self.enemy_statistics[self.coordination["Stamina"]], 
            "Additional Damage": self.player_statistics[self.coordination["Agility"]] * 1.5
        }
        self.enemy_figth_statistics = {
            "Accuracy": self.enemy_statistics[self.coordination["Attack"]] - self.player_statistics[self.coordination["Defence"]],
            "Physical Damage": self.enemy_statistics[self.coordination["Strength"]] - self.player_statistics[self.coordination["Stamina"]],
            "Magical Damage": self.enemy_statistics[self.coordination["Magic"]] * 2.5 - self.player_statistics[self.coordination["Stamina"]], 
            "Additional Damage": self.enemy_statistics[self.coordination["Agility"]] * 1.5
        }

Mesela buradan göreceğiniz üzere fiziksel hasar bu şekilde hesaplanıyor:

self.player_statistics[self.coordination["Strength"]] - self.enemy_statistics[self.coordination["Stamina"]]

Yani:
Strength skilli - Stamina skilli
Güç - dayanıklılık (rakibin dayanıklılığı)

Accuracy’nin hesaplanışını da aynı şekilde görebilirsiniz.
Kısacası kodları inceleyerek edinebileceğiniz bir sürü ipucu bulunmaktadır diyorum.


Kodlar hakkında eleştirilerinizi bildirebilmeniz için main.py’yi burada da göstereyim:

class Game:
    def __init__(self):
        self.status = True
        self.hit = 0
        self.player_statistics = []
        self.encounter_text = (
            r"""
                    --------------------------------------
                            \\ STAGE {} //
                            ******* Hit {} *******
                            Opponnent: ︶ノ︵  {}  ︶ノ︵
                            -------------------------
                            Opponnent's Statistics:
                            Strength: {}
                            Agility: {}
                            Attack: {}
                            Defence: {} 
                            Vitality: {}
                            Stamina: {}
                            Magic: {}
                    --------------------------------------
            
            """
        )
        self.coordination = {
            "Strength": 0,
            "Agility": 1,
            "Attack": 2,
            "Defence": 3,
            "Vitality": 4,
            "Stamina": 5,
            "Magic": 6
        }
        
        with open("stage.txt", "r") as stage:
            self.stages = iter(range(int(stage.read()), 101))
            
        with open("enemy_names.json", "r") as enemy_name_datas:
            self.enemy_names = list(json.load(enemy_name_datas))
        
        with open("skill_points.json", "r") as data_base:
            self.player_skill_points = list(json.load(data_base))[0]
            data_base.seek(0)
            self.enemy_skill_points = list(json.load(data_base))[1]
        
        with open("player_skills.json", "r") as data_base:
            self.player_skill_datas = json.load(data_base)
            self.player_statistics = [
                self.player_skill_datas["Strength"], self.player_skill_datas["Agility"],
                self.player_skill_datas["Attack"], self.player_skill_datas["Defence"],
                self.player_skill_datas["Vitality"], self.player_skill_datas["Stamina"],
                self.player_skill_datas["Magic"]
            ]
            
    def distribute(self, count: int, size=7) -> list:
        N = size      
        list_ = sorted([random.randint(1, count-1) for i in range(N - 1)])
        list_.insert(0, 0)
        list_.append(count)
        result = []

        for i in range(N):
            result.append(list_[i + 1] - list_[i])

        return result
    
    
    def percent(self, percent: int) -> bool:
        return True if random.choice([i for i in range(1, 101)]) <= percent else False
    
    
    def skill_upgrade_menu(self):
        # Wanted skills that user's wanna update.
        upgraded_skills = input(
            f"""
            =================================================================================
            Choose whichever you want to upgrade and follow this syntax:
            <ability>: <upgrade value> | <ability>: <upgrade value> | ..... 
            Don't forget: Abilities can upgrade by 1 per 1 skill point. Spend them carefully
            
            Info 1: Be sensitive to spaces
            >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            False ----------> Strength:6
            True  ----------> Strength: 6                
            <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            You don't need to be sensitive to upper and lower case letters.
            
            Info 2: The values ​​in your entry providing information about the upgrade must be 1 digit.
            >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            False ----------> Strength: 10
            True  ----------> Strength: 9 | Strength: 1
            *********************************************
            False ----------> Strength: 16
            True  ----------> Strength: 9 | Strength: 7
            <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            =================================================================================
            
                    Strength: {self.player_statistics[self.coordination["Strength"]]} 
                    Agility: {self.player_statistics[self.coordination["Agility"]]}
                    Attack: {self.player_statistics[self.coordination["Attack"]]}
                    Defence: {self.player_statistics[self.coordination["Defence"]]}
                    Vitality: {self.player_statistics[self.coordination["Vitality"]]}
                    Stamina: {self.player_statistics[self.coordination["Stamina"]]}
                    Magic: {self.player_statistics[self.coordination["Magic"]]}
                        
                    Skill Points: {self.player_skill_points}
            ------------------------------------------------------------------------------
            ↓↓
            """
        )

        amounts = []
        for i in "".join(upgraded_skills.split("|")):
            if i.isdigit():
                amounts.append(int(i))
            
        abilities = []
        for i in range(len("".join(("".join(upgraded_skills.split("|")).split(":"))).split()) - 1):
            if "".join(("".join(upgraded_skills.split("|")).split(":"))).split()[i].isalpha():
                abilities.append("".join(("".join(upgraded_skills.split("|")).split(":"))).split()[i])
            
        for i in range(len(abilities)):
            try:
                self.player_statistics[self.coordination[abilities[i].lower().capitalize()]] += amounts[i]
            except KeyError:
                print("Please be sensitive to spaces")
                
        if sum(amounts) > self.player_skill_points:
            print(f"\n{60 * '*'}")
            print("\tOut of range skill points" + f"\n\t\t You have {self.player_skill_points} skill points but you spent {sum(amounts)}")
            print(60 * "*")
            self.skill_upgrade_menu()
            
        else:
            with open("player_skills.json", "w") as data_base:
                datas = dict(self.player_skill_datas)
                new_statistic = [i[0] + i[1] for i in list(zip([i for i in datas.values()], [i for i in self.player_statistics]))]
                json.dump(dict(zip(self.coordination.keys(), new_statistic)), data_base)
                
            with open("skill_points.json", "w") as data_base:
                self.player_skill_points -= sum(amounts)
                json.dump(list([self.player_skill_points, self.enemy_skill_points]), data_base)
    

    def encountering(self, hit: int):
        self.player_figth_statistics = {
            "Accuracy": self.player_statistics[self.coordination["Attack"]] - self.enemy_statistics[self.coordination["Defence"]],
            "Physical Damage": self.player_statistics[self.coordination["Strength"]] - self.enemy_statistics[self.coordination["Stamina"]],
            "Magical Damage": self.player_statistics[self.coordination["Magic"]] * 2.5 - self.enemy_statistics[self.coordination["Stamina"]], 
            "Additional Damage": self.player_statistics[self.coordination["Agility"]] * 1.5
        }
        self.enemy_figth_statistics = {
            "Accuracy": self.enemy_statistics[self.coordination["Attack"]] - self.player_statistics[self.coordination["Defence"]],
            "Physical Damage": self.enemy_statistics[self.coordination["Strength"]] - self.player_statistics[self.coordination["Stamina"]],
            "Magical Damage": self.enemy_statistics[self.coordination["Magic"]] * 2.5 - self.player_statistics[self.coordination["Stamina"]], 
            "Additional Damage": self.enemy_statistics[self.coordination["Agility"]] * 1.5
        }
        
        print(self.encounter_text.format(self.stage, hit, self.enemy_name, *[i for i in list(self.enemy_statistics)]))
                
        # Attacking Styles
        player_attack_menu = (
            """
                            *********************
                            * YOU ARE ATTACKING!*
                            *********************
                            
            >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            Tip:
             Critical: 
              The chances of an accurate shot are too low. 
              But it makes your damage 6 times more effective
              
             Power: 
              The chances of an accurate shot are low. 
              But its damage is 3 times more effective.
              
             Quick:
              The chances of an accurate shot are too high. 
              But its damage is common.
            
            Tip:
             Magical damages are more effective than physical damages. 
             But its accuracy is lower.
            >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            =====================================================================================
            Choose a hit style by dialing their numbers:
            
            Critical:                     Powerful:                     Quick:
                [10] Critical (Physical)     [20] Powerful (Physical)     [30] Quick (Physical)        
                [11] Critical (Magical)      [21] Powerful (Magical)      [31] Quick (Magical)
            =====================================================================================
            ----------------------------------------------------------------------------
            ↓↓
            """
        )
        time.sleep(4)
        player_hit_style = input(player_attack_menu)
        self.figth_result_text = (
            """
            
                            ===============================
                            *****************************
                            {} Dealt {} {} Damage !
                            *****************************
                            Player's Health Has Left {}
                            *****************************
                            Enemy's Health Has Left {}
                            *****************************
                            ===============================
            """
        )
        blocked_hit_text = (
            """
                          *********************************
                          {}
                          *********************************
            """
        )
        
        # Absolute Damages
        self.player_physical_damage = self.player_figth_statistics["Physical Damage"] + (self.player_figth_statistics["Additional Damage"] if self.percent(30) else 0) 
        self.player_physical_damage = 0 if self.player_physical_damage < 0 else self.player_physical_damage
        
        self.player_magical_damage = self.player_figth_statistics["Magical Damage"] + (self.player_figth_statistics["Additional Damage"] if self.percent(30) else 0)
        self.player_magical_damage = 0 if self.player_magical_damage < 0 else self.player_magical_damage
        
        
        # ------ Player's hit -----------
         
        if player_hit_style == "10":
            if self.percent(10 + self.player_figth_statistics["Accuracy"]):
                self.enemy_health -= self.player_physical_damage * 6 # Multiplied by 6 because this is a critical damage.
                print(self.figth_result_text.format("You", self.player_physical_damage * 6, "Physical", self.player_health, self.enemy_health))
            
            else:
                print(blocked_hit_text.format("Your Opponnent Blocked Your Hit !"))
                
        elif player_hit_style == "11":
            if self.percent(10 + self.player_figth_statistics["Accuracy"]-20): # minus twenty. Because it is magical damage.
                self.enemy_health -= self.player_magical_damage * 6 # Multiplied by 6 because this is a critical damage.
                print(self.figth_result_text.format("You", self.player_magical_damage * 6, "Magical", self.player_health, self.enemy_health))
        
            else:
                print(blocked_hit_text.format("Your Opponnent Blocked Your Hit !"))
                
        elif player_hit_style == "20":
            if self.percent(20 + self.player_figth_statistics["Accuracy"]):
                self.enemy_health -= self.player_physical_damage * 3 # Multiplied by 3 because this is a powerful damage.
                print(self.figth_result_text.format("You", self.player_physical_damage * 3, "Physical", self.player_health, self.enemy_health))
    
            else:
                print(blocked_hit_text.format("Your Opponnent Blocked Your Hit !"))
                
        elif player_hit_style == "21":
            if self.percent(20 + self.player_figth_statistics["Accuracy"]-20): # minus twenty. Because it is magical damage.
                self.enemy_health -= self.player_magical_damage * 3 # Multiplied by 3 because this is a powerful damage.
                print(self.figth_result_text.format("You", self.player_magical_damage * 3, "Magical", self.player_health, self.enemy_health))
            else:
                print(blocked_hit_text.format("Your Opponnent Blocked Your Hit !"))
                
        elif player_hit_style == "30":
            if self.percent(70 + self.player_figth_statistics["Accuracy"]):
                self.enemy_health -= self.player_physical_damage # No multiplication because this is a quick attack style.
                print(self.figth_result_text.format("You", self.player_physical_damage, "Physical", self.player_health, self.enemy_health))
            else:
                print(blocked_hit_text.format("Your Opponnent Blocked Your Hit !"))
                
        elif player_hit_style == "31":
            if self.percent(70 + self.player_figth_statistics["Accuracy"]-20): # minus twenty. Because it is magical damage.
                self.enemy_health -= self.player_magical_damage # No multiplication because this is a quick attack style.
                print(self.figth_result_text.format("You", self.player_magical_damage, "Magical", self.player_health, self.enemy_health))
            else:
                print(blocked_hit_text.format("Your Opponnent Blocked Your Hit !"))
                
        else:
            print("Please dial a number displayed in menu")
        
        
        #      ------ enemy's hit -----------
        print(
            """
                            ***********************
                            * ENEMY IS ATTACKING! *
                            ***********************
            """
        )
        
        time.sleep(1)
        for i in range(6):
            print("🕒" * i)
            time.sleep(0.6) 
            
        styles = [
            1 * [["Critical Physical", "Critical Physical", "Critical Magical"]], # 10% Chance
            3 * [["Powerful Physical", "Powerful Physical", "Powerful Magical"]], # 30% Chance 
            6 * [["Quickly Physical", "Quickly Physical", "Quickly Magical"]] # 60% Chance
        ]
        self.enemy_hit_style = random.choice(random.choice(random.choice(styles)))
        
        # Absolute Damages
        self.enemy_physical_damage = self.enemy_figth_statistics["Physical Damage"] + (self.enemy_figth_statistics["Additional Damage"] if self.percent(30) else 0)
        self.enemy_physical_damage = 0 if self.enemy_physical_damage < 0 else self.enemy_physical_damage
        
        self.enemy_magical_damage = self.enemy_figth_statistics["Magical Damage"] + (self.enemy_figth_statistics["Additional Damage"] if self.percent(30) else 0)
        self.enemy_magical_damage = 0 if self.enemy_physical_damage < 0 else self.enemy_physical_damage
        
        if self.enemy_hit_style == "Critical Physical":
            if self.percent(5 + self.enemy_figth_statistics["Accuracy"]):
                self.player_health -= self.enemy_physical_damage * 6 # Multiplied by 6 because this is a critical damage.
                print(self.figth_result_text.format("Enemy", self.enemy_physical_damage * 6, "Physical", self.player_health, self.enemy_health))
                
            else:
                print(blocked_hit_text.format("You Blocked your Opponnent's Hit"))
            
        elif self.enemy_hit_style == "Critical Magical":
            if self.percent(5 + self.enemy_figth_statistics["Accuracy"]-20): # minus twenty. Because it is magical damage.
                self.player_health -= self.enemy_magical_damage * 6 # Multiplied by 6 because this is a critical damage.
                print(self.figth_result_text.format("Enemy", self.enemy_magical_damage * 6, "Magical", self.player_health, self.enemy_health))
                
            else:
                print(blocked_hit_text.format("You Blocked your Opponnent's Hit"))
            
        elif self.enemy_hit_style == "Powerful Physical":
            if self.percent(10 + self.enemy_figth_statistics["Accuracy"]):
                self.player_health -= self.enemy_physical_damage * 3 # Multiplied by 3 because this is a powerful damage.
                print(self.figth_result_text.format("Enemy", self.enemy_physical_damage * 3, "Physical", self.player_health, self.enemy_health))
                
            else:
                print(blocked_hit_text.format("You Blocked your Opponnent's Hit"))
            
        elif self.enemy_hit_style == "Powerful Magical":
            if self.percent(10 + self.enemy_figth_statistics["Accuracy"]-20): # minus twenty. Because it is magical damage.
                self.player_health -= self.enemy_magical_damage * 3 # Multiplied by 3 because this is a powerful damage.
                print(self.figth_result_text.format("Enemy", self.enemy_magical_damage * 3, "Magical", self.player_health, self.enemy_health))
                
            else:
                print(blocked_hit_text.format("You Blocked your Opponnent's Hit"))
            
        elif self.enemy_hit_style == "Quickly Physical":
            if self.percent(65 + self.enemy_figth_statistics["Accuracy"]):
                self.player_health -= self.enemy_physical_damage # No Multiplication because this is a powerful damage.
                print(self.figth_result_text.format("Enemy", self.enemy_physical_damage, "Physical", self.player_health, self.enemy_health))
                
            else:
                print(blocked_hit_text.format("You Blocked your Opponnent's Hit"))
            
        elif self.enemy_hit_style == "Quickly Magical":
            if self.percent(65 + self.enemy_figth_statistics["Accuracy"]-20): # minus twenty. Because it is magical damage.
                self.player_health -= self.enemy_magical_damage # No Multiplication because this is a powerful damage.
                print(self.figth_result_text.format("Enemy", self.enemy_magical_damage, "Magical", self.player_health, self.enemy_health))
                
            else:
                print(blocked_hit_text.format("You Blocked your Opponnent's Hit"))
                
            
    def play(self):
        # define stage
        try:
            self.stage = next(self.stages)
        except StopIteration:
            print("GAME OVER")
            self.status = False
        
        # define enemy names
        self.enemy_name = self.enemy_names[self.stage-1]
        
        # increase enemy skill points according to stages.
        if self.stage % 2 != 0 and self.stage % 5 == 0:
            self.enemy_skill_points += 5
             
        elif self.stage % 10 == 0:
            self.enemy_skill_points += 10
            
        else:
            self.enemy_skill_points += 1
        
        # enemy statistics
        if self.stage == 1:
            self.enemy_statistics = self.distribute(self.enemy_skill_points)
        
        else:
            self.enemy_statistics = self.distribute(self.enemy_skill_points)

        # saving amounts to files.
        with open("enemy_skills.json", "w") as data_base:
            json.dump(self.enemy_statistics, data_base)
        
        with open("skill_points.json", "w") as data_base:
            json.dump(list([self.player_skill_points, self.enemy_skill_points]), data_base)
        
        with open("stage.txt", "w") as data_base:
            print(str(self.stage), file=data_base, flush=True)
        
        # Customizing First Stage
        if self.stage == 1:
            print(
                """
                -------------------------------------------------------------------------------
                Welcome to the Game ! 
                This is a PvP game played in terminal and it also like "Swords and Sandals II". 
                Your target is reaching to the last stage and beating the last boss. 
            
                --> Categories of brawler statistics:
                
                 Offensive:
                    Strength: It increases your Physical Damage. Your Physical Damage depends on this skill
                    Magic: It increases your Magical Damage. Your Magical Damage depends on this skill
                    Agility: Its value is multiplied by 1.5 and
                     there is a 30% Chance that you can add this damage next to your normal damage.
                
                 Defancive:
                    Stamina: It decreases your opponnent's damage
                
                 Accuracy:
                    Attack: It increases your succesful attack chance. So your accuracy depends on this skill
                    Defence: It increases your block chance.
                    
                 Health:
                    Vitality: Its value is multiplied by three (ten if stage is more than 20) and added to your health. 
                
                --> WARNING:
                 Everything is saved when you exit the program.
                 But be careful when you are quitting. 
                 You must exit the game when you are moving to a new stage. 
                 Otherwise, your skills may not be recorded.
                 
                --> The Logic of the game:
                 There are 100 stages in this game and you are tryna reach till to the last stage.
                 You fight with an enemy in every stages. You must kill them to transitioning to a next stage.
                 Everyone has some skills to beat each other. 
                 So, you have skills too. You and other enemies are  needing skill points to upgrade a skill.
                 You must transition to a next stage to get more skill points.
                 There are some bosses in this game.
                 Masters (M) and Grandmasters (GM). GMs are more powerful.
                 
                 Masters are coming in these stages :
                 print(list(filter(lambda x: True if x % 5 == 0 and not x % 2 == 0 else False, range(1, 100+1))))
                 
                 Grandmasters are coming in these stages:
                 print(list(filter(lambda x: False if x % 10 else True, range(1, 100+1))))
                 
                 And here are some attack styles. Magical and physical attack styles.
                 Magical attacks are more effective than physical attacks. 
                 But magical attack's accuracy is lower.
                 
                 
                 --> TIP:   
                 It is recommended to upgrade physical damage in the early stages, 
                 and it is recommended to use one of the attack styles, the "quick" style. 
                 Because the magic damage in the early stages is unlikely to be accurate.
                 Likewise, "powerful" and "critical" attack styles are unlikely to be accurate.
                 So it is recommended to be prone to physical damage in the early stages and 
                 to use the "quick" style heavily.
                ------------------------------------------------------------------------------
                """
            )
            self.skill_upgrade_menu()
        
        # Healths 
        self.player_health = 30 + self.player_statistics[self.coordination["Vitality"]] * (3 if self.stage < 20 else 10)
        self.enemy_health = 30 + self.enemy_statistics[self.coordination["Vitality"]] * (3 if self.stage < 20 else 10)
        
        # Refresh hit for next stage.
        self.hit = 0
        
        # Loop of every stage.
        if self.stage in [i for i in range(1, 100+1)]:
            while True:
                if not self.player_health > 0:
                    print(
                        """
                                        xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                                                You Have Been Slained
                                        xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                        """
                    )
                    exit()
                
                elif not self.enemy_health > 0:
                    break
            
                else:
                    self.hit += 1
                    self.encountering(self.hit)
                    
                
            self.player_skill_points += 1
            with open("skill_points.json", "w") as data_base:
                json.dump(list([self.player_skill_points, self.enemy_skill_points]), data_base)

            print(
                """
                            ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
                                You have successfully completed the episode
                                after your opponent's last hit before he died!
                            ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
                """
            )
            self.skill_upgrade_menu()
            
        else:
            print("YOU HAVE FINISHED THE GAME !")
            
    
if __name__ == '__main__':
    import json
    import random
    import time
    
    game = Game()
    while game.status:
        game.play()

Videoda İngilizce konuşuyorum. Ne kadar başarılı olmuştur pek bir fikrim yok. Çoğunlukla doğaçlama oldu :smiley: Biraz yavaş konuştum bundan dolayı. Sıkıcı olmuşsa kusuruma bakmayın.


En zor olan şey matematiksel dengeyi kurabilmekti. Ki halen kurabildiğimi tam olarak sanmıyorum.
matematiksel dengeden kastım bu sorularla ilişkilidir:
Strength skilli neye göre hesaplanmalı ?
Critical saldırı tipi kaç ile çarpılmalı ve dolayısıyla kaç hasar vurmalı ?
Stage başına biz ne kadar skill point almalıyız ? Düşman ne kadar almalı ?

Bu tarz soruların cevabının son derece dengeli olması gerekiyor. “Örneğin” dengesiz bir şey yapsaydım oyuncu, oyunun başından sonuna kadar skill point’lerini strength’e harcayıp herkese tek atabilirdi.


Ekleyeyim:
Oyun "Swords and Sandals II"ye de benzemektedir. Fikri oradan geliyor zaten.


Umarım beğenirsiniz.

11 Beğeni

(karakter sınırını aştığım için konuyu editleyemedim.)
Burada yazdıklarım projeyle ilgili kafanızda bir fikir oluşturmuş olmalı. Ancak tavsiyem tam olarak anlayabilmeniz için repoyu klonlayıp oyunu kendiniz denemeniz olacaktır. Ki zaten oyun içerisinde bir çok ipucu var. Nasıl oynayacağınız konusunda size bilgi vereceklerdir. Birazcık oynadıktan sonra mantığını hemen kavrayacaksınızdır. Sadece skiller hakkında fikir sahibi olmanız gerekiyor. Ki bunun için de oyun içerisinde ipuçları bulunuyor söylediğim gibi. Mesela:

            Offensive:
                    Strength: It increases your Physical Damage. Your Physical Damage depends on this skill
                    Magic: It increases your Magical Damage. Your Magical Damage depends on this skill
                    Agility: Its value is multiplied by 1.5 and there is a 30% Chance that you can add this damage next to your normal damage.
                     
                
                 Defancive:
                    Stamina: It decreases your opponnent's damage
                
                 Accuracy:
                    Attack: It increases your succesful attack chance. So your accuracy depends on this skill
                    Defence: It increases your block chance.
                    
                 Health:
                    Vitality: Its value is multiplied by three (ten if stage is more than 20) and added to your health.

Son olarak, Eğleneceğinizi umuyorum :slight_smile:
Edit:
json dosyalarından da tahmin edebileceğiniz üzere, ilerlemeniz kaydediliyor. Her stage atlayışınızda ilerlemeniz kaydedilir.

tamam açık kaynak kodlu olduğuna göre ben kendimi ölümsüz yapacağım :smiley:. bu arada sana tavsiyem oyunu kapalı kaynak kod olarak paylaşman o zaman kimse yarın benim yapacağım gibi hile yapamaz. Ama çok önemsemiyorsan gerek yok.

3 Beğeni

Tek kisilik bir oyun zaten, hile yapilmasinda bir sorun yok. Ozgur bir yazilimdan soz ediyoruz, ve hile yapilmasin diye kapali kaynak yap diyorsunuz.

Sizi ozgur yazilim felsefesini anlamaya davet ediyorum.

2 Beğeni

Benim amacım her zaman, yapılan şeylerden tecrübe edinmek ve kendimizi geliştirmektir.
Üstelik zaten online olarak oyuncularla oynanan bir şey de yapmadım. Açık kaynak olması sayesinde isteyen herkes bir takım şeyleri kendine göre tasarlayabilir ki bu çok güzel bir şeydir ve dediğim gibi online bir şey olmadığı için bunun kimseye zararı olmayacaktır.
Eğer kendinizi geliştirmenize yardımcı olacaksa istediğiniz kadar hile yapabilirsiniz :slight_smile: Yeter ki sizi bir adım daha ileri taşısın.

4 Beğeni

Bu skillerden biri olan staminanın hesaplanışı hakkında bir noktada hata yaptığımı fark ettim ve düzelttim.
Bunun dışında magical damage’in isabetliliği arttırıldı
Repoda main.py güncellendi
:+1:

Aklıma cursor’u hareket ettirerek konsol üzerinde yaptığım animasyonlu platformer game geldi…

Her zamanki gibi, tebrikler…

1 Beğeni

Yeni ve önemli bir güncelleme yaptım.
Skill point’lerinizi yükselteceğiniz zaman input() fonksiyonuna yükseltmeyle alakalı değerlerinizin girilmesi gerekiyor. Yani kullanıcıdan veri alınıyor.
Kullanıcı skill point’i olmadığı durumda mecburen bir değer girmiyor ve bu programda bir buga sebep oluyor. Skill point’leriniz ikiye katlanıyordu ve çok can sıkıcı bir durumdu. Sık sık denk gelinmese de önemli bir sorundu ve tek sorun buydu.
Bu güncelleme ile bu bugu düzelttim ve artı olarak kullanıcının bossları yendiği zaman 1 değil 5 skill point kazanmasını sağladım. Oyunu biraz daha eğlenceli kılmak adına biraz daha Over Powered bir profilimiz oldu.

1 Beğeni