This is Item Drops Tutorial (17) in the pygame RPG series
We have successfully created a very basic RPG environment, complete with enemies, stage clear prompts, status bar etc. One very “RPG-ish” thing we’re missing however, is Item drops.
Item drops is a really great feature due to the flexibility and wide range of features it can bring. Ranging from health recoveries, power-ups, special abilities and money, Item drops can bring a spark of life into what otherwise may be a dull and boring RPG.
In this tutorial, we’ll be working on adding “Health” and “Money” Item drops into our Pygame RPG. Furthermore, by the end of this tutorial, we’ll have created a framework, allowing you to add any number of Items into the game.
The first step is to begin creating an Item class. One thing we can take advantage of, is the re-usability that classes offer. Instead of creating separate classes for each Item drop that we make, we’ll just one class. Of course, we’ll have to be a bit smart about it how create the functions and parameters to allow for such a possibility.
For the first time, we’re including an extra parameter in the
init function. These parameter will be used to determine the item number that we’re created. As you can see below, the image we load into the created Item, varies on the value of the
class Item(pygame.sprite.Sprite): def __init__(self, itemtype): super().__init__() if itemtype == 1: self.image = pygame.image.load("heart.png") elif itemtype == 2: self.image = pygame.image.load("coin.png") self.rect = self.image.get_rect() self.type = itemtype self.posx = 0 self.posy = 0
For future use in other functions of the Item class, we’re also going to save itemtype into a variable called
Item.render() function, we’re going to update the values of rect of the Item with the position variables, and then
blit (draw) it to the screen.
def render(self): self.rect.x = self.posx self.rect.y = self.posy displaysurface.blit(self.image, self.rect)
We haven’t actually assigned the position variables any value here (besides the default of 0). This part will make more sense later when we actually work on the Enemy class, where the Item will be generated.
Before we proceed any further, let’s quickly review what these Items are going to do. The Health Item is meant to be a restorative item that heals you by one “heart”, as long as you aren’t at full health.
The Money item is obviously meant to be our currency in this game, obtained from beating enemies. We haven’t added an actual Money system yet, where we can purchase or sell things, but this serves as the base foundation.
We’ve assigned the Health and Money items, the
itemtypes of “1” and “2” respectively.
Back to the actual coding part now.
update() function is the part of the code responsible for checking whether the Player has “collected” the item or not. We determine that the Player has “collected” the item if he comes into contact with it. Which is a pretty standard way in many RPGs.
def update(self): hits = pygame.sprite.spritecollide(self, Playergroup, False) # Code to be activated if item comes in contact with player if hits: if player.health < 5 and self.type == 1: player.health += 1 health.image = health_ani[player.health] self.kill() if self.type == 2: # handler.money += 1 self.kill()
If the collision is detected, we then once again split into various blocks. The block that runs will be determined by the itemtype. In the above example, if the
1, the health will be increased by 1.
We currently don’t have anything except a commented out piece of code in the second block, which would run if it was a money item. This is something we’ll develop further if we ever create a proper money system.
We now have to decide where we want the item generation code to be. The place that makes the most sense to me, is in the enemy class. Or more specifically, in the function where the kill code is stored.
The reason behind this being, Item drops are typically found when enemies are killed. So it makes sense to generate the item here.
One problem however, is that Items are typically generated with a randomized chance (e.g: 10% chance). In order to fully implement the concept of Items, we need to come up with a way to determine with a new technique. Luckily, the numpy library can help us here with it’s
rand_num = numpy.random.uniform(0, 100)
The above line will generate numbers from 0 to 100. The unique feature about
random.uniform, is that it has a uniform spread. If we run the above line 1000 times, each number from 0 – 100 will repeat about 10 times. Unlike a regular random function where there would be an uneven spread (in most scenarios)
So how does this help us in adding Item drops into our Pygame RPG? Look at the below code, belonging to the enemy
# Activates upon either of the two expressions being true if hits and player.attacking == True or f_hits: self.kill() if player.mana < 100: player.mana += self.mana # Release mana player.experiance += 1 # Release expeiriance rand_num = numpy.random.uniform(0, 100) item_no = 0 if rand_num >= 0 and rand_num <= 5: # 1 / 20 chance for an item (health) drop item_no = 1 elif rand_num > 5 and rand_num <= 15: item_no = 2
We allocated the number 0 – 5 for Item1, and 6 – 15 for Item2. In other words, there is a 6% chance of a Health item dropping, and a 10% chance of a Coin dropping.
It may look unorthodox, but this is really one of the only ways to do it. Asking a computer, which runs off logic, to come up with a random value is not that simple.
We still aren’t done yet though! The below block of code comes right after the previous one, in the same function. We still have to add the Item into the Items group, and set it’s location.
First, we pass the
item_no into the Item class, which creates the appropriate item.
if item_no != 0: # Add Item to Items group item = Item(item_no) Items.add(item) # Sets the item location to the location of the killed enemy item.posx = self.pos.x item.posy = self.pos.y
The last two lines of the above code, set the position of the item, to that of the enemy. This way the item appears in the exact location where the enemy was killed.
To make thing easier on us, we’re going to make a Items class where store all our items. We’ve already shown you multiple times in the above code, how and where to add the Item into the Items group.
Items = pygame.sprite.Group()
(You have to create the Items group outside the game loop!)
The benefit of this class is, that it allows us to iterate over all the items in it and call the same function on them.
for i in Items: i.render() i.update()
(We increased the item drop chance for the purpose of this video)
The next tutorial is going to be quite interesting and full of new concepts. We’ll be adding buttons, a new cursor, and the ability to pause and resume your game at will.
This marks the end of the Pygame RPG – Item Drops tutorial. Any suggestions or contributions for CodersLegacy are more than welcome. Questions about the tutorial content can be asked in the comments section below.