Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

[Ren'py] [Programer] Can you explain classes?

A topic by AxalKay created 66 days ago Views: 169 Replies: 3
Viewing posts 1 to 3

Hello. I am trying to learn how to code in ren'py (python). I watched ren'py tutorials. I watched python tutorial. I don't get it. It is frustrating. Often times people will say do this, but not explain the process. Even longer turorials focus more on  width than depth.

  I love pen and paper games, but most people are more interested in video games. I would appreciate help traslating a pen and paper game to a video game.

  If it is not too much trouble I would like help making a simple combat system. The biggest barrier I am facing is classes (objects). I don't understand object orriented programing. Different tutorials say different thing. Would you be able to explain oop to me?

(+1)

I haven't used ren'py and I don't usually program in python, but I can try to explain classes in a simple way.

I'll use a pseudo-code and try to keep it python-like, but it may not be exactly correct python code.

As you probably know, you can use a variable to store a simple piece of data like a number or string. A function gives a name to a grouping of code, which can take in variables and return them. Before getting into classes, you could implement code to attack an enemy in a very simple way using just variables and functions:


def attack_enemy(damage_amount, enemy_hp):
    new_hp = enemy_hp - damage_amount
    return new_hp
enemy_max_hitpoints = 100
enemy_current_hitpoints = 100
enemy_current_hitpoints = attack_enemy(5, enemy_current_hitpoints)
if enemy_current_hitpoints <= 0
    print("You defeated the enemy)


This is not that great but works ok if you only have one enemy and limited amount of data and functions. Tracking multiple enemies becomes cumbersome if you have to define a separate variable for every enemy and every enemy's HP. Now imagine you have more variables you want to track for an enemy, like their location, what they're doing, etc.

The first thing you can do with a class is bundle together a bunch of different variables and then refer to it with a single variable (the "object"). You can think of an object as a group of variables for now. This is similar to a struct in other languages. This first part is pseudocode to simplify the concept:

class Enemy:
    max_hp = 100
    current_hp = 100
    strength = 5
    location_x = 50
    location_y = 50
def attack_enemy(damage_amount, enemy):
    enemy.current_hp = enemy.current_hp - damage_amount
def move_enemy_randomly(enemy):
    enemy.location_x = random_x_location()
    enemy.location_x = random_x_location()
enemyA = Enemy() 
enemyB = Enemy() 
attack_enemy(5, enemyA)  
attack_enemy(10, enemyB)

Now you can an enemy "object" which bundles together different data points about a particular enemy. Each enemy object holds their health, strength, location, and whatever else you want. You can refer to an enemy object with a single variable like enemyA, and pass it to functions. Then you can get or set particular attributes of the enemy using the dot syntax, enemy.current_hp = enemy.current_hp - 5

This by itself is pretty useful, because now you could create a bunch of different enemies and pass them to functions to do things like attack or move them.

You can use classes this way pretty effectively without even learning more about OOP or using methods, but a common next step is to bundle methods with the class. A method is basically a function like shown above, but instead of being standalone, it's defined within the class itself, so you can do this:


class Enemy:     
    current_hp = 100      
def attack(damage_amount):         
    current_hp = current_hp - damage_amount
enemyA = Enemy()
enemyA.attack(5)


This is equivalent to the code above with the attack_enemy function, but defining the method "attack" inside of the enemy class means you can call it as if it's a property of the enemy, like enemyA.attack(5), instead of passing enemyA as a parameter to a function like attack_enemy(5, enemyA). Either way of doing things works, but it's common to bundle behaviors related to the enemy into methods within the class.

You could imagine other methods you could define on an enemy, which would interact with the data on the enemy itself and in some cases return data:
- attack_player()
- gain_strength()
- is_dead()
- drop_loot()
- take_a_nap()
- revive()

As a python specific note, you don't define the attributes as I did above, but more like this:

class Enemy:
    def __init__(self, hp):
        self.max_hp = hp
        self.current_hp = hp

The __init__ is a special function that runs when you create an enemy with Enemy(). It allows you to pass in initial data, like Enemy(100) (initializes HP to 100). self is a python keyword that has to be the first argument of every method, but you don't have to pass it in. self is basically a reference to the current object, so it's similar to doing this:

def attack_enemy(enemy, damage):
    # stuff...
enemy = Enemy() 
attack_enemy(enemy, damage)

This is a function that takes in an enemy object. A method defined with the self argument is doing the same thing - taking in an enemy object. The self just refers to the particular object that this method that it's being called on:

class Enemy:
    def attack(self, damage):
        self.current_hp = self.current_hp - damage self.check_if_dead_and_if_so_play_dying_animation()

enemyA.attack(5) # self will refer to the enemyA object
enemyB.attack(5) # self will refer to the enemyB object

So self gives you access to the data attributes and other methods of the object that the method is called on.

I hope this is helpful, let me know if something wasn't clear or you have followup questions.

(+1)

Thank you :)

(+1)

https://therealpenaz91.itch.io/2dgd-f0th

Here is a book that shows you more detail information about the topics. You can skip to the OOP section but if you can't understand it then try reading a bit from the beginning.


Download the python edition since you are working on ren.py.