[PYTHON] Make a 2D RPG with Ren'Py (3) -Items and Tool Shop

Overview

Hello, this is erotic gamers Kanimaru you're not Eroge recently, negative, the game production. This is the third 2D RPG production using Ren'Py. This time we will make items and tool stores.

Last time: Making a 2D RPG with Ren'Py (2) -Party and Status

** Scope of this article ** Implement items and enable them to be used from the menu screen and bought and sold at the tool shop

background

Why do I need an item for an RPG! I don't think anyone has that feeling. If you make an item before making a battle, you will be able to recover during the battle, so you will make an item first.

1. Make an item

First, create an item-Implement the part to be used from the menu screen.

System implementation

Like last time, this is just Python, not Ren'Py, so if you know Python, you can do whatever you want.

First, make ʻinventory` with dict type. Use key as the item instance and value as the number of possessed items. Since the user-defined type instance is hashable, it can be used as a dict type key. Convenient. I don't want to use global variables so much when writing Python code normally, but Ren'Py uses global variables mercilessly because there are some quirks.

inventory = {}

Next, create the ʻItem` class that is the basis of the item. Define the price, availability flag, etc. as instance variables. The method defines a getter that returns a message at the time of use, processing at the time of acquisition / sale, and so on.

class Item():
    def __init__(self, name, desc, price):
        self.name = name
        self.desc = desc
        self.price = price
        self.sell_price = int(price / 2.0)
        self.marketable_flag = True #If False, it cannot be sold
        self.usable_flag = True #If False, it cannot be used normally
        self.battle_flag = True #If False, it cannot be used during battle
        self.icon_image = "images/icons/medical_item.png "

    ###Omission: Basic getter###

    def get_confirm_msg(self):
        return self.name + "Do you use?"

    def get_result_msg(self):
        return self.name + "I used"

    #Purchase at the store
    def buy_item(self, buy_amount = 1):
        party_money.add_value(-self.price * buy_amount)
        inventory[self] += buy_amount

    #Sale at the store
    def sell_item(self, sell_amount = 1):
        party_money.add_value(self.sell_price * sell_amount)
        inventory[self] -= sell_amount

    #When picked up or received
    def find_item(self, find_amount = 1):
        inventory[self] += find_amount 

Create a class that inherits the ʻItem` class for each item type. Recovery items, status up items, material items, recipe items, etc. Implement what you need for your game. Below is the code for the recovery item class as an example.

--Target status of recovery items

Is newly defined. When using an item, call the ʻadd_current_value (diff) method of the instance of the target status to recover, and decrement the value of that item from the previously defined ʻinventory.

#Recovery item
class MedicalItem(Item):
    def __init__(self, name, desc, price, target_stat, amount):
        super(MedicalItem, self).__init__(name, desc, price)
        self.target_stat = target_stat
        self.amount = amount

    def get_target_stat(self):
        return self.target_stat

    def get_amount(self):
        return self.amount

    def get_usable_flag(self):
        if self.target_stat.get_current_value() == self.target_stat.get_max_value():
            return False
        else:
            return True

    #Raise the current price
    def use_item(self):
        self.target_stat.add_current_value(self.amount)
        inventory[self] -= 1

Once you've done this, add your items to ʻinventory` as follows:

medical_hp_small = MedicalItem(name = "A little bitter medicine", desc = "Recovers a small amount of physical strength.", price = 50, target_stat = stat_hp, amount = 40)
inventory[medical_hp_small] = 3

You can now manage your items.

UI implementation

This is Ren'Py's original. The result of this implementation is shown in the figure first. SnapCrab_griseo_2020-8-1_18-12-17_No-00.png The main functions and variables used are as follows.

--Display the item list on the menu screen (display the key whose value is greater than 0 from ʻinventory) --Color coding for currently available and unavailable items (using ʻusable_flag) --When you hover to the item name, the item description is displayed on the right (using Ren'Py's tooltip) --Click on an available item to use the tool (use ʻuse_item () `)

Then I will put the code.

screens.rpy


#Item screen settings
screen inventory():

    tag menu

    use game_menu(_("item"), scroll="None"):

        style_prefix "inventory"

        hbox: #Side by side status, item, item list
            spacing 40
            vbox: 
                ###Omitted: Status screen (see last time)###
            
            viewport: #Use viewport to scroll when there are many items
                scrollbars "vertical"
                mousewheel True
                draggable True
                pagekeys True
                xsize 350
                ysize 500
                vbox:
                    label _("item")
                    null height (2 * gui.pref_spacing)
                    for item, amount in inventory.items():
                        if amount > 0:
                            hbox:
                                $item_name = item.get_name()
                                $usable_flag = item.get_usable_flag()
                                $confirm_msg = item.get_confirm_msg()
                                $desc = item.get_desc()
                                $icon_image = item.get_icon_image()
                                add icon_image
                                if usable_flag and amount > 0: #When the item is available
                                    textbutton _(item_name + " " + str(amount)):
                                        tooltip desc 
                                        action Confirm(confirm_msg, UseItem(item))
                                else: #When it cannot be used. Note that tooltips cannot be used if insensitive
                                    textbutton _(item_name + " " + str(amount)):
                                        tooltip desc 
                                        action NullAction()
                                        text_style "unusable_text" #Change color
                                null height (gui.pref_spacing)

            vbox:
                xsize 350

                label _("Item details")
                $ tooltip = GetTooltip()
                if tooltip:
                    null height (4 * gui.pref_spacing)
                    text "[tooltip]"

###style omitted###

style unusable_text:
    color gui.insensitive_color

This code displays a Confirm screen that issues aconfirm_msg when an available item is clicked, and calls the ʻUseItem action if Yes is selected. ʻUse Item is a uniquely implemented Action.

screens.rpy


init:
    python:
        class UseItem(Action):
            def __init__(self, item):
                self.item = item

            def predict(self):
                renpy.predict_screen("notify")

            def __call__(self):
                renpy.notify(self.item.get_result_msg())
                self.item.use_item()

In Ren'Py, a class that inherits the ʻAction class can be called as an Action, and when called, the processing in call () is performed. Here, when ʻUseItem (item) is called, after getting the result_msg of ʻitem and displaying it in notify, the ʻuse_item () method of ʻitem` is called.

Finally, display the ʻinventory ()` screen created here in the game menu. It's the same as the status.

screens.rpy


screen navigation():

    ###Omission###

        if main_menu:

            ###Omission###

        else:

            textbutton _("status") action ShowMenu("stats")

            textbutton _("item") action ShowMenu("inventory") #Add this line

You can now use the item from the game menu.

2. Buying and selling at a tool shop

Now that you can use the item, let's buy and sell it at the tool shop. This is where the price andbuy_item ()methods defined in the ʻItem` class come into play.

System implementation

I don't have much to do here, I just define an item at a tool shop. This time I made it a list, but if you have the concept of inventory, you can handle it by making it with dict.

store.rpy


#Register an item at the tool shop
init python:
    store = [medical_hp_small, medical_hp_medium, enhancing_hp]

UI implementation

The result of implementation is also posted here. SnapCrab_griseo_2020-8-1_18-50-15_No-00.png It's a bit unnatural because it's made from existing images (especially scroll bars), but it's functionally completely a tool shop. Moreover, although it is not transmitted in the image, it makes a beeping sound when purchasing or selling. It's like a game!

Below is the code. The class definition is also posted at once.

store.rpy


init 1 python:
    #When the text button on the purchase imagemap is pressed
    class BuyItem(Action):
        def __init__(self, item):
            self.item = item

        def __call__(self):
            self.item.buy_item()
            renpy.restart_interaction()
            renpy.play("audio/sounds/coins.mp3")

    #When the text button on the sell imagemap is pressed
    class SellItem(Action):
        def __init__(self, item):
            self.item = item

        def __call__(self):
            self.item.sell_item()
            renpy.restart_interaction()
            renpy.play("audio/sounds/coins.mp3")

screen store_screen(store_instance):

    style_prefix "store"
    $current_money = party_money.get_value() #Global variable party_money(Get the current value from an instance of a properly created money class)

    frame:
        background "gui/store/blank.png "
        style_group "mm"
        xalign 0
        yalign 0
    hbox:
        xalign 0.05 yalign 0.03
        add "images/icons/money.png "
        text str(current_money)

    null height (4 * gui.pref_spacing)
    hbox: #Side by side buy imagemap and sell imagemap
        xalign 0.05
        yalign 0.4
        imagemap:
            ground "gui/store/background.png "
            label _("Purchase")   
            viewport:
                #yinitial yinitial
                scrollbars "vertical"
                mousewheel True
                draggable True
                pagekeys True

                side_yfill True
                vbox:
                    for item in store_instance: #Display the inventory of the tool shop along with the amount
                        $item_name = item.get_name()
                        $item_price = item.get_price()
                        hbox:
                            if item_price > current_money: #Items higher than your money
                                textbutton item_name sensitive False
                                add "images/icons/money.png " yalign 1.0
                                text str(item_price)
                            else: #Items you can buy
                                textbutton item_name action BuyItem(item)
                                add "images/icons/money.png " yalign 1.0
                                text str(item_price)

        null width (2 * gui.pref_spacing)
        imagemap:
            ground "gui/store/background.png "
            label _("sale")
            viewport:
                #yinitial yinitial
                scrollbars "vertical"
                mousewheel True
                draggable True
                pagekeys True

                side_yfill True

                vbox:
                    for item, amount in inventory.items(): #View inventory items along with selling price and quantity
                        if amount > 0:
                            $item_name = item.get_name()
                            $item_sell_price = item.get_sell_price()
                            $marketable_flag = item.get_marketable_flag()
                            hbox:
                                if marketable_flag: #Items that sell
                                    textbutton item_name action SellItem(item)
                                    add "images/icons/money.png " yalign 1.0
                                    text str(item_sell_price)
                                    text "×" + str(amount)
                                else: #Items that cannot be sold
                                    textbutton item_name sensitive False

    button: #back button
        xalign 0.9
        yalign 1.0
        xsize 145
        ysize 100
        text "Return" yalign 0.35
        background "gui/store/blank.png "
        
        action Return(True) #Return to caller label

###style omitted###

I'm very happy to be able to create a tool shop with this much code!

Conclusion and future

This time, we have implemented the item so that it can be used from the menu screen and purchased / sold at the tool shop. It's almost time for a battle, so next time I'll make a battle system.

Referenced codes and materials (titles omitted)

Code reference & borrow GUI: Dragonaqua on Lemmasoft(https://lemmasoft.renai.us/forums/viewtopic.php?f=51&t=57105) background: Nao Naruse Standing picture: Wataokiba (https://wataokiba.net/) icon: Material shop Rosa (http://sozairosa.blog.fc2.com/)

Recommended Posts

Make a 2D RPG with Ren'Py (3) -Items and Tool Shop
(Memorandum) Make a 3D scatter plot with matplodlib
Try to make a command standby tool with python
Let's make a simple game with Python 3 and iPhone
Make a CSV formatting tool with Python Pandas PyInstaller
Let's make a Mac app with Tkinter and py2app
Create a 3D model viewer with PyQt5 and PyQtGraph
Associate Python Enum with a function and make it Callable
Make a fortune with Python
Make a BLE thermometer and get the temperature with Pythonista3
Make a fire with kdeplot
[5th] I tried to make a certain authenticator-like tool with python
[2nd] I tried to make a certain authenticator-like tool with python
Make a simple OMR (mark sheet reader) with Python and OpenCV
I tried to make a periodical process with Selenium and Python
Make a Kanji display compass with Raspberry Pi and Sense Hat
Generate physically sturdy shapes with GAN and print with a 3D printer
Make a scraping app with Python + Django + AWS and change jobs
[4th] I tried to make a certain authenticator-like tool with python
[1st] I tried to make a certain authenticator-like tool with python
Let's make a GUI with python.
Solve ABC166 A ~ D with Python
Make a recommender system with python
Make a filter with a django template
Let's make a graph with python! !!
Let's make a supercomputer with xCAT
Make a model iterator with PySide
Make a nice graph with plotly
2. Make a decision tree from 0 with Python and understand it (2. Python program basics)
I came up with a way to make a 3D model from a photo.
Make a wireless LAN Ethernet converter and simple router with Raspberry Pi
Make a DNN-CRF with Chainer and recognize the chord progression of music
Make a decision tree from 0 with Python and understand it (4. Data structure)
Let's make a shiritori game with Python
Make a video player with PySimpleGUI + OpenCV
Make a rare gacha simulator with Flask
Make a Notebook Pipeline with Kedro + Papermill
Fractal to make and play with Python
Make a partially zoomed figure with matplotlib
Make a cascade classifier with google colaboratory
Let's make a simple language with PLY 1
Make a logic circuit with a perceptron (multilayer perceptron)
Solve AtCoder ABC168 with python (A ~ D)
Make a Yes No Popup with Kivy
Make a wash-drying timer with a Raspberry Pi
Make a GIF animation with folder monitoring
Let's make a web framework with Python! (1)
Let's make a tic-tac-toe AI with Pylearn 2
Make a desktop app with Python with Electron
Let's make a Twitter Bot with Python!
Implement a model with state and behavior
Let's make a web framework with Python! (2)
2D physics simulation with Box2d and wxPython
I tried to make a periodical process with CentOS7, Selenium, Python and Chrome
Make a thermometer with Raspberry Pi and make it visible on the browser Part 3
Let's make a nervous breakdown application with Vue.js and Django-Rest-Framework [Part 3] ~ Implementation of nervous breakdown ~
Let's make a nervous breakdown app with Vue.js and Django-Rest-Framework [Part 2] ~ Vue setup ~
Let's make a nervous breakdown app with Vue.js and Django-Rest-Framework [Part 1] ~ Django setup ~
Let's make a nervous breakdown application with Vue.js and Django-Rest-Framework [Part 6] ~ User Authentication 2 ~
WEB scraping with python and try to make a word cloud from reviews
Load a photo and make a handwritten sketch. With zoom function. Tried to make it.