1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

renpy_技術メモ(2025-09-19)

Posted at

クリックゲーム

クリックして画像を切り替え.py
init python:
    import random

    clicked = False

    def random_pos(img_w=0, img_h=0):
        """画像サイズを考慮して画面内に収まるランダム座標を返す"""
        screen_w = config.screen_width
        screen_h = config.screen_height

        max_x = screen_w - img_w
        max_y = screen_h - img_h

        x = random.randint(0, max_x)
        y = random.randint(0, max_y)
        return x, y




label start:
    # 状態をリセット
    $ clicked = False

    # 関数呼び出し
    $ rx, ry = random_pos(94, 94)

    # screen に引数で渡す
    call screen click_game(rx, ry)

    if _return == "continue":
        jump start   # 自分に戻ってやり直す
    else:
        return

screen click_game(xpos, ypos):
    if clicked:
        add "03.png":
            xpos xpos
            ypos ypos
        vbox:
            xalign 0.5
            yalign 0.9
            spacing 12
            textbutton "続ける" action Return("continue")
            textbutton "終わり" action Return("end")
    else:
        imagebutton:
            idle "01.png"
            hover "02.png"
            xpos xpos
            ypos ypos
            action [
                Play("sound", "01.mp3"),
                SetVariable("clicked", True)
            ]

画面内にランダム配置したい

def random_pos(img_w=0, img_h=0):
    screen_w = config.screen_width
    screen_h = config.screen_height
    max_x = screen_w - img_w
    max_y = screen_h - img_h
    return random.randint(0, max_x), random.randint(0, max_y)

random_pos(幅, 高さ)` でランダム座標を取得できる。

変数を初期化したい

label start:
    $ clicked = False

画面を呼び出す前に、状態をリセットできる。


label から screen に値を渡したい

call screen click_game(rx, ry)

click_game screen に xpos=rx, ypos=ry として渡る。


クリックしたら画像を変えたい

if clicked:
    add "03.png"
else:
    imagebutton:
        idle "01.png"
        hover "02.png"
        action SetVariable("clicked", True)

if 分岐と SetVariable でクリック前/後を切り替える。


クリックで音を鳴らしたい

action Play("sound", "01.mp3")

Play("sound", ファイル名) で効果音を鳴らせる。


screen から値を返したい

textbutton "続ける" action Return("continue")
textbutton "終わり" action Return("end")

押したボタンの値が _return に入る。


返り値で処理を分けたい

if _return == "continue":
    jump start
else:
    return

screen で押されたボタンに応じて次の処理を決められる。


ドラッグ&ドロップ

ドラッグ&ドロップ.py
define config.mouse = {}
default dart_x = 400
default dart_y = 300
default dart_grabbed = False
default dart_offset_x = 0
default dart_offset_y = 0
default dart_shrinking = False
default dart_target_x = 0
default dart_target_y = 0

init python:
    import renpy.exports as renpy

    # Dart のサイズ(画像サイズに合わせる)
    DART_W, DART_H = 188, 188

    def grab_dart():
        mx, my = renpy.get_mouse_pos()
        # マウスが Dart の矩形内か判定
        if (store.dart_x <= mx <= store.dart_x + DART_W and
            store.dart_y <= my <= store.dart_y + DART_H):
            store.dart_offset_x = mx - store.dart_x
            store.dart_offset_y = my - store.dart_y
            store.dart_grabbed = True

    def release_dart():
        store.dart_grabbed = False
    
        # ランダムずれを決める
        offset_x = random.randint(-10, 10)
        offset_y = random.randint(0, 100)
        store.dart_target_x = store.dart_x + offset_x
        store.dart_target_y = store.dart_y + offset_y
        
        # 中間点を少し横にずらす(カーブ用)
        curve_x = (store.dart_x + store.dart_target_x) // 2 + random.randint(-50, 50)
        curve_y = (store.dart_y + store.dart_target_y) // 2 + random.randint(-125, 0)
        store.dart_mid_x = curve_x
        store.dart_mid_y = curve_y
        
        store.dart_shrinking = True

    def update_dart_pos():
        if store.dart_grabbed:
            mx, my = renpy.get_mouse_pos()
            store.dart_x = mx - store.dart_offset_x
            store.dart_y = my - store.dart_offset_y

label test_drag_like:
    call screen drag_like_screen
    return

# 縮小用 transform
transform shrink_dart(start_x, start_y, mid_x, mid_y, target_x, target_y):
    xpos start_x
    ypos start_y
    # 前半:中間地点まで
    easein 0.5 zoom 0.2 xpos mid_x ypos mid_y
    # 後半:的に到達&縮小
    easeout 0.25 zoom 0.05 xpos target_x ypos target_y


screen drag_like_screen():
    if dart_shrinking:
        add "04.png" at shrink_dart(dart_x, dart_y, dart_mid_x, dart_mid_y, dart_target_x, dart_target_y)
    else:
        add "04.png" xpos dart_x ypos dart_y


    timer 0.01 action Function(update_dart_pos) repeat True

    key "mousedown_1" action Function(grab_dart)
    key "mouseup_1" action Function(release_dart)

    vbox:
        xalign 0.5
        yalign 0.9
        text "座標 = [dart_x], [dart_y]"
        text "掴んでいる? [dart_grabbed]"
        textbutton "戻る" action Return()

変数をゲーム中に保持したい

default dart_x = 400
default dart_y = 300
default dart_grabbed = False
default dart_offset_x = 0
default dart_offset_y = 0

defaultセーブ/ロードにも対応
ゲーム全体の状態を保存するのに使う。


マウス座標を取得したい

mx, my = renpy.get_mouse_pos()

今のマウス位置 (x, y) を取得できる。


ドラッグ開始(掴んだとき)

def grab_dart():
    mx, my = renpy.get_mouse_pos()
    if (store.dart_x <= mx <= store.dart_x + DART_W and
        store.dart_y <= my <= store.dart_y + DART_H):
        store.dart_offset_x = mx - store.dart_x
        store.dart_offset_y = my - store.dart_y
        store.dart_grabbed = True

クリック位置が Dart の矩形内なら「掴んだ」状態にする。
offset を保存して画像が瞬間移動しないようにする。


ドラッグ中に追従させたい

def update_dart_pos():
    if store.dart_grabbed:
        mx, my = renpy.get_mouse_pos()
        store.dart_x = mx - store.dart_offset_x
        store.dart_y = my - store.dart_offset_y

掴んでいるときだけマウスに追従させる。

timer 0.01 action Function(update_dart_pos) repeat True

timer で 0.01 秒ごとに更新。
常時「掴んでいるかどうか」を確認できる。


ドラッグ終了(離したとき)

def release_dart():
    store.dart_grabbed = False
    offset_x = random.randint(-10, 10)
    offset_y = random.randint(0, 100)
    store.dart_target_x = store.dart_x + offset_x
    store.dart_target_y = store.dart_y + offset_y
    store.dart_shrinking = True

離したら掴んでいない状態に戻す。
ついでに「着地点(ランダムずれ)」を決める。


キー入力で掴む/離す

key "mousedown_1" action Function(grab_dart)
key "mouseup_1" action Function(release_dart)

左クリック押下で掴み、離したらリリース。


縮小しながら移動させたい

transform shrink_dart(start_x, start_y, mid_x, mid_y, target_x, target_y):
    xpos start_x
    ypos start_y
    easein 0.5 zoom 0.2 xpos mid_x ypos mid_y
    easeout 0.25 zoom 0.05 xpos target_x ypos target_y

開始 → 中間点 → 最終位置を通過する。
easein / easeout で加速・減速のニュアンスを調整。


ランダムに中間点をずらしてカーブ移動

curve_x = (store.dart_x + store.dart_target_x) // 2 + random.randint(-50, 50)
curve_y = (store.dart_y + store.dart_target_y) // 2 + random.randint(-125, 0)
store.dart_mid_x = curve_x
store.dart_mid_y = curve_y

最終位置の真ん中を基準に少しズラすことで、直線ではなく「弧を描く」動きになる。


状態を画面で分けたい

if dart_shrinking:
    add "04.png" at shrink_dart(dart_x, dart_y, dart_mid_x, dart_mid_y, dart_target_x, dart_target_y)
else:
    add "04.png" xpos dart_x ypos dart_y

dart_shrinking が True のときは transform でアニメーション。
False のときは通常表示。


1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?