95 mini game Renpy

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.
Message
Author
User avatar
emilkun
Newbie
Posts: 17
Joined: Tue Apr 28, 2015 6:11 am
Location: England
Contact:

Re: 71 mini game Renpy

#61 Post by emilkun »

Andredron wrote: Thu Jan 25, 2018 6:14 pm 37)
Dragon and coins
viewtopic.php?f=8&t=65071
Hi! I've been playing around with this code, and my question would be: how do you add imagebuttons on the right side that work as up and down arrows when clicked/tapped? For touchscreen play or in case the up and down buttons from the keyboards don't work? I've tried everything I could think of but my attempts were vain. Thanks a lot if anyone can help!

thexerox123
Regular
Posts: 144
Joined: Fri Jan 20, 2023 3:21 pm
itch: thexerox123
Contact:

Re: 71 mini game Renpy

#62 Post by thexerox123 »

emilkun wrote: Fri Aug 18, 2023 4:38 am Hi! I've been playing around with this code, and my question would be: how do you add imagebuttons on the right side that work as up and down arrows when clicked/tapped? For touchscreen play or in case the up and down buttons from the keyboards don't work? I've tried everything I could think of but my attempts were vain. Thanks a lot if anyone can help!
There's code doing similar in the Christmas Cranes minigame!

viewtopic.php?f=8&t=66003&start=30

Code: Select all

image a_right = Image("Right_Idle.png", xysize=(100,100))
image a_left = Image("Left_Idle.png", xysize=(100,100))
image a_up = Image("Up_Idle.png", xysize=(100,100))

Code: Select all

    hbox:
        xalign 0.5 yalign 0.9 spacing 100
        for btn_img in ["a_left", "a_up", "a_right"]:
            imagebutton:
                idle btn_img action Return(btn_img)
                hover Transform(btn_img, matrixcolor=TintMatrix("#10e91a"))
...
    key "input_left" action Return("a_left")
    key "input_right" action Return("a_right")
    key "input_up" action Return("a_up")
You'd want to make it a vbox rather than an hbox (vertical vs horizontal).

And then key is referenced in the part of the class that handles inputs.

(You can thank _ticlock_ for that clever bit of code, I still wouldn't know to use that trick off-hand!)

User avatar
emilkun
Newbie
Posts: 17
Joined: Tue Apr 28, 2015 6:11 am
Location: England
Contact:

Re: 71 mini game Renpy

#63 Post by emilkun »

thexerox123 wrote: Sun Aug 20, 2023 11:15 pm
emilkun wrote: Fri Aug 18, 2023 4:38 am Hi! I've been playing around with this code, and my question would be: how do you add imagebuttons on the right side that work as up and down arrows when clicked/tapped? For touchscreen play or in case the up and down buttons from the keyboards don't work? I've tried everything I could think of but my attempts were vain. Thanks a lot if anyone can help!
There's code doing similar in the Christmas Cranes minigame!

viewtopic.php?f=8&t=66003&start=30
[...]
Thank you for the reply, I actually looked at this exact code before asking my question but unfortunately, I never managed to make it work. The arrows just won't appear , I managed to do it once but never managed to do it again but even then, it was impossible for me to click on them...
Where in this code would you add this?

Code: Select all

init python:

    import random

    class TigerGameDisplayable(renpy.Displayable):
        def __init__(self):
            renpy.Displayable.__init__(self)
            self.key_pressed = None # This will store which key is held down

            # Set game values
            self.PLAYER_WIDTH = 250
            self.PLAYER_HEIGHT = 200
            self.COIN_WIDTH = 128
            self.COIN_HEIGHT = 128
            self.PLAYER_STARTING_LIVES = 5
            self.PLAYER_VELOCITY = 50
            self.COIN_STARTING_VELOCITY = 10
            self.COIN_ACCELERATION = 1
            self.BUFFER_DISTANCE = 100

            self.score = 0
            self.player_lives = self.PLAYER_STARTING_LIVES
            self.food_velocity = self.COIN_STARTING_VELOCITY

            # Some displayables we use.
            self.player = Image("images/minigames/tiger_right.png")
            self.food = Image("images/minigames/food.png")

            # The positions of the two displayables.
            self.px = 20
            self.py = 500
            self.pymin = 100
            self.pymax = 1080 - 256
            self.cx = 1920 + 128
            self.cy = random.randint(128, 1080 - 128)
            self.cymin = 100
            self.cymax = 1080 - 128

            # The time of the past render-frame.
            self.oldst = None

            self.lose = False

            return

        # Draws the screen
        def render(self, width, height, st, at):

            # The Render object we'll be drawing into.
            r = renpy.Render(width, height)

            # Figure out the time elapsed since the previous frame.
            if self.oldst is None:
                self.oldst = st
            if self.key_pressed == "up":
                self.py -= self.PLAYER_VELOCITY
            elif self.key_pressed == "down":
                self.py += self.PLAYER_VELOCITY
            dtime = st - self.oldst
            self.oldst = st

            # This draws the player.
            def player(px, py, pymin, pymax):

                # Render the player image.
                player = renpy.render(self.player, width, height, st, at)

                # renpy.render returns a Render object, which we can
                # blit to the Render we're making.
                r.blit(player, (int(self.px), int(self.py)))
            
            # This draws the food.
            def food(cx, cy, cymin, cymax):

                # Render the food image.
                food = renpy.render(self.food, width, height, st, at)

                # renpy.render returns a Render object, which we can
                # blit to the Render we're making.
                r.blit(food, (int(self.cx), int(self.cy)))

            if self.cx < -128:
                # Player missed the food
                self.player_lives -= 1
                renpy.sound.play("audio/minigames/miss_sound.ogg")
                self.cx = width + 128
                self.cy = random.randint(128, height - 128)
            else:
                # Move the food
                self.cx -= self.food_velocity

            if self.py < self.pymin:
                self.py = self.pymin               
            if self.py > self.pymax:
                self.py = self.pymax

            if self.cy < self.cymin:
                self.cy = self.cymin               
            if self.cy > self.cymax:
                self.cy = self.cymax

            player(self.px, self.py, self.pymin, self.pymax)
            food(self.cx, self.cy, self.cymin, self.cymax)

            # Check for collisions
            def is_colliding(player, food):
                return (
                    self.px <= self.cx + self.COIN_WIDTH and
                    self.px + self.PLAYER_WIDTH >= self.cx and
                    self.py <= self.cy + self.COIN_HEIGHT and
                    self.py + self.PLAYER_HEIGHT >= self.cy
                )
            
            if is_colliding(player, food):
                self.score += 1
                renpy.sound.play("audio/minigames/food_sound.ogg")
                self.food_velocity += self.COIN_ACCELERATION
                self.cx = width + 128
                self.cy = random.randint(128, height - 128)

            # Check for a loss.
            if self.player_lives == 0:
                self.lose = True

                renpy.timeout(0)

            # Ask that we be re-rendered ASAP, so we can show the next
            # frame.
            renpy.redraw(self, 0)

            # Return the Render object.
            return r

        # Handles events.
        def event(self, ev, x, y, st):

            import pygame

            # The following allows to store which key was held down.
            if ev.type == pygame.KEYDOWN and ev.key == pygame.K_UP and self.key_pressed != "up":
                self.key_pressed = "up"
            elif ev.type == pygame.KEYDOWN and ev.key == pygame.K_DOWN and self.key_pressed != "down":
                self.key_pressed = "down"
            elif ev.type == pygame.KEYUP:
                self.key_pressed = None

            # Ensure the screen updates.
            renpy.restart_interaction()

            # If the player loses, return it.
            if self.lose:
                return self.lose
            else:
                raise renpy.IgnoreEvent()

    def display_score(st, at):
        return Text(_("Score: ") + "%d" % feed_the_tiger.score, size=40, color="#00cc00", outlines=[ (4, "#006600", 0, 0) ]), .1

    def display_player_lives(st, at):
        return Text(_("Lives: ") + "%d" % feed_the_tiger.player_lives, size=40, color="#00cc00", outlines=[ (4, "#006600", 0, 0) ]), .1

default feed_the_tiger = TigerGameDisplayable()

screen feed_the_tiger():

    add Solid("#000000")

    add feed_the_tiger

    add DynamicDisplayable(display_score) xpos 240 xanchor 0.5 ypos 25

    add DynamicDisplayable(display_player_lives) xpos (1920 - 240) xanchor 0.5 ypos 25

    text _("Feed the Tiger"):
        xalign 0.5
        ypos 25
        size 40
        color "#00cc00"
        outlines [ (4, "#006600", 0, 0) ]
        #font "gui/font/PressStart2P.ttf"

label play_feed_the_tiger:

    window hide  # Hide the window and quick menu while in Feed the Dragon
    $ quick_menu = False

    play music "audio/minigames/tune.mp3"

    $ feed_the_tiger.lose = False
    $ feed_the_tiger.score = 0
    $ feed_the_tiger.player_lives = 5
    $ feed_the_tiger.food_velocity = feed_the_tiger.COIN_STARTING_VELOCITY
    $ feed_the_tiger.py = 500
    $ feed_the_tiger.cy = random.randint(128, 1080 - 128)

    call screen feed_the_tiger

    play music  "audio/minigames/04.mp3"

    $ quick_menu = True
    window auto

label feed_the_tiger_done:

    if persistent.feed_the_tiger_high_score >= feed_the_tiger.score:
        pass
    else:
        $ persistent.feed_the_tiger_high_score = feed_the_tiger.score

    "Score: [feed_the_tiger.score]\n\nHigh Score: [persistent.feed_the_tiger_high_score]"
label start:
    menu:
        "Would you like to play again?"

        "Yes.":
            jump play_feed_the_tiger

        "No.":
            jump aftergame

Sorry to be a bother and I understand if you can't help

thexerox123
Regular
Posts: 144
Joined: Fri Jan 20, 2023 3:21 pm
itch: thexerox123
Contact:

Re: 71 mini game Renpy

#64 Post by thexerox123 »

emilkun wrote: Tue Aug 22, 2023 12:39 pm Thank you for the reply, I actually looked at this exact code before asking my question but unfortunately, I never managed to make it work. The arrows just won't appear , I managed to do it once but never managed to do it again but even then, it was impossible for me to click on them...
Where in this code would you add this?

Sorry to be a bother and I understand if you can't help
No bother at all! I'm actually at a part in my current minigame endeavour where I've started trying to reverse engineer this bit of _ticlock_'s code to allow for different control schemes, so it's well-timed! (I also haven't gotten it to quite work for myself yet, though, so take anything I say at this point with a grain of salt! Haha.)

The image definitions would be at the start, before the init python block.

The hbox would be within the screen, probably at the end to be the topmost layer. The key action assignments are also in the screen.

I *think* that it would involve passing "key" along to your event and render methods, as that's where the inputs are handled.

In the Christmas Cranes code, I noticed that the imagebuttons were not given an action other than to return the button itself:

Code: Select all

    hbox:
        xalign 0.5 yalign 0.9 spacing 100
        for btn_img in ["a_left", "a_up", "a_right"]:
            imagebutton:
                idle btn_img action Return(btn_img)
                hover Transform(btn_img, matrixcolor=TintMatrix("#10e91a"))
...
    key "input_left" action Return("a_left")
    key "input_right" action Return("a_right")
    key "input_up" action Return("a_up")
The images for a_left, _right, and _up are defined at the beginning, and there are no other references to input_left, _right, _up. Edit: Sussed out that input_left, etc are referencing Renpy's default keymap: https://www.renpy.org/doc/html/keymap.h ... the-keymap So that's how it links the onscreen button to the keyboard button.

But, "key" is referenced in two methods of the code that handle inputs:

In the Crane class:

Code: Select all

        def input_handler(self, key, st, game):
            try:
                if self.arrows[self.progress] == key and self.progress == game.progress:
                    self.progress += 1
                    game.reset_progress = False
                    if self.progress == len(self.arrows):
                        self.progress = "done"
                        self.end_st = st
                        game.reset_progress = True
                        return True
                else:
                    self.progress = 0
            except TypeError:
                return
And in the CraneGame class:

Code: Select all

        def handler(self, key = None):
            if key:
                self.reset_progress = True
                for column in self.columns:
                    for crane in column:
                        if crane.input_handler(key, self.time, self):
                            self.score += 1
                if self.reset_progress:
                    self.progress = 0
                else:
                    self.progress += 1
I think the first one is saying that if the key [a_left, _right, _up] matches the arrow that has been assigned to the crane from the same list, then that crane progresses. And I think the second part runs the first method (crane.input_handler) when the key is pressed, and handles the crane scoring. So they'd be equivalent to your event method and your render method (where it deals with keypresses).

So I think the way it's working is that it changes the keymap functions within the screen, and then the methods handle the logic of what happens when that button is triggered, whether it's by keyboard or onscreen button. So I think you'd need to change how the event methods work, so that it's handling things using "key" rather than "KEYDOWN"/"KEYUP". https://www.renpy.org/doc/html/screens.html#key

Since you just have the two keypresses to consider, I don't know if you can just do a simple "if key == "input_up"" or "if key == "a_"" conditional? I currently only have these two examples which are checking for the arrow == key and just checking for any of the listed keys with "if key".

I don't know if that helps, I'm still trying to figure it out myself! If I do get it working in my new minigame, I'll see if I can clarify or confirm any of this! :)

thexerox123
Regular
Posts: 144
Joined: Fri Jan 20, 2023 3:21 pm
itch: thexerox123
Contact:

Re: 71 mini game Renpy

#65 Post by thexerox123 »

Another option that I may just give in and do myself:

Allow the player to select their control type at the start, and then it's an either/or thing rather than trying to get the onscreen and keyboard controls to work in conjunction

User avatar
_ticlock_
Miko-Class Veteran
Posts: 910
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: 71 mini game Renpy

#66 Post by _ticlock_ »

emilkun wrote: Tue Aug 22, 2023 12:39 pm Thank you for the reply, I actually looked at this exact code before asking my question but unfortunately, I never managed to make it work. The arrows just won't appear , I managed to do it once but never managed to do it again but even then, it was impossible for me to click on them...
Where in this code would you add this?
Your minigame seems to work withing a single call screen statement. You need to process the pressed keys or buttons within the screen interaction. I provided an example in this post viewtopic.php?f=8&t=66003&p=562510#p562510

Orme_
Newbie
Posts: 2
Joined: Mon Aug 28, 2023 6:12 pm
Contact:

Re: 71 mini game Renpy

#67 Post by Orme_ »

Hi,
I have a problem with the dog fishing game. The game is not center and i don't want to mess up the game by meddling with the game (like the sapwn of the fish).
Where can I find the code line in order to center my game?

Thanks a lot!

User avatar
Andredron
Miko-Class Veteran
Posts: 776
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: 71 mini game Renpy

#68 Post by Andredron »

Orme_ wrote: Mon Aug 28, 2023 6:18 pm Hi,
I have a problem with the dog fishing game. The game is not center and i don't want to mess up the game by meddling with the game (like the sapwn of the fish).
Where can I find the code line in order to center my game?

Thanks a lot!
I ended up changing the position variable for each object. So in each object class (fish & player), there's self.position. It's [x, y], so by default for the fish class, for example, it's [0,0]. Actually I'm not even sure if this one's important -- for the fish, the important one is the createNew(self) one, where position[0] (x position) is random between 0 and 800. Just change that to where you need the fish to spawn. position [1] right below that is for y position, just change 0 to your desired y. Make sure you also change self.maxY in Fish() to where you want the fish to stop falling.

Same thing for class Player (), change position to the new x and y coordinates; that's where it'll spawn. Then change

Code: Select all

if ( self.position[0] < 0 ):
    self.position[0] = 0
elif ( self.position[0] > 800 - self.dimensions[0] ):
    self.position[0] = 800 - self.dimensions[0]
from 0 and 800 to your leftmost and rightmost coordinate, respectively. Basically everything's just fiddling around with the position of each object.

Lastly I noticed there's r = renpy.render( self.image, 800, 600, shownTimebase, animationTimebase ) , which on documentation says this

"class renpy.Render(width, height)"

so I assume you would want to change 800 and 600 to your new dimensions.
Renpy textbook (in Russian). https://disk.yandex.ru/i/httNEajU7iFWHA (all information is out of date) Update 22.06.18

Sawa - a game of the Drow Nation

Honest Critique

Poses in visual novels, or how to hold a character properly in the frame

Help save articles to the webarchive. [/color]

Please save your projects on github, you would know how hard it is to find projects after 7 years...

Orme_
Newbie
Posts: 2
Joined: Mon Aug 28, 2023 6:12 pm
Contact:

Re: 71 mini game Renpy

#69 Post by Orme_ »

Andredron wrote: Tue Aug 29, 2023 1:22 am
Orme_ wrote: Mon Aug 28, 2023 6:18 pm Hi,
I have a problem with the dog fishing game. The game is not center and i don't want to mess up the game by meddling with the game (like the sapwn of the fish).
Where can I find the code line in order to center my game?

Thanks a lot!
I ended up changing the position variable for each object. So in each object class (fish & player), there's self.position. It's [x, y], so by default for the fish class, for example, it's [0,0]. Actually I'm not even sure if this one's important -- for the fish, the important one is the createNew(self) one, where position[0] (x position) is random between 0 and 800. Just change that to where you need the fish to spawn. position [1] right below that is for y position, just change 0 to your desired y. Make sure you also change self.maxY in Fish() to where you want the fish to stop falling.

Same thing for class Player (), change position to the new x and y coordinates; that's where it'll spawn. Then change

Code: Select all

if ( self.position[0] < 0 ):
    self.position[0] = 0
elif ( self.position[0] > 800 - self.dimensions[0] ):
    self.position[0] = 800 - self.dimensions[0]
from 0 and 800 to your leftmost and rightmost coordinate, respectively. Basically everything's just fiddling around with the position of each object.

Lastly I noticed there's r = renpy.render( self.image, 800, 600, shownTimebase, animationTimebase ) , which on documentation says this

"class renpy.Render(width, height)"

so I assume you would want to change 800 and 600 to your new dimensions.

After testing and a lot of head-scratching, I found out that my problem is because, the gui of my game is different of the gui of the source game, and (as it was coded in a prevous version of renpy), I doesn't have a clue on how to solve this problem.

Thanks for your help

User avatar
Andredron
Miko-Class Veteran
Posts: 776
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: 76 mini game Renpy

#70 Post by Andredron »

Renpy textbook (in Russian). https://disk.yandex.ru/i/httNEajU7iFWHA (all information is out of date) Update 22.06.18

Sawa - a game of the Drow Nation

Honest Critique

Poses in visual novels, or how to hold a character properly in the frame

Help save articles to the webarchive. [/color]

Please save your projects on github, you would know how hard it is to find projects after 7 years...

User avatar
Andredron
Miko-Class Veteran
Posts: 776
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: 79 mini game Renpy

#71 Post by Andredron »

https://github.com/BlackRam-oss/Chrome-Dino-Runner

A Replica of the hidden Dinosaur Game from Chrome Browser Offline mode build using Python and PyGame.
Renpy textbook (in Russian). https://disk.yandex.ru/i/httNEajU7iFWHA (all information is out of date) Update 22.06.18

Sawa - a game of the Drow Nation

Honest Critique

Poses in visual novels, or how to hold a character properly in the frame

Help save articles to the webarchive. [/color]

Please save your projects on github, you would know how hard it is to find projects after 7 years...

User avatar
birctreel
Regular
Posts: 53
Joined: Wed Dec 20, 2017 7:17 am
Projects: Knell of st.Godhrkar
Organization: -Andinomie-
Tumblr: birctreel
Location: Beijing, China
Contact:

Re: 80 mini game Renpy

#72 Post by birctreel »

THank you!!
It would be definitely helpful! Each of the mini games looks so interesting ^^

User avatar
Andredron
Miko-Class Veteran
Posts: 776
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: 81 mini game Renpy

#73 Post by Andredron »

Code: Select all

#mines
init python:
    
    import random

    class MinesweeperGame:

        def __init__(self, dimx, dimy, bombs):

            if dimx > dimy:

                self.dimx = dimx

                self.dimy = dimy

            else:

                self.dimx = dimy

                self.dimy = dimx

            self.bombs = bombs

            self.table = MinesweeperTileset(self.dimx, self.dimy, bombs)

            self.dim = 1000//self.dimy

            self.colors = [u'#fff',u'#060afe',u'#388e3c',u'#d32f2f',u'#ba2fd3',u'#d38f2f',u'#2fbed3',u'#2fd38f',u'#f5e42b']


    class MinesweeperTileset:

        def __init__(self, dimx, dimy, bombs):

            self.explosion = False

            self.bombs = bombs

            self.opened = 0

            self.marked = 0

            self.tiles = []

            self.dimx = dimx

            self.dimy = dimy

            for i in range(dimy):

                self.tiles.append([])

                for j in range(dimx):

                    self.tiles[i].append(MinesweeperTile(posi = i, posj = j))

            self.pomlist = range(dimx*dimy)

            random.shuffle(self.pomlist)

            for i in range(bombs):

                ii = self.pomlist[i] // dimx
                jj = self.pomlist[i] % dimx

                self.tiles[ii][jj].bomb = True

                pomarr = self.getNeighbours(ii,jj)

                for x in pomarr:

                    x.num += 1

        def getNeighbours(self, posi, posj):

            nbrs = []

            if (posi == 0 and posj == 0):

                nbrs.append(self.tiles[posi+1][posj+1])
                nbrs.append(self.tiles[posi+1][posj])
                nbrs.append(self.tiles[posi][posj+1])

            elif (posi == 0 and posj == self.dimx - 1):

                nbrs.append(self.tiles[posi][posj-1])
                nbrs.append(self.tiles[posi+1][posj])
                nbrs.append(self.tiles[posi+1][posj-1])

            elif (posi == self.dimy - 1 and posj == 0):

                nbrs.append(self.tiles[posi-1][posj+1])
                nbrs.append(self.tiles[posi-1][posj])
                nbrs.append(self.tiles[posi][posj+1])

            elif (posi == self.dimy - 1 and posj == self.dimx - 1):

                nbrs.append(self.tiles[posi-1][posj-1])
                nbrs.append(self.tiles[posi-1][posj])
                nbrs.append(self.tiles[posi][posj-1])

            else:

                if posi == 0:

                    nbrs.append(self.tiles[posi+1][posj-1])
                    nbrs.append(self.tiles[posi+1][posj])
                    nbrs.append(self.tiles[posi+1][posj+1])
                    nbrs.append(self.tiles[posi][posj-1])
                    nbrs.append(self.tiles[posi][posj+1])

                elif posj == 0:

                    nbrs.append(self.tiles[posi-1][posj])
                    nbrs.append(self.tiles[posi+1][posj])
                    nbrs.append(self.tiles[posi-1][posj+1])
                    nbrs.append(self.tiles[posi][posj+1])
                    nbrs.append(self.tiles[posi+1][posj+1])

                elif posi == self.dimy - 1:

                    nbrs.append(self.tiles[posi-1][posj-1])
                    nbrs.append(self.tiles[posi-1][posj])
                    nbrs.append(self.tiles[posi-1][posj+1])
                    nbrs.append(self.tiles[posi][posj-1])
                    nbrs.append(self.tiles[posi][posj+1])

                elif posj == self.dimx - 1:

                    nbrs.append(self.tiles[posi-1][posj-1])
                    nbrs.append(self.tiles[posi][posj-1])
                    nbrs.append(self.tiles[posi+1][posj-1])
                    nbrs.append(self.tiles[posi-1][posj])
                    nbrs.append(self.tiles[posi+1][posj])

                else:

                    nbrs.append(self.tiles[posi-1][posj-1])
                    nbrs.append(self.tiles[posi-1][posj])
                    nbrs.append(self.tiles[posi-1][posj+1])
                    nbrs.append(self.tiles[posi][posj-1])
                    nbrs.append(self.tiles[posi][posj+1])
                    nbrs.append(self.tiles[posi+1][posj-1])
                    nbrs.append(self.tiles[posi+1][posj])
                    nbrs.append(self.tiles[posi+1][posj+1])

            return nbrs


        def open(self, posi, posj):

            self.tiles[posi][posj].opened = True

            self.opened += 1

            if self.tiles[posi][posj].bomb == True:

                self.explosion = True

            else:

                if not self.tiles[posi][posj].num:

                    pomarr = self.getNeighbours(posi,posj)

                    for x in pomarr:

                        if not x.opened:

                            self.open(posi = x.posi, posj = x.posj)


        def toggle(self, posi, posj):

            self.tiles[posi][posj].marked ^= True

            if self.tiles[posi][posj].marked:
                
                self.marked += 1

            else:

                self.marked -= 1 

        def force_open(self, posi, posj):

            nbrs = self.getNeighbours(posi,posj)

            pomnum = 0
            for x in nbrs:

                if x.marked:

                    pomnum+=1

            if pomnum == self.tiles[posi][posj].num:

                for x in nbrs:

                    if not x.opened and not x.marked:

                        self.open(posi = x.posi, posj = x.posj)

            # else:

            #     for x in nbrs:

            #         if not x.opened:

            #             x.hlight = True


            

    class MinesweeperTile:

        def __init__(self, posi, posj):

            self.posi = posi
            self.posj = posj

            self.bomb = False
            self.marked = False
            self.num = 0
            self.opened = False
            self.hlight = False


transform hlighttf():

    easeout 0.3 alpha 0.5
    easein 0.3 alpha 1.0

screen msw_screen(ms):

    modal True
    zorder 1000

    add "background.png"

    frame:

        xalign 0.99
        yalign 0.01
        fixed:

            xsize 200
            ysize 120


            vbox:
                label "Bombs:"
                hbox:
                    text str(ms.table.marked)
                    text "/"
                    text str(ms.table.bombs)
    frame:

        xalign 0.5
        yalign 0.5
    
        fixed:

            xsize ms.dim*ms.dimx
            ysize ms.dim*ms.dimy
    
            for i in range(len(ms.table.tiles)):

                for j in range(len(ms.table.tiles[i])):

                    button:

                        xsize ms.dim
                        ysize ms.dim

                        xpos j * ms.dim
                        ypos i * ms.dim

                        if not ms.table.tiles[i][j].opened:
                            
                            background u'#cc0066'
                            hover_background u'#dd0077'
                            alternate [Function(ms.table.toggle, posi = i, posj = j)]
                            action [Function(ms.table.open, posi = i, posj = j)]
                            if ms.table.tiles[i][j].marked:

                                text ('X') xalign 0.5 yalign 0.5

                            #if ms.table.tiles[i][j].hlight:

                                #at hlighttf

                                #$ ms.table.tiles[i][j].hlight = False

                        else:

                            background u'#191316'
                            alternate [Function(ms.table.force_open, posi = i, posj = j)]
                            action [Function(ms.table.force_open, posi = i, posj = j)]
                            if ms.table.tiles[i][j].bomb:

                                text ('O') xalign 0.5 yalign 0.5

                            elif ms.table.tiles[i][j].num:

                                text (str(ms.table.tiles[i][j].num)) xalign 0.5 yalign 0.5 color ms.colors[ms.table.tiles[i][j].num]


                        
                        #hovered []

    if ms.table.explosion:

        button:

            background u'#191316aa'
            xsize 1920
            ysize 1080

            action [Hide("msw_screen"),Jump("start")]

        vbox:
            xalign 0.5 
            yalign 0.5
            text "The mine exploded :((" size 50 xalign 0.5 yalign 0.5
            text "Press anywhere to play again!" xalign 0.5 yalign 0.5

    if ms.dimx*ms.dimy - ms.table.opened == ms.table.bombs:

        button:

            background u'#191316aa'
            xsize 1920
            ysize 1080

            action [Hide("msw_screen"),Jump("start")]

        vbox:
            xalign 0.5 
            yalign 0.5
            text "You found all the mines!!!" size 50 xalign 0.5 yalign 0.5
            text "Press anywhere to play again!" xalign 0.5 yalign 0.5

label start:

    $ msgame = MinesweeperGame(20,24,99)

    show screen msw_screen(ms = msgame)

    pause

    # This shows a character sprite. A placeholder is used, but you can
    # replace it by adding a file named "eileen happy.png" to the images
    # directory.

    show eileen happy

    # These display lines of dialogue.

    e "You've created a new Ren'Py game."

    e "Once you add a story, pictures, and music, you can release it to the world!"

    # This ends the game.

    return
Renpy textbook (in Russian). https://disk.yandex.ru/i/httNEajU7iFWHA (all information is out of date) Update 22.06.18

Sawa - a game of the Drow Nation

Honest Critique

Poses in visual novels, or how to hold a character properly in the frame

Help save articles to the webarchive. [/color]

Please save your projects on github, you would know how hard it is to find projects after 7 years...

thexerox123
Regular
Posts: 144
Joined: Fri Jan 20, 2023 3:21 pm
itch: thexerox123
Contact:

Re: 81 mini game Renpy

#74 Post by thexerox123 »

I bring another humble offering for this wonderful thread, made using PyTom's Cardgame Framework:

viewtopic.php?p=565308#p565308

User avatar
Andredron
Miko-Class Veteran
Posts: 776
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: 83 mini game Renpy

#75 Post by Andredron »

Code: Select all

init python:
    import random
    import os
    import json

	# Initialize the game with players, dice sides, rounds, dice count, bonus sides, and bonus scores
    class DiceGame:
        def __init__(self, players, sides=6, rounds=1, dice_count=1, bonus_sides=[], bonus_scores={}):
            self.players = players
            self.sides = sides
            self.rounds = rounds
            self.dice_count = dice_count
            self.bonus_sides = bonus_sides
            self.bonus_scores = bonus_scores
            self.scores = {player: 0 for player in players}
            self.rolls = 0
            self.current_player = None
            self.current_rolls = []
            # game_wins is a good addition to track wins across multiple games.
            self.game_wins = {}

	# Roll the dice for a player and update their score
        def roll(self, player):
            self.rolls += 1
            self.current_player = player
            self.current_rolls = []
            for _ in range(self.dice_count):
                roll = random.randint(1, self.sides)
                self.current_rolls.append(roll)
                # Using get() with a default value simplifies the bonus score handling.
                self.scores[player] += self.bonus_scores.get(roll, 0) or roll
            return self.current_rolls
	
	# Reset the scores and rolls for a new round
        def reset_round(self):
            self.scores = {player: 0 for player in self.players}
            self.rolls = 0
            self.current_player = None
            self.current_rolls = []

	# Reset the scores, rolls, and rounds for a new game
        def reset_game(self):
            self.scores = {player: 0 for player in self.players}
            self.rolls = 0
            self.rounds = 1
            self.current_player = None
            self.current_rolls = []

	# Determine the winner based on the highest score
        def winner(self):
            winner = max(self.scores, key=self.scores.get) if self.scores else None
            if winner:
                self.game_wins[winner] = self.game_wins.get(winner, 0) + 1
            return winner

	# Check if it's the last round
        def is_last_round(self):
            return self.rounds == 1

	# Save the game results to a JSON file
        def save_results(self, filename):
            directory = os.path.dirname(filename)
            if not os.path.exists(directory):
                os.makedirs(directory)
            with open(filename, 'w') as f:
                json.dump({"scores": self.scores, "winner": self.winner(), "game_wins": self.game_wins}, f)

	# Clear the game results from the JSON file
        def clear_results(self, filename):
            if os.path.exists(filename):
                with open(filename, 'w') as f:
                    json.dump({}, f)

	# Load the game results from the JSON file
        @classmethod
        def load_results(cls, filename):
        # Load game results from a file, with default values if the file is empty or does not exist.
            if not os.path.exists(filename):
                return {}, None, {}
            with open(filename, 'r') as f:
                data = json.load(f)
                return data.get("scores", {}), data.get("winner", None), data.get("game_wins", {})

# UI elements are well-structured and informative.
screen dice_game:
    frame:
        xalign 0.5
        yalign 0.5
        vbox:
            text "Dice Game" size 36 xalign 0.5
            null height 20
            hbox:
                for player in dice.players:
                    vbox:
                        text player size 24 xalign 0.5
                        text str(dice.scores[player]) size 36 xalign 0.5
            null height 20
            if dice.current_player:
                text "Current player: [dice.current_player]" size 24 xalign 0.5
                text "Cube: [dice.current_rolls]" size 24 xalign 0.5
            else:
                text "No current player" size 24 xalign 0.5
            null height 20
            textbutton "Roll Dice" action Jump("roll_dice") xalign 0.5
            textbutton "Reset Round" action Function(dice.reset_round) xalign 0.5
            textbutton "Reset Game" action Function(dice.reset_game) xalign 0.5

label start:
    # Initializing the game with default values is clear.
    python:
        players = ["Player", "NPS"]
        sides = 6
        rounds = 3
        dice_count = 2
        bonus_sides = [6]
        bonus_scores = {6: 5}
        dice = DiceGame(players, sides, rounds, dice_count, bonus_sides, bonus_scores)
        scores, winner, game_wins = DiceGame.load_results("game/results.json")
        if game_wins is not None:
            dice.game_wins = game_wins

    # Displaying previous game results provides context.
    if scores:
        if winner:
            $ winning_score = scores[winner]
            $ other_scores = {k: v for k, v in scores.items() if k != winner}
            $ losing_score = min(other_scores.values()) if other_scores else 0
            $ diff = winning_score - losing_score
            "You won last game by beating your opponent by [diff] points!"
            "You have won [dice.game_wins[winner]] games in total!"
        else:
            "In the last game, you failed to win!"

    $ filename = "game/results.json"
    "Welcome to the dice game!"
    "There are players, and each player rolls a certain number of dice, for example - ([dice_count]) a die with [sides] sides."
    if rounds > 1:
        "There will be [rounds] rounds in the game."
    if bonus_sides:
        "If you roll a number [bonus_sides[0]], you will get [bonus_scores.get(bonus_sides[0], 0)] bonus points!"
        if len(bonus_sides) > 1:
            "If you roll a number [bonus_sides[1]], you will get [bonus_scores.get(bonus_sides[1], 0)] bonus points!"
    menu:
        "Do you want to start the game?"
        "Yes":
            jump game
        "No":
            menu:
                "Do you want to clear the game results?"
                "Yes":
                    $ dice.clear_results(filename)
                    "Game results cleared!"
                    jump start
                "No":
                    "Thanks for playing!"
                    return

label game:
    call screen dice_game

label roll_dice:
    # Handling the last round and determining the winner is well-implemented.
    if dice.is_last_round():
        $ winner = dice.winner()
        if winner:
            "The winner of the game is [winner]!"
            # Offering to save results at the end of the game is a good practice.
            "Do you want to save the results?"
            menu:
                "Yes":
                    $ dice.save_results(filename)
                    "The results have been saved to [filename]."
                    jump start
                "No":
                    menu:
                        "Do you want to clear the game results?"
                        "Yes":
                            $ dice.clear_results(filename)
                            "Game results cleared!"
                            jump start
                        "No":
                            "Thanks for playing!"
                            return
        else:
            "Tie!"
            "Do you want to save the results?"
            menu:
                "Yes":
                    $ dice.save_results(filename)
                    "The results have been saved to [filename]."
                    jump start
                "No":
                    menu:
                        "Do you want to clear the game results?"
                        "Yes":
                            $ dice.clear_results(filename)
                            "Game results cleared!"
                            jump start
                        "No":
                            "Thanks for playing!"
                            return
    else:
        $ dice.rounds -= 1
        "Round [dice.rounds]!"
        python:
            for player in dice.players:
                rolls = dice.roll(player)
        call screen dice_game
        "Do you want to roll again?"
        menu:
            "Yes":
                jump roll_dice
            "No":
                menu:
                    "Do you want to clear the game results?"
                    "Yes":
                        $ dice.clear_results(filename)
                        "Game results cleared!"
                        jump start
                    "No":
                        "Thanks for playing!"
                        return
Renpy textbook (in Russian). https://disk.yandex.ru/i/httNEajU7iFWHA (all information is out of date) Update 22.06.18

Sawa - a game of the Drow Nation

Honest Critique

Poses in visual novels, or how to hold a character properly in the frame

Help save articles to the webarchive. [/color]

Please save your projects on github, you would know how hard it is to find projects after 7 years...

Post Reply

Who is online

Users browsing this forum: No registered users