Why does my textbutton work in a weird way?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
ippherita
Regular
Posts: 27
Joined: Fri May 09, 2014 1:46 pm
Contact:

Why does my textbutton work in a weird way?

#1 Post by ippherita »

Hi, I am kinda new to coding and renpy.

I try to build a buying system. I have kinda manage to build a simple one and have a basic shop set up.

The problem is when i try to use textbutton as the "buy" function.

I can't click it.

but clicking on the pictures of the items available, i can see my gold coins reduced. This is not what i intended. i don't want to purchase anything when i click on stuff to check the price.

The gold coin reduced in a weird way.
When i click on the a item pic, nothing happened
when i click on the another item pic, the gold amount reduced as the cost of the previous item x2
basically each image become a "buy" button x2 of the previously clicked image
(I never wanted to do that!!!)

What did i do wrong?

Code: Select all

style slot: 
#these two styles are styles for the inventory/seller window
    background Frame("square")
    xalign 0.5
    minimum(150,300)
    maximum(150,300)

style horizontal_slot:
    xalign 0.5
    yalign 0.6
    background Frame("horizontal")
    minimum(300,150)
    maximum(300,150)



screen buying_dress:

	#this is the vpgrid to show the images items to be purchased
    vpgrid:  
        cols 3
        draggable True
        mousewheel True
        xmaximum 500
        xminimum 500
        ymaximum 450
        yminimum 450
        yalign 0.2
        xalign 0.5
        spacing 5
        for Item in ClothingShopItenery:
            imagebutton:
                style "slot"
                idle Item.img
                action SetVariable("selected_item", Item)


    vbox:    #this box to is show the info of the selected item 
        xalign 0.5
        yalign 0.89
        frame:
            style "horizontal_slot"
            vbox:
                if selected_item != None:
                    label "Cost: [selected_item.cost]"
                    label "Name: [selected_item.name]"





    textbutton "BUY":
        xalign 0.7
        yalign 0.95
        sensitive
        selected
        if selected_item != None:
            action inventory.buy(selected_item)



    textbutton "Return":
        action Return()
        xalign 0.5
        yalign 0.95

init python:
    class Inventory:
        def __init__(self):
            self.items = []

        def buy(self, item):
            global gold
            global justbought
            if gold >= item.cost:
                gold -= item.cost
                self.items.append(item)
                justbought = item.name
                #global selected_item
                #selected_item = None


    class Item:
        def __init__(self, name, cost, img):
            self.name = name
            self.cost = cost
            self.img = img




default ClothingShopItenery = []
default shirt1= Item("Shirt 1", 5, "shirt a buying.png")
default shirt2= Item("Shirt 2", 10, "shirt a buying.png")
default shirt3= Item("Shirt 3", 15, "shirt b buying.png")
default shirt4= Item("Shirt 4", 20, "shirt b buying.png")

screen Goldcoins:
     text "Goldcoins [gold]" xpos 0.065 ypos 0.125

label start:
    show screen Goldcoins
    scene bg white
    python:
        inventory = Inventory()
        ClothingShopItenery.append(shirt1)
        ClothingShopItenery.append(shirt2)
        ClothingShopItenery.append(shirt3)
        ClothingShopItenery.append(shirt4)
        selected_item = None
        gold = 300


    "go to clothing shop"
    
    call screen buying_dress

User avatar
Alex
Lemma-Class Veteran
Posts: 3094
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Why does my textbutton work in a weird way?

#2 Post by Alex »

You need a Function action, so try

Code: Select all

    textbutton "BUY":
        xalign 0.7
        yalign 0.95
        sensitive
        selected
        if selected_item != None:
            action Function(inventory.buy(selected_item))
https://www.renpy.org/doc/html/screen_a ... l#Function

User avatar
xavimat
Eileen-Class Veteran
Posts: 1461
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Discord: xavimat
Contact:

Re: Why does my textbutton work in a weird way?

#3 Post by xavimat »

If Alex solution does not work, try passing the argument in the "Function" action:

Code: Select all

    textbutton "BUY":
        xalign 0.7
        yalign 0.95
        sensitive
        selected
        if selected_item != None:
            action Function(inventory.buy, item=selected_item)
Explanation:
Your weird behavior probably is caused by "screen prediction". Screens are "predicted" by renpy an undetermined number of times, to avoid waiting while the screen is being prepared (some screens can be very complex and memory-heavy). So your action + function name (without the "Function" action) will execute the function on prediction.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

ippherita
Regular
Posts: 27
Joined: Fri May 09, 2014 1:46 pm
Contact:

Re: Why does my textbutton work in a weird way?

#4 Post by ippherita »

Alex wrote: Mon Apr 29, 2019 6:26 pm You need a Function action, so try

Code: Select all

    textbutton "BUY":
        xalign 0.7
        yalign 0.95
        sensitive
        selected
        if selected_item != None:
            action Function(inventory.buy(selected_item))
https://www.renpy.org/doc/html/screen_a ... l#Function
Huh, interesting, Now I can click it. but the problem (clicking other image item = buy x2) still persist...

ippherita
Regular
Posts: 27
Joined: Fri May 09, 2014 1:46 pm
Contact:

Re: Why does my textbutton work in a weird way?

#5 Post by ippherita »

xavimat wrote: Tue Apr 30, 2019 9:48 am If Alex solution does not work, try passing the argument in the "Function" action:

Code: Select all

    textbutton "BUY":
        xalign 0.7
        yalign 0.95
        sensitive
        selected
        if selected_item != None:
            action Function(inventory.buy, item=selected_item)
Explanation:
Your weird behavior probably is caused by "screen prediction". Screens are "predicted" by renpy an undetermined number of times, to avoid waiting while the screen is being prepared (some screens can be very complex and memory-heavy). So your action + function name (without the "Function" action) will execute the function on prediction.
OOOOH THANK YOU SO MUCH! It works!!!

Thank you thank you thank you!

ippherita
Regular
Posts: 27
Joined: Fri May 09, 2014 1:46 pm
Contact:

Re: Why does my textbutton work in a weird way?

#6 Post by ippherita »

ippherita wrote: Tue Apr 30, 2019 10:12 am
xavimat wrote: Tue Apr 30, 2019 9:48 am If Alex solution does not work, try passing the argument in the "Function" action:

Code: Select all

    textbutton "BUY":
        xalign 0.7
        yalign 0.95
        sensitive
        selected
        if selected_item != None:
            action Function(inventory.buy, item=selected_item)
Explanation:
Your weird behavior probably is caused by "screen prediction". Screens are "predicted" by renpy an undetermined number of times, to avoid waiting while the screen is being prepared (some screens can be very complex and memory-heavy). So your action + function name (without the "Function" action) will execute the function on prediction.
OOOOH THANK YOU SO MUCH! It works!!!

Thank you thank you thank you!

Hi xavimat, thank you so much for solving the problem~!

why does separating the "inventory.buy" and the "selected_item" (and turn it to item=selected_item) works? they stop the screen prediction?

I thought it would be the same as "action Function(inventory.buy(selected_item))"?

User avatar
xavimat
Eileen-Class Veteran
Posts: 1461
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Discord: xavimat
Contact:

Re: Why does my textbutton work in a weird way?

#7 Post by xavimat »

ippherita wrote: Tue Apr 30, 2019 10:17 amwhy does separating the "inventory.buy" and the "selected_item" (and turn it to item=selected_item) works? they stop the screen prediction?
I don't know how exactly it works, I was simply reading the docs: https://www.renpy.org/doc/html/screen_a ... l#Function
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

rames44
Veteran
Posts: 233
Joined: Sun May 29, 2016 4:38 pm
Contact:

Re: Why does my textbutton work in a weird way?

#8 Post by rames44 »

ippherita wrote: Tue Apr 30, 2019 10:17 am why does separating the "inventory.buy" and the "selected_item" (and turn it to item=selected_item) works? they stop the screen prediction?

I thought it would be the same as "action Function(inventory.buy(selected_item))"?
Again, the inventory.buy(selected_item)) call will be executed during screen prediction, since what this says is “call this method and then use the return value as the argument to the Function screen action. As if you were dynamically figuring out the function to be called. When you break them up, buy() doesn’t get called at screen prediction time - you’re telling the Function screen action, “when you’re activated, call buy with this argument”

ippherita
Regular
Posts: 27
Joined: Fri May 09, 2014 1:46 pm
Contact:

Re: Why does my textbutton work in a weird way?

#9 Post by ippherita »

xavimat wrote: Tue Apr 30, 2019 6:03 pm
ippherita wrote: Tue Apr 30, 2019 10:17 amwhy does separating the "inventory.buy" and the "selected_item" (and turn it to item=selected_item) works? they stop the screen prediction?
I don't know how exactly it works, I was simply reading the docs: https://www.renpy.org/doc/html/screen_a ... l#Function
Thank you so much~!

I need to read the docs more often.

Sigh. the docs are really not very newbie friendly

ippherita
Regular
Posts: 27
Joined: Fri May 09, 2014 1:46 pm
Contact:

Re: Why does my textbutton work in a weird way?

#10 Post by ippherita »

rames44 wrote: Wed May 01, 2019 11:57 am
ippherita wrote: Tue Apr 30, 2019 10:17 am why does separating the "inventory.buy" and the "selected_item" (and turn it to item=selected_item) works? they stop the screen prediction?

I thought it would be the same as "action Function(inventory.buy(selected_item))"?
Again, the inventory.buy(selected_item)) call will be executed during screen prediction, since what this says is “call this method and then use the return value as the argument to the Function screen action. As if you were dynamically figuring out the function to be called. When you break them up, buy() doesn’t get called at screen prediction time - you’re telling the Function screen action, “when you’re activated, call buy with this argument”
Thank you for the explanation. I need to read through a few times. I think i kinda understand now. (I am confused the the argument thing)

so the buy() action was not activated in screen prediction, but it is activated for the... OK I just lost myself

I think i need to go through some tutorials/lessons for this.

ippherita
Regular
Posts: 27
Joined: Fri May 09, 2014 1:46 pm
Contact:

Re: Why does my textbutton work in a weird way?

#11 Post by ippherita »

xavimat wrote: Tue Apr 30, 2019 6:03 pm
ippherita wrote: Tue Apr 30, 2019 10:17 amwhy does separating the "inventory.buy" and the "selected_item" (and turn it to item=selected_item) works? they stop the screen prediction?
I don't know how exactly it works, I was simply reading the docs: https://www.renpy.org/doc/html/screen_a ... l#Function
Hi xavimat, again, thank you for your help.

just asking a bit deeper. this question is not urgent, just a nice function to have.

After getting your help on the code. I felt ambitious and put the code onto an imagebutton. I wanted its function same as the "BUY" textbutton.

i also added a line of new code in the "buy()"

Code: Select all

imagebutton:
        idle "buy button.png"
        if selected_item != None:
            action Function(inventory.buy, item=selected_item)
            

init python:
    class Inventory:
        def __init__(self):
            self.items = []

        def buy(self, item):
            global gold
            global justbought
            if gold >= item.cost:
                gold -= item.cost
                self.items.append(item)
                justbought = item.name
                ClothingShopItenery.remove(selected_item)  # <---- new code!!
                
                
so with this new code "ClothingShopItenery.remove(selected_item)" it works perfectly fine with the texbutton you fixed. image item dissappeared when i buy them.

what is weird is, when i delete the textbutton and use the iimagebutton like the code above, the second image i click become a "buy()", an the first clicked image disappeared as supposed.

when i try to click another image, or the "buy" textbutton, this error code come out:

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 31, in script
    call screen buying_dress
  File "renpy/common/000statements.rpy", line 519, in execute_call_screen
    store._return = renpy.call_screen(name, *args, **kwargs)
  File "renpy/common/00action_other.rpy", line 517, in __call__
    rv = self.callable(*self.args, **self.kwargs)
  File "game/script.rpy", line 251, in buy
    ClothingShopItenery.remove(selected_item)
ValueError: list.remove(x): x not in list

i assume it is the predict screen thing doing, as the problem i have faced before.

without the new line of "ClothingShopItenery.remove(selected_item)", using the imagebutton just resulted the old problem:
clicking on image item will buy the previously clicked image item.
gold minus normally in this case. (in previous case, gold minus x2)

Not too sure how to fix it...

I will switch back to using textbutton, which works perfectly fine, for now. I think i will just use this textbutton for final product...

User avatar
xavimat
Eileen-Class Veteran
Posts: 1461
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Discord: xavimat
Contact:

Re: Why does my textbutton work in a weird way?

#12 Post by xavimat »

1. Imagebutton and textbutton should work the same, both are buttons, the "action" should do exactly the same.
2. Inside your "buy" function, you shouldn't use the variable "selected_item" but the local variable "item". I guess the estrange behavior you are getting lies there.
3. Check for the item in the list before removing it, the same way you check the money:

Code: Select all

init python:
    class Inventory:
        def __init__(self):
            self.items = []

        def buy(self, item):
            global gold
            global justbought
            if gold >= item.cost and item in ClothingShopItenery:
                gold -= item.cost
                self.items.append(item)
                justbought = item.name
                ClothingShopItenery.remove(item)
If I were you, I'd make another class for items and have a list of all items from the beginning. Instead of appending/removing objects from lists, you could have a variable "quantity" in every item: item.quantity == 0 means that the player does not own that item. another variable item.stock could be the quantity of items in the shop. The "buy" function could be inside the item class instead of the inventory class. So "buy" an item would be simply: self.quantity += 1; self.stock -= 1
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

Post Reply

Who is online

Users browsing this forum: Bing [Bot], Majestic-12 [Bot]