Renpy Pirate Game Part 6 - Styles, Scoring, Inventory System
by IoFAdmin at
renpy | python | programming
Our Previous Trip On the High Seas...
In our last post, we learned all about Renpy variables, conditionals and screens. We'll build on those concepts in this post.
Programming Notice!
For brevity's sake, I'll only be showing code that has changed since last post instead of all of the code. (Your noticing the notice has been noticed.)
Sailing Ever Onward
We'll be exploring three concepts in this tutorial:
- Styles
- A Scoring System
- An Inventory System
So What Are Renpy Styles?
Styles in Renpy allow us to change the appearance and layout of components in our game. If you've ever learned CSS for websites, it's similar in concept. While Renpy Styles can become quite complicated, we're keeping it pretty simple here. (See the Renpy documentation for more information on styles.)
Getting the High Score
To help the player and add a little extra fun, we're going to add scoring to our game. (By the way, how and what does a pirate score? A date? Some treasure? A bottle of rum?) When our player completes certain tasks in the game, he/she will receive points. To complete the current level, our player will have to complete all of the required tasks (and score all of the points).
An Inventory System... AKA Our Pirate Treasure
If you remember from our last post, our pirate hero found a house key when he investigate the potted plant in front of his house. We set a variable, hasHouseKey, to keep track of whether he collected the key or not. Since we're going to have many more items in the future, setting a variable for each one will get to be impractical. An inventory system will solve our problem. We'll be visualizing our inventory with a backpack.
X Marks the Spot... For Our Code
Keeping with the format of the previous posts, I'll show you the code and then explain it. We'll start with script.rpy from post #5. Like I mentioned earlier, we'll only be looking at code that has changed so your code will be longer than what's shown here.
default inventory = [] label start: scene bg insidehouse show pirate happy show screen hudScreen $ points = 0 $ player_name = renpy.input("What is your name?", length=10) $ player_name = player_name.strip() if player_name == "": $ player_name = "Sheldon" p "No Miss Fluffybottom! Wait!" "Your cat, the adventurous (and naughty) Miss Fluffybottom runs out the front door of your house. That bad kitty's chasing a bird again! You should probably go after her right meow." menu: "Go after her.": jump house_outside "She'll be fine.": jump house_inside return label flower_pot: scene bg outsidehouse show pirate happy if 'house_key' in inventory: p "Mom's favorite plant could use some watering but I'll LEAVE it alone right now." else: $ inventory.append('house_key') $ points += 10 p "Hey what's that? Looks like a house key! Now I have the key to my front door." jump front_porch label house_outside: scene bg outsidehouse show screen frontPorchScreen show pirate happy p "There she is down on the beach chasing the seagulls again. Crazy cat! I should probably bring her back in the house before she gets lost or drowns." "The door slams shut and you're locked out of the house!" menu: "Use my key." if 'house_key' in inventory: hide screen frontPorchScreen jump house_inside "Knock on the door." if 'house_key' not in inventory: jump door_knock "Go after Ms Fluffybottom.": hide screen frontPorchScreen jump beach_squid label front_porch: scene bg outsidehouse show screen frontPorchScreen show pirate happy p "My front porch." menu: "Use my key." if 'house_key' in inventory: hide screen frontPorchScreen jump house_inside "Knock on the door." if 'house_key' not in inventory: hide screen frontPorchScreen jump door_knock "Go after Ms Fluffybottom.": hide screen frontPorchScreen jump beach_squid
Another One
Open up myscreens.rpy and replace everything with the code below.
screen frontPorchScreen(): imagebutton: xalign 0.75 yalign 1.0 idle "flower" action Jump("flower_pot") screen hudScreen(): frame style style["hud_frame"]: hbox: if player_name == "": label "Player" else: label player_name label " Points: " text "%d " % points imagebutton: idle "backpack" action Show("inventoryScreen") screen inventoryScreen(): modal True frame style style["inventory_frame"]: imagebutton style style["close_btn"]: idle "close" action Hide("inventoryScreen") vbox: text "Inventory" grid 7 4: for i in range(28): frame: maximum(155,155) if i < len(inventory): background Image(inventory[i]+".png") $ inv_item_name = inventory[i].replace('_', ' ') text [inv_item_name] style style["inv_item"] else: background Image("placeholder.png")
Arrrgh! This Be The Last One
Create a new file in the same directory as script.rpy, name it mystyles.rpy, and paste all of the following code into it.
style inv_item is text: size 16 bold True color Color((0, 255, 0, 255)) pos (5,125) style inventory_frame is frame: xpadding 10 ypadding 10 xalign 0.5 yalign 0.5 xsize 1152 ysize 660 background Color((193, 66, 66, 192)) style close_btn: xpos 1100 ypos -4 style hud_frame is frame: xpadding 10 ypadding 10 xalign 0.5 yalign 0.0
So What Was All of That?
We'll start with script.rpy mateys.
default inventory = []
We replaced define hasHouseKey = False with default inventory = [] which is required to work with our screen code below.
label start: scene bg insidehouse show pirate happy show screen hudScreen $ points = 0
Here we're showing a new screen hudScreen (which we'll create later) and we have a new variable points that we'll use in our scoring system.
label flower_pot: scene bg outsidehouse show pirate happy if 'house_key' in inventory: p "Mom's favorite plant could use some watering but I'll LEAVE it alone right now." else: $ inventory.append('house_key') $ points += 10 p "Hey what's that? Looks like a house key! Now I have the key to my front door." jump front_porch
In our flower_pot label, we're checking to see if house_key exists in our inventory variable. If it does, make a bad pun, else append it to our inventory list variable and give our player 10 points.
label house_outside: scene bg outsidehouse show screen frontPorchScreen show pirate happy p "There she is down on the beach chasing the seagulls again. Crazy cat! I should probably bring her back in the house before she gets lost or drowns." "The door slams shut and you're locked out of the house!" menu: "Use my key." if 'house_key' in inventory: hide screen frontPorchScreen jump house_inside "Knock on the door." if 'house_key' not in inventory: jump door_knock "Go after Ms Fluffybottom.": hide screen frontPorchScreen jump beach_squid
Same thing here... see if house_key is in our inventory variable.
label front_porch: scene bg outsidehouse show screen frontPorchScreen show pirate happy p "My front porch." menu: "Use my key." if 'house_key' in inventory: hide screen frontPorchScreen jump house_inside "Knock on the door." if 'house_key' not in inventory: hide screen frontPorchScreen jump door_knock "Go after Ms Fluffybottom.": hide screen frontPorchScreen jump beach_squid
Third time's a charm.
screen hudScreen(): frame style style["hud_frame"]: hbox: if player_name == "": label "Player" else: label player_name label " Points: " text "%d " % points imagebutton: idle "backpack" action Show("inventoryScreen")
In myscreens.rpy, we define a new screen hudScreen which will sit at the top of our game and display the player's name, current points, and an imagebutton of a backpack that will load our inventory screen. We're using a style here: frame style style["hud_frame"]. That tells Renpy that we have a style called hud_frame in our new mystyles.rpy file which we want to apply to our frame object. Inside our frame, we have a horizontal box (hbox) with a player label, a points label, a points text, and an imagebutton. The text "%d " % points code tells Renpy that we are wanting to display points as an integer.
screen inventoryScreen(): modal True frame style style["inventory_frame"]: imagebutton style style["close_btn"]: idle "close" action Hide("inventoryScreen") vbox: text "Inventory" grid 7 4: for i in range(28): frame: maximum(155,155) if i < len(inventory): background Image(inventory[i]+".png") $ inv_item_name = inventory[i].replace('_', ' ') text [inv_item_name] style style["inv_item"] else: background Image("placeholder.png")
We define our screen as modal which means nothing below it can be interacted with. We have a frame using the inventory_frame style that contains an imagebutton and a vbox. The imagebutton closes the current screen when clicked. Inside the vbox we have a grid which has 7 columns and 4 rows. We loop over each cell in the grid and add a frame with a maximum width and height of 155 pixels. If the current index of i is less than the number of elements in the inventory variable, add a background Image and the name of the item. Else, display a placeholder image.
style inv_item is text: size 16 bold True color Color((0, 255, 0, 255)) pos (5,125)
Here we define our first style. We're creating styles in the mystyles.rpy file to keep the other files less cluttered. Renpy styles are pretty self-explanatory which makes them easy to understand. The inv_item part gives us a name that we can use the access the style in other files. The is text section tells Renpy that our style is modifying the default text style included with Renpy. All of the other parts do just what you'd expect: set the text size to 16 pixels, bold the text, set the text color to green, and display the text at 5 pixels to the left and 125 pixels down from the top left corner of the Renpy component that the style is applied to.
style inventory_frame is frame: xpadding 10 ypadding 10 xalign 0.5 yalign 0.5 xsize 1152 ysize 660 background Color((193, 66, 66, 192))
Define a style named inventory_frame that modifies the default Renpy frame styles. Give it 10 pixels padding on the all sides (both x and y), center it horizontally and vertically (xalign 0.5 -> horizontal, yalign 0.5 -> vertical), set the size as 1152 x 660 pixels, and set the background color to reddish with a partial opacity (a little bit transparent).
style close_btn: xpos 1100 ypos -4
Another style... This time it doesn't modify any default style. Set the position as 1110 pixels to the left and 4 pixels above the top left corner of the container that the component is inside of.
style hud_frame is frame: xpadding 10 ypadding 10 xalign 0.5 yalign 0.0
Last style... Modify the default frame style, set padding to 10 pixels in all directions, center horizontally, display at the top of the container.
Screenshots
Wrapping Up
If you followed along and didn't walk the plank, your Renpy game should look very similar to the images above. As always, if you have feedback please let me know your opinions in the comments below.
Git Repo Link
If you'd like to download the code and images in this post, get them here.
Support Me
If you find these tutorials useful (or enjoy my bad puns), please consider buying me a coffee. Thanks!