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
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.
First, create an item-Implement the part to be used from the menu screen.
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.
This is Ren'Py's original. The result of this implementation is shown in the figure first. 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.
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.
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]
The result of implementation is also posted here. 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!
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.
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