Arcade slot framework

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Post Reply
Message
Author
User avatar
gas
Miko-Class Veteran
Posts: 842
Joined: Mon Jan 26, 2009 7:21 pm
Contact:

Arcade slot framework

#1 Post by gas »

ARCADE SLOT FRAMEWORK
=====================

With this recipe you can change the standard Ren'py save system into something more similar to console games.
Well, yeah, like Castlevania, Zelda or Tokimeki Memorial.
You have three slots to choose at the start of the game.
If you choose a void slot, you begin a game from scratch. If you chose an occupied slot, you continue the game from that point.

All progresses are saved in the chosen slot when YOU, the game designer, want for.

### WHY USE IT AND WHY NOT ###
This code is perfect for dating sims, RPG and all games that require control over game progress. The standard ren'py save system can destroy the game engagement.
This system allow the player to focus more on each move, without abusing of a save/reload mechanic.

In visual novels the save system work mostly as bookmarks, to avoid reading again long chunks of text. Saving as much as you want doesn't harm the gameplay. In fact, where is the gameplay??
So, if your game is mostly narrative, it's far better that you don't use it.


### HOW TO USE IT ###

1) Copy the long script that follow below, and paste it in place of a default script.
That's mean this script will overwrite that Eileen babbling about releasing the game to the world.
It's far much better if you begin by running the launcher, create a new project, then open 'script.rpy' file and overwrite the content with the arcade slot one.

2 )To have the game save, use this exact line:

Code: Select all

$ renpy.save(slot,extra_info=save_name)
'save_name' is by default the word 'Introduction'.
That word appear in the slots. To change it, for example to state a chapter number or a route, simply use before:

Code: Select all

$ save_name="whatever you want"
PLEASE NOTICE: it's up to you to decide when the game save. All quick, auto and standard save features are stripped off.
The player will be unaware of the save, that will happen in the background.
This is an example of use...

Code: Select all

label turn:
    $ day+=1
    $ save_name="Chapter "+str(day)
    "It's day [day]"
label adventure:
   "Play there your adventure!"
label night:
   "The day come to an end, and the game autosave in the proper slot."
   $ renpy.save(slot,extra_info=save_name)
   jump turn
3) Don't touch the START label, it's used to immediatley jump to the slot screen.
Instead, your game begin with the next label, 'realstart', and you can proceed as usual.

### THE CODE ###

Code: Select all

# ARCADE SLOT FRAMEWORK
#######################
# Made by GAS, found on LemmaSoft Forum
# New Script.rpy

### Preliminary operations
init python:
    config.has_autosave=False
default slot=0

### Your script begin there
label start:
    $ save_name="Introduction"
    $ _game_menu_screen=None
    call screen slotscreen
    $ slotn=_return
    $ slot="1-"+str(slotn)
    $ renpy.save(slot, extra_info=save_name)
    $ _game_menu_screen="preferences"

### ... but the narration begin there below!
label realstart:
    "The actual game begin there."
    "Use '$ renpy.save(slot, extra_info=save_name)' to save the game in the proper slot."
    return
    
#############################################################
### The screen to chose the slot to play in
screen slotscreen():
    tag menu
    add gui.game_menu_background
    text _("Choose Game") xalign 0.5 size 30
    hbox:
        xalign 0.5
        yalign 0.6
        spacing 8
        for i in range(1,4):
            if FileLoadable(i):
                # define the content
                button:
                    xsize 300
                    ysize 400
                    background Frame("gui/frame.png")
                    vbox:
                        xsize 300
                        spacing 3
                        yalign 0.5
                        text "[i]" xalign 0.5
                        add Solid((100,100,100,255),xsize=200, ysize=200, xalign=0.5)
                        text FileSaveName(i):
                            style "slot_name_text"
                        text FileTime(i, format=_("{#file_time}%A, %B %d %Y, %H:%M"), empty=_("empty slot")):
                            style "slot_time_text"
                    action FileLoad(i)
                    key "save_delete" action FileDelete(i)
            else:
                # define the void slot
                button:
                    xsize 300
                    ysize 400
                    background Frame("gui/frame.png")
                    vbox:
                        xsize 300
                        spacing 3
                        yalign 0.5
                        text "[i]" xalign 0.5
                        add Solid((50,50,50,255),xsize=200, ysize=200, xalign=0.5)
                        text "NEW GAME":
                            style "slot_name_text"
                        text "-- -- --":
                            style "slot_time_text"
                    action Return(i)

### modified screens
screen quick_menu():
    zorder 100
    if quick_menu:
        hbox:
            style_prefix "quick"
            xalign 0.5
            yalign 1.0
            textbutton _("Back") action Rollback()
            textbutton _("History") action ShowMenu('history')
            textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
            textbutton _("Auto") action Preference("auto-forward", "toggle")
            textbutton _("Prefs") action ShowMenu('preferences')

screen navigation():
    vbox:
        style_prefix "navigation"
        xpos gui.navigation_xpos
        yalign 0.5
        spacing gui.navigation_spacing
        if main_menu:
            textbutton _("Start") action Start()
        else:
            textbutton _("History") action ShowMenu("history")
        textbutton _("Preferences") action ShowMenu("preferences")
        if _in_replay:
            textbutton _("End Replay") action EndReplay(confirm=True)
        elif not main_menu:
            textbutton _("Main Menu") action MainMenu()
        textbutton _("About") action ShowMenu("about")
        if renpy.variant("pc"):
            ## Help isn't necessary or relevant to mobile devices.
            textbutton _("Help") action ShowMenu("help")
            ## The quit button is banned on iOS and unnecessary on Android.
            textbutton _("Quit") action Quit(confirm=not main_menu)
### HOW TO CUSTOMIZE IT ###
There's a lot you can do there, as the system is very barebone, while functional.
1 - BASIC SLOT STYLES
The slots are styled two ways:
-They are buttons with a Frame() inside. You can just change the frame image.
-You can change text appearance at will, changing the GUI.RPY file, modifying voices used for 'slot'.

2 - ADD OTHER DATA TO SLOTS
To show other data on the slot you need to add a JSON function.
Think of a JSON as a post-it Ren'py can read before the slot is actually loaded.

Let's say for example you want to show the character name ('charaname'), the game day ('day') and the money collected ('money'). Add this at the end or start of your script. It create a function I've named 'myjson', that create a dictionary called 'jsondata'. What follow on square brackets are the 'key' name we'll use later, they are made out of thin air.

Code: Select all

default charaname="Gas"
default day=1
default money=21000
init python:
    def myjson(jsondata):
        jsondata["thename"]=charaname
        jsondata["theday"]=day
        jsondata["themoney"]=money
    config.save_json_callbacks.append(myjson)
Then you need to change the slots to retrieve and show those data. If a slot is void, let's use placeholders.

Code: Select all

#############################################################
### The screen to chose the slot to play in
screen slotscreen():
    tag menu
    add gui.game_menu_background
    text _("Choose Game") xalign 0.5 size 30
    hbox:
        xalign 0.5
        yalign 0.6
        spacing 8
        for i in range(1,4):
            if FileLoadable(i):
                # define the content
                $ yourname=FileJson(i,"thename")
                $ yourday=FileJson(i,"theday")
                $ yourmoney=FileJson(i,"themoney")
                button:
                    xsize 300
                    ysize 400
                    background Frame("gui/frame.png")
                    vbox:
                        xsize 300
                        spacing 3
                        yalign 0.5
                        text "[i]" xalign 0.5
                        add Solid((100,100,100,255),xsize=200, ysize=200, xalign=0.5)
                        text FileSaveName(i):
                            style "slot_name_text"
                        text FileTime(i, format=_("{#file_time}%A, %B %d %Y, %H:%M"), empty=_("empty slot")):
                            style "slot_time_text"
                        text "NAME: [yourname]"
                        text "DAY: [yourday]"
                        text "Money: [yourmoney]"
                    action FileLoad(i)
                    key "save_delete" action FileDelete(i)
            else:
                # define the void slot
                button:
                    xsize 300
                    ysize 400
                    background Frame("gui/frame.png")
                    vbox:
                        xsize 300
                        spacing 3
                        yalign 0.5
                        text "[i]" xalign 0.5
                        add Solid((50,50,50,255),xsize=200, ysize=200, xalign=0.5)
                        text "START NEW GAME":
                            style "slot_name_text"
                        text "-- -- --":
                            style "slot_time_text"
                        text "NAME: ---"
                        text "DAY: --"
                        text "Money: ----"
                    action Return(i)
3 - WHY NOT SCREENSHOTS? ... and how to show icons instead
As the game save at given checkpoints, probably the screenshots will be terrible to use.
It's far better if you'll use some icon.
You have 2 options there:
A: Easy Option.
In the script, you'll see something like:

Code: Select all

add Solid((50,50,50,255),xsize=200, ysize=200, xalign=0.5)
Once for a free slot, once for the occupied slot.
You can have a 200*200 pixel image for an occupied slot and another one instead for a void slot.

Change the first 'add' like this:

Code: Select all

add "fullslot.png" xalign 0.5
And the second like this:

Code: Select all

add "voidslot.png" xalign 0.5
Of course fullslot and voidslot are the images you want to use, and of the same size.

B: Icon by story or goals
You can use a JSON function to determine a slot icon to show based on game values.
Let's pretend you have a value called 'lover', that register the character you're dating. There are 3 of them, with a value from 0 to 2 to identify them. If you're dating no one, you have your face instead.
Add the JSON function or modify the one you've coded already.

Code: Select all

init python:
    def myjson(jsondata):
        jsondata["thelover"]=lover
    config.save_json_callbacks.append(myjson)
Add a list of the icons.

Code: Select all

default sloticons=["eileenslot.png","charlizeicon.png", "lindsayicon.png","yourface.png"]
Later, in the screen you can retrieve this value to show the proper icon.

Code: Select all

            if FileLoadable(i):
                # define the content
                $ icon_numb=FileJson(i,"thelover")
                $ img=sloticons[icon_numb]
                button:
                    xsize 300
                    ysize 400
                    background Frame("gui/frame.png")
                    vbox:
                        xsize 300
                        spacing 3
                        yalign 0.5
                        text "[i]" xalign 0.5
                        add "img"
                        text FileSaveName(i):
                            style "slot_name_text"
If you want to debate on a reply I gave to your posts, please QUOTE ME or i'll not be notified about. << now red so probably you'll see it.

10 ? "RENPY"
20 GOTO 10

RUN

User avatar
PyTom
Ren'Py Creator
Posts: 16093
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: Arcade slot framework

#2 Post by PyTom »

Note that this is kind of terrible to inflict on your players. They want to save right away, perhaps because their baby climbed into the oven. Why should you force them to have to pick between saving little Bobby and their game progress?

In general - when the player wants to save, you should let them. It seems incredibly rude for a creator to prioritize their wishes over that of the player. Saving multiple times is a technique people use to explore alternate endings, to retain bookmarks to important scenes to be able to discuss them, or any of a dozen other readings. It's also serves to add accessibility for people who can't always choose the right choice. (In the same way

What's more, everybody knows by now that Ren'Py is capable of this, meaning people will know you took a standard feature from them - which is probably going to lead to more than a few ragequits.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
Software > Drama • https://www.patreon.com/renpytom

User avatar
gas
Miko-Class Veteran
Posts: 842
Joined: Mon Jan 26, 2009 7:21 pm
Contact:

Re: Arcade slot framework

#3 Post by gas »

PyTom wrote: Thu May 10, 2018 6:57 pm Note that this is kind of terrible to inflict on your players. They want to save right away, perhaps because their baby climbed into the oven. Why should you force them to have to pick between saving little Bobby and their game progress?

In general - when the player wants to save, you should let them. It seems incredibly rude for a creator to prioritize their wishes over that of the player. Saving multiple times is a technique people use to explore alternate endings, to retain bookmarks to important scenes to be able to discuss them, or any of a dozen other readings. It's also serves to add accessibility for people who can't always choose the right choice. (In the same way

What's more, everybody knows by now that Ren'Py is capable of this, meaning people will know you took a standard feature from them - which is probably going to lead to more than a few ragequits.
PyTom, did you read the disclaimer at the post begin?
As for the baby in the owen, do you really SAVE THE GAME instead of run saving the kid?

Anyway, I was about to introduce a Coffee Break save mode that probably you'll like.
If you want to debate on a reply I gave to your posts, please QUOTE ME or i'll not be notified about. << now red so probably you'll see it.

10 ? "RENPY"
20 GOTO 10

RUN

User avatar
wyverngem
Miko-Class Veteran
Posts: 615
Joined: Mon Oct 03, 2011 7:27 pm
Completed: Simple as Snow, Lady Luck's Due,
Projects: Aether Skies, Of the Waterfall
Tumblr: casting-dreams
itch: castingdreams
Location: USA
Contact:

Re: Arcade slot framework

#4 Post by wyverngem »

:) Helped me to wrap my head around JSONs so I'm really glad you posted. I think it's a good code! It's a start to having personalized saves for multi-users on the same console. It definitely gives a groundwork for expanding the code. :D

Post Reply

Who is online

Users browsing this forum: No registered users