Renpy how to start making minigame

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
Princesky
Newbie
Posts: 5
Joined: Fri May 17, 2024 11:40 am
Contact:

Renpy how to start making minigame

#1 Post by Princesky »

Hello! I've made my own game for quite a bit now, and I really want to add some mini game to them, I already came across some example of mini games here on this forum.

I really want to get the hang of programing since at this moment, I'm a total newbie, is there any resource apart from the renpy documentation that could help me get started on making some simple minigames?

i've been trying to follow on some videos, but some seems dated and don't actually work with the current version of Renpy

For reference, i want to make a sort of infinite runner kind of minigame, and maybe a rythm one later on.

Thanks for reading me


Princesky
Newbie
Posts: 5
Joined: Fri May 17, 2024 11:40 am
Contact:

Re: Renpy how to start making minigame

#3 Post by Princesky »

this give out this error

OSError: Could not open 'assets/DinoWallpaper.png'. b"Couldn't open assets/DinoWallpaper.png"

The image is in the right folder though

Code: Select all

init python:
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import os
    import random
    import threading
    import pygame
    
    pygame.init()

    def set_mode():

        if _preferences.fullscreen:
            fsflag = FULLSCREEN
        else:
            fsflag = 0
    
        screen = pygame.display.set_mode((800, 600), fsflag, 32)
        return screen
    
    set_mode()    

    # Global Constants

    SCREEN_HEIGHT = 800
    SCREEN_WIDTH = 1200
    SCREEN = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

    pygame.display.set_caption("Chrome Dino Runner")

    Ico = pygame.image.load("assets/DinoWallpaper.png")
    pygame.display.set_icon(Ico)

RewindTheGame
Regular
Posts: 80
Joined: Thu Dec 31, 2020 3:37 pm
Contact:

Re: Renpy how to start making minigame

#4 Post by RewindTheGame »

Based on the directory structure in the download, it looks as though that should probably be:

Code: Select all

Ico = pygame.image.load("minigame/assets/DinoWallpaper.png")
but as I'm not familiar with PyGame this may or may not be the solution.

Simon

jeffster
Miko-Class Veteran
Posts: 520
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Re: Renpy how to start making minigame

#5 Post by jeffster »

There are tons of minigames presented and discussed in Ren'Py Cookbook:
viewforum.php?f=51

And generally search the whole forum with keywords like minigame, rhythm etc.
Princesky wrote: Thu May 23, 2024 6:44 am this give out this error

OSError: Could not open 'assets/DinoWallpaper.png'. b"Couldn't open assets/DinoWallpaper.png"

The image is in the right folder though

Code: Select all

...
    Ico = pygame.image.load("assets/DinoWallpaper.png")
I guess the error here shows that pygame doesn't know anything about the base directory Ren'Py works with.

Moreover, putting Python + pygame code directly into Ren'Py is an incorrect approach.

For example, most imports are already in Ren'Py, and you shouldn't try to reset display like

Code: Select all

pygame.display.set_mode((800, 600), fsflag, 32)
because it would interfere with Ren'Py's work.

In Ren'Py you already have initialized display etc.

Drop all that low-level programming and implement the game logic with Ren'Py methods:

Code: Select all

# Initial x, y of the player on screen
default player_x = 100
default player_y = 800

init python:
    ### Set constants ###
    # Movement (x, y):
    RIGHT = (1, 0)
    LEFT = (-1, 0)
    UP = (0, -1)
    DOWN = (0, 1)

    ### Python functions ###
    def updateRunner(direction, jumping):
        # Some function here to update Runner position and process everything:
        #...
        store.player_x += direction[0]
        store.player_y += direction[1]
        #...
        #... Collision detection, jumping, falling etc.
        #...

# Ren'Py uses "screen" for interactions with player:
screen minigame_runner():

    # Set Runner direction and jumping status as ScreenVariable's:
    default direction = RIGHT
    default jumping = None

    # 60 times per second update Runner position
    timer 0.016 action Function(updateRunner, direction, jumping) repeat True

    # Set buttons and keyboard keys to control Runner:

    button:
        # Click this with mouse or press "Arrow Left" to send Runner left
        keysym focus_left
        action SetScreenVariable("direction", LEFT)
        align (0.0, 0.5)
        xysize (240, 600)
        background "#666"
        
    button:
        # Click this with mouse or press "Arrow Right" to send Runner right
        keysym focus_right
        action SetScreenVariable("direction", RIGHT)
        align (1.0, 0.5)
        xysize (240, 600)
        background "#666"

    button:
        # Click this with mouse or press "Arrow Up" to send Runner up
        keysym focus_up
        action SetScreenVariable("direction", UP)
        align (0.5, 0.0)
        xysize (1200, 240)
        background "#666"

    button:
        # Click this with mouse or press "Arrow Down" to send Runner down
        keysym focus_down
        action SetScreenVariable("direction", DOWN)
        align (0.5, 1.0)
        xysize (1200, 240)
        background "#666"

    button:
        # A button to jump (spacebar), or possibly 2 buttons: "jump left", "jump right"
        #...

    add scrolling_scene:
        # This could be a Creator Defined Displayable or whatever method to scroll the scene
        #...
    add player_figure:
        pos (player_x, player_y)
        #...
Examine how Creator Defined Displayables work, and that would give clues about programming dynamic elements in Ren'Py:
https://renpy.org/doc/html/cdd.html
If the problem is solved, please edit the original post and add [SOLVED] to the title. 8)

RewindTheGame
Regular
Posts: 80
Joined: Thu Dec 31, 2020 3:37 pm
Contact:

Re: Renpy how to start making minigame

#6 Post by RewindTheGame »

Not to create a stir or anything, but you can also pretty much ask an AI to write you code these days. I suggest this merely as a learning tool, of course, and wouldn't want to suggest using AI to write your actual game - but I sure wish we'd had something like that available in the 80s. The absolute best way to learn programming is by studying existing code.

Princesky
Newbie
Posts: 5
Joined: Fri May 17, 2024 11:40 am
Contact:

Re: Renpy how to start making minigame

#7 Post by Princesky »

Thanks for all your answer and help, i came begging for help once again.
jeffster wrote: Thu May 23, 2024 7:47 am There are tons of minigames presented and discussed in Ren'Py Cookbook:
viewforum.php?f=51

And generally search the whole forum with keywords like minigame, rhythm etc.
Princesky wrote: Thu May 23, 2024 6:44 am this give out this error

OSError: Could not open 'assets/DinoWallpaper.png'. b"Couldn't open assets/DinoWallpaper.png"

The image is in the right folder though

Code: Select all

...
    Ico = pygame.image.load("assets/DinoWallpaper.png")
I guess the error here shows that pygame doesn't know anything about the base directory Ren'Py works with.

Moreover, putting Python + pygame code directly into Ren'Py is an incorrect approach.

For example, most imports are already in Ren'Py, and you shouldn't try to reset display like

Code: Select all

pygame.display.set_mode((800, 600), fsflag, 32)
because it would interfere with Ren'Py's work.

In Ren'Py you already have initialized display etc.

Drop all that low-level programming and implement the game logic with Ren'Py methods:
I couldn't manage to piece together something with the code you offered, i couldn't really make out the gaps but i did find a tutorial here:

https://youtu.be/ZZsCUROxKQk

It's not what i wanted to do at all, but by following along, and cutting down on the feature i didn't want, i managed to make the code work but i've run into a dead end now and have a couple issues.

First of all, my character doesn't move anymore, it seems to have happened after i got rid of the other characters.

Two, the movements aren't really working as i wanted them to be, my goal is to make the character move automatically while also being able to move him to the left and right of the screen aaand of course jump. but the way the i made out the key_pressed thingy seems to be barely working... also i'd want to have the character move back down from a jump with a small inertia ideally..

Also i didn't even try to include a scrolling background and obstacle with a hitbox as i wanted to make the character movement first of all.

So how would i go down to include all the following while improving on the code i have now?

Thanks again for the help!

Code: Select all

init python:
    def reset_racing_game():
        global selected_character
        global selected_character_pos
        global who_won
        global goal_reached
        global countdown_timer

        countdown_timer = 3
        who_won = None
        goal_reached = False
        selected_character = None
        character_1_pos = [character_1.x, character_1.y]

        
        renpy.hide_screen("game_over")
        renpy.hide_screen("racing_mini_game")
        renpy.show_screen("racing_game_menu")
    def npc_movement(st):


        return None
    def character_events(event, x, y, st):
        #this function is the event of spritemanager
        global left_key_pressed
        global right_key_pressed
        global up_key_pressed
        global player_start_move

        if event.type == renpy.pygame_sdl2.KEYDOWN and countdown_timer == 0:
            #a key is being pressed down.
            keys_pressed = renpy.pygame_sdl2.key.get_pressed()
            if keys_pressed[renpy.pygame_sdl2.K_LEFT]:
                player_start_move = True
                left_key_pressed = True
                character_movex(character_1)
            elif keys_pressed[renpy.pygame_sdl2.K_RIGHT]:
                player_start_move = True
                right_key_pressed = True            
                character_movex(character_1)


            if keys_pressed[renpy.pygame_sdl2.K_UP]:
                up_key_pressed = True
            


            if up_key_pressed:
                character_move(character_1)
            


    def setup_racing_game():
        global character_1_pos

        character_1.x = 200
        character_1.y = 500

        character_1_pos = [character_1.x, character_1.y]
        
        renpy.hide_screen("racing_game_menu")
        renpy.show_screen("racing_mini_game")



init python:
    
    def character_movex(character):
        global right_key_pressed
        global left_key_pressed
        global character_1_pos

        if right_key_pressed:
            character.x += player_char_speed
            character_1_pos = [character.x, character.y]
            renpy.restart_interaction()
        
        if left_key_pressed:
            character.x -= player_char_speed
            character_1_pos = [character.x, character.y]
            renpy.restart_interaction()
    
    
    def character_move(character):
        global goal_reached
        global who_won
        global selected_character_pos
        global up_key_pressed
        global right_key_pressed
        global left_key_pressed



        if up_key_pressed:
            character_1.y -= player_char_speed
            character_1_pos = [character.x, character.y]
            renpy.restart_interaction()
    

    renpy.hide_screen("racing_game_menu")
    renpy.show_screen("racing_mini_game")

    #def npc_movement(st):
    #if not goal_reached and countdown_timer == 0:

screen countdown_timer:
    frame:
        background "#00000080"
        align(0.5, 0.5)
        xysize 400,250
        vbox:
            align(0.5, 0.5)
            text "Starting.." size 40 xalign 0.5
            text "[countdown_timer]" size 50 xalign 0.5
    
    timer 1.0 action If(countdown_timer > 1, SetVariable("countdown_timer", countdown_timer - 1), [SetVariable("countdown_timer", 0), Hide("countdown_timer")]) repeat If(countdown_timer > 1, True, False)
        ### ^this code decreases variable time by 0.01 until time hits 0, at which point, the game jumps to label timer_jump (timer_jump is another variable that will be defined later)


screen racing_mini_game:
    on "show" action Show("countdown_timer")
    key ["K_LEFT", "K_RIGHT", "K_UP"] action NullAction()
    image "background.png"

    #cire sprite

    add character_sprites

    # show player how to move

    if not player_start_move and countdown_timer == 0:
        frame:
            align(0.5, 0.3)
            xysize (600,250)
            background "#00000080"
            vbox:
                spacing 20
                align(0.5, 0.5)
                text "Right, left, up key to move" xalign 0.5
                add "arrow_keys" xalign 0.5
    
screen racing_game_menu:
    image "background.png"
    image Solid("#00000080")

    text "select a character" size 50 align(0.5, 0.1)
    
    text "Start?" size 50 align(0.5, 0.1)

    hbox:
        align (0.5, 0.4)
        spacing 10
        
        imagebutton idle "Menu/play_button_idle.png" action Function(setup_racing_game) align (0.5, 0.8)

image arrow_keys:
    zoom 0.5
    "arrow_keys_1.png"
    pause 0.5
    "arrow_keys_2.png"
    pause 0.5
    repeat
image arrow_keys:
    zoom 0.5
    "arrow_keys_1.png"

screen game_over:
    modal True
    
    frame:
        background "#00000080"
        xfill True
        yfill True
        frame:
            align(0.5, 0.5)
            xysize(500, 350)
            background Solid("#00000080")
            text "Game over!" size 50 align(0.5, 0.5)

            if who_won == character_1:
                text "You won!" size 40 align(0.5,0.5)

                                        
            textbutton "Play again" align(0.5, 0.5) action Function(reset_racing_game)



# Character sprites

default character_sprites = SpriteManager(update = npc_movement, event = character_events)
default character_1 = character_sprites.create("character_1.png")



# Character variable
default goal_xpos = 1500 #x coordiante of the finish line
default player_char_speed = 20 #speed of character

#Keypress variables
default up_key_pressed = False
default left_key_pressed = False
default right_key_pressed = False
default player_start_move = False

#other
default character_1_pos = [character_1.x, character_1.y] #Keep track of character position
default who_won = None
default goal_reached = False
default countdown_timer = 3


label start:
    call screen racing_game_menu

jeffster
Miko-Class Veteran
Posts: 520
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Re: Renpy how to start making minigame

#8 Post by jeffster »

Princesky wrote: Fri May 24, 2024 8:57 am I couldn't manage to piece together something with the code you offered, i couldn't really make out the gaps but i did find a tutorial here:

https://youtu.be/ZZsCUROxKQk

It's not what i wanted to do at all, but by following along, and cutting down on the feature i didn't want, i managed to make the code work but i've run into a dead end now and have a couple issues.
Honestly, my advice was just some example how to use Ren'Py functionality rather than pygame.

It was not a solution of any kind. Sorry. ;)

But the tutorial you mentioned doesn't seem to be a good foundation for your work either (so I don't really want to dive into that code).

For example:
global right_key_pressed
global left_key_pressed
Why would you need both right_key_pressed and left_key_pressed?
Doesn't only the last key matter, whether it's right or left or any other?

And I think instead of
global left_key_pressed
it's better to use
store.left_key_pressed
because "store" is the namespace Ren'Py offers to you, to use for variables (instead of globals).

And I think instead of renpy.pygame_sdl2.K_RIGHT you can use pygame.K_RIGHT.
Just do import pygame (like in this example of using a Creator Defined Displayable):

Code: Select all

init python:
    class InfiniteRunner(renpy.Displayable):
        def __init__(self):
            # Place initialization here

        def render(self, width, height, st, at):
            # Place drawing here

        def event(self, ev, x, y, st):
            # Process events here
            import pygame

            if ev.type == pygame.KEYDOWN:
                # A key was pressed

                if ev.key == pygame.K_RIGHT:
                    # It's Arrow Right
Anyways, the best solution for minigames IMO is to use Creator Defined Displayables (CDD):
https://renpy.org/doc/html/cdd.html

It might seem overwhelming at first, but after a few attempts to use it you might find it really simple and convenient.

See for yourself:

(A) You create CDD the size of the whole screen. And then you work with it pretty much similarly to what you would do with pygame.

(Or you can create just separate displayables as CDDs... I would rather try the whole screen, because then it's easy to scroll it etc., and CDDs are as fast as possible in Ren'Py).

(The tutorial you mentioned used sprites instead of CDDs, but sprites make sense when there are multiple runners and simple scene. For one runner and complex scene, implement that scene as CDD).

(B) There are 3 main elements of CDD, the three most important functions:

Code: Select all

__init__() # initialization
render()  # drawing
event()   # events
(1) In __init__() you set all the parameters that will be used during the minigame.

(2) In render() you draw the scene and every element in it.
(I mean, in this case the displayable is the whole scene, so you draw here everything).

You would likely run render() every frame, because the picture changes every frame.

Therefore, with CDD you will have full control of what and where to draw on the screen, for every frame.

E.g. to show the runner, you would calculate its (x, y) for the current frame, and then "blit" its picture to those coordinates (into the render of the whole screen).

Here in render() you can also calculate coordinates of other objects and process e.g. collisions (like when runner is hit by a fireball, etc).

In other words, your minigame will be mostly coded in the CDD's "render" function.

(3) In event() you process key presses and maybe some other events like runner's deaths.

For example, runner was running to the right; "arrow left" was pressed; that causes function event() to be called. In that function you check which event happened and set new direction for running. Then the next frame render function runs and shows runner running to the new direction.

...I think you could find some good tutorials for using CDDs somewhere.
If the problem is solved, please edit the original post and add [SOLVED] to the title. 8)

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot]