Sunday, April 17, 2016

Screens: Backgrounds and Buttons

Hello again everyone! I'm glad you decided to join me on this week's adventure. ^^

When I first opened Ren'Py, setting up my first game certainly looked easy: name it, choose a color, a theme, and POOF! I was all set to start adding content. For a first-time programmer, that window felt like it had been touched by the hand of Midas.

Then I looked a little closer.

The templates are nice, yes, but none of them quite jived with the theme and tone I was looking for. And certainly none of them are going to set my work apart. Some features come standard with a brand new project that I had to disable, or even eliminate completely.

Long story short, my menus needed a complete makeover. If you're here, yours probably does too. Let me show you how I did it. Hopefully you can take something away from my efforts, and make your screens into the special snowflakes you always knew they could be. ^^

This is the default Preferences screen. (I chose "A White Tulip" as  the theme, and "Dramatic Flesh" as the color scheme, if you're playing the home game. )

As you can see, there's nothing inherently wrong with the setup. It's just so... impersonal. Bland, almost. With a little patience (and a LOT of trial and error), I went from that...



...to this! That's quite a change, isn't it? It's not the final design, but now that I have all of the elements in place, I can change it whenever I need to.

Note: I DO NOT own that background. It is art that I found, currently being used as a stand-in (although I do like it enough that I might ask for permission to use it in my final project).







If you are using Ren'Py, and you don't know about the Lemma Soft forums, you are doing yourself a disservice. The community there is fantastic, supportive, and very, very helpful.

Case in point: this post by Aleema was invaluable to me as someone who had no idea how to begin changing existing code. The tutorial is a little outdated, but by reading through the rest of the responses, I gleaned a great deal of knowledge.


Step One: The Size:
Obviously, the first step is to figure out the height and width you want your game window to be. You can change this at any time, but remember that you'll probably need to modify your images to fit. :)

The code you're looking for is under options.rpy, on/about lines 18-21.
    ## These control the width and height of the screen.
    config.screen_width = 800
    config.screen_height = 600
 

I think that 800x600 is the default, and it's what I've been working with as I learn. Once I get confident enough to create content that I want to publish, I'll likely increase the size to support HD images. ^^

Step Two: The Image:
O
kay then. Now that that's taken care of, it's time to choose an image. Make sure that it fits the dimensions you declared above, or you might find the interesting bits at the sides cut off. No one wants that. ^^


This code (still in options.rpy) is on/about lines 62-70.
        ## The background of the main menu. This can be a color
        ## beginning with '#', or an image filename. The latter
        ## should take up the full height and width of the screen.
        mm_root = "images/title_screen.png",

        ## The background of the game menu. This can be a color
        ## beginning with '#', or an image filename. The latter
        ## should take up the full height and width of the screen.
        gm_root = "menu/background1.png",

As the comments describe, your background can be a solid color (a six-digit code beginning with #) or an image. Make sure the image you're using is in your "game" folder. If you've placed your images in a sub-folder like I have, make sure that you include that folder in your file name (the folder is the word before the /) .

Above, you'll see that there are two "roots": mm, and gm. mm is the Main Menu (also used as the title screen), while gm is the Game Menu (used for things like the save/load screen, and the preferences screen). Those can be the same image, or not! I chose to use different images, because I'm awesome that way. ;)
Personal note: I would suggest ALWAYS saving your image files as .png. The other formats can compress your picture, leaving it looking grainy; doubly so if you edit it often. .png doesn't, so you can edit as much as you like without any real loss of quality.

Step Three-A: To Image Map...:
Firstly, if you don't know what an image map or "hotspot" is, read this post. It is more succinct than I could hope to be, and it's Ren'Py-specific. Perfect, right? ^^

Because I was a total coding newbie, I originally created image maps for my screens. What that means is that I made some button images, slapped them across the bottom of my background picture, and defined some hotspots for them to work.
(If you choose to go this route, check out this hotspot tool. It generates the code for you, so you can just copy/paste the results. I love using it for my image maps.)

Technically, that's all you need to have a working menu. But it's easier on your players when you have a rollover effect (something that happens to the hotspot when the mouse is on it)

In my case, I created another set of button images. "Idle" is how I want the button to look normally. Nothing is happening to it; it's just there, being its awesome button self. "Hovered" is how it will change when the mouse is over it. "Disabled" is... well, pretty self-explanatory, I would think. *grin*  While I only used the Load button for this example, I did have to create images for each of these three states, for all five of my buttons.


From there, the process was fairly easy. One background picture had a set of idle buttons, while the other had a set of hovered buttons. Note here that I didn't bother putting Options on the second image at all. That's just a personal design choice. Because this is the menu for the Options screen, I made the Options button disabled; there's no real point in clicking it if you're already there, right? Because nothing is happening to it, I didn't create a hotspot for it, and decided not to put that little bit extra onto my "hover background." But again, do whatever works for you.

Using that hotspot tool, I ended up with a code similar to this:
imagemap:
    background 'imagemapidle.png'
    idle 'imagemapidle.png'
    hover 'imagemaphover.png'

    alpha False

    hotspot(32,550,119,33) action Start()
    hotspot(179,550,117,37) action ShowMenu("load")
    hotspot(339,551,119,38) action Return()
    hotspot(663,550,121,38) action Quit()


Always begin your block exactly as shown. "Background" is well, your background image. The picture that you want to show up behind all those nifty buttons we're working on. "Idle" is how you want your buttons to look on that background, so it's usually the same image. "Hover" is what you want your buttons to look like when the mouse is on them. Because you're defining your hotspots to only cover a certain area, your second image only needs to have the button art.

The numbers following the hotspots are the corners of the area you want to be clickable. The action is what you want to happen when said area is clicked. Make sure the actions are properly capitalized. This is just as important as punctuation (don't you dare forget those parentheses either), and if you miss even a single capital, you're going to have a day of frustration.
NOTE: To get to the Options screen, the command is action ShowMenu("preferences"). There is also an action MainMenu() command, but that doesn't work outside of the game itself, so action Return() took its place in the Options and Save/Load menus.

After some time, I decided that the buttons on my image map looked a little... lackluster. They just didn't... pop in the same way that my other buttons did. I decided to move on to learning styling (making the look of your buttons universal) because I was changing my mind about which stand-in art I was going to use on a near-daily basis... and if you make even a minor change in an image map, you need to redo the WHOLE thing.

Step Three-B: ...or Not To Image Map:
Styling actually turned out to be a lot of fun for me. Of course, I'm enjoying learning to code, so anything that ultimately creates more lines is usually a good experience. ^^

So, once again, I had to create the images I wanted to use, and place them into a style block. I put it at the bottom of my options.rpy in the "more customization" section, and it looks a little something like this:

style button:
    background Frame("buttons/menu_idle.png",10,10)
    hover_background Frame("buttons/menu_hover.png",10,10)
    selected_background Frame("buttons/menu_selected.png",10,10)
    insensitive_background Frame("buttons/menu_disabled.png",10,10)
    yminimum 40

Don't forget to close the quotes on your image file. Don't forget the commas. Don't forget to close the parentheses. Python is like a picky second-grader, and if you don't do things exactly its way, it throws a tantrum.

Definitions:
hover/selected/insensitive/background: These are defined by Ren'Py. Scripting a picture into that definition will make sure that your buttons will come to this set of images to know what, say, their hover effect will be.
Frame: This means that the image you're defining will stretch to fill the available space. Some buttons are inherently bigger than others; using Frame, you don't have to manually create all of those different images. Thankfully, right? ^^
yminimum: This tells the button that it has to be at least 40 pixels high. It's not essential to the code, but I feel better having it. Play around with a number that makes your screens look nice. ^^
10,10 : Those two numbers at the end are how many pixels you're allowing for the corners of your image. Again, play with those until you've gotten the look and feel that you want.

NOTE: "button" is a word taken by Ren'Py; by using it here, I'm changing all buttons, everywhere, to look like this. It can be overridden (more on that in another post), but for now, it's best to assume that by using a pre-defined label, all of your buttons will have the same style.

Ah, but now the tricky part. How do you enact this new code?
 
screen navigation():

    # The background of the game menu
    window:
        style "gm_root"
   
    # The various buttons.
    hbox:
        style_group "gm_nav"
        xalign .5
        yalign .98

        spacing 10
       
        textbutton _("Return") action Return()
        textbutton _("Save/Load") action ShowMenu("load")
        textbutton _("Main Menu") action MainMenu()
        textbutton _("Options") action ShowMenu("preferences")
        textbutton _("Quit") action Quit()


init -2:

    # Make all game menu navigation buttons the same size.
    style gm_nav_button:
        size_group "gm_nav"

I can't give exact line numbers here, because I've changed so much in my options file. My navigation begins at 213, which I think is a decent ballpark figure.

Definitions:
style_group "gm_nav": gm_nav is a subset, or child, of the "button" attribute I changed earlier. If I'd wanted to change the buttons for only my game menus, I would have used "style gm_nav_button" instead.
x/yalign: x is the X axis, which runs horizontally. y is the Y axis, and runs vertically. When adding "align" to x or y, I'm telling my buttons where on the screen I want them to be. Using a whole number will result in Ren'Py moving the object that many pixels from either the left (x) or the top (y). Using a decimal, as I did, moves it that percentage of the whole screen.
spacing: How many pixels apart you want your buttons.

Step Four: ????:
Hooray! If you were following along at home, you should now have a working background, and buttons that look cool and do things. 

Step Five: Profit:
Wh- what do you mean the text isn't styled yet?

...next time, Gadget. Next time.

So, uh, this blog ended up a little more technical than I'd wanted it to be. But I thought it was important to get down how I got to where I am now. So the next couple entries might be like this. After that though, it'll be a little more free-form. Hopefully you will stick around to see it. ^^

No comments:

Post a Comment