mieki256's diary



2026/07/01(水) [n年前の日記]

#1 [prog] スプライトのzソートについて調べてる

2Dゲームに近い感じの描画をするプログラムで、スプライトの描画順をz値に基づいて決定する処理が気になってきた。たしか以前、love2d 関連の解説ページで目にしたような気がするのだけどググっても辿り着けない…。そもそもキーワードを思い出せない…。そういう処理ってどういう呼称がついているのだっけ…。もうちょっとググってみないと…。

2026/07/02(木) [n年前の日記]

#1 [prog] スプライトのzソートについて調べてる。その2

スプライトの描画順をz値に基づいて決定したい。

以前 love2d 関係の解説ページで目にしたような記憶があったのだけど、たぶん以下のページかな…。内容はまだ理解できてない…。

_Tutorial:Drawing Order - LOVE
_Skip list:Drawing Order - LOVE


Google Gemini にも尋ねてみたら、C言語で以下のサンプルが提示された。クイックソートとポインタ変数配列を使って描画順を得られる。

// ポインタ配列とクイックソートでzソートをする事例
// Google Gemini に作成してもらった。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SPRITE_COUNT 20

// 1. スプライトの構造体(実体)
typedef struct {
    int id;
    int z;  // 描画順(Z値)
    // X, Y座標など
} Sprite;

// 2. qsort用の比較関数
// 「Spriteへのポインタ」の配列をソートするため、引数は「Spriteへのポインタのポインタ」になります
int compare_sprites(const void* a, const void* b) {
    // void* から Sprite* のポインタへとキャストする
    Sprite* spriteA = *(Sprite**)a;
    Sprite* spriteB = *(Sprite**)b;
  
    // 1. まずはZ値で比較(昇順)
    // Z値の昇順(小さい順 = 奥から手前)に並べる
    // spriteA->z が小さければ負、大きければ正、等しければ0を返す
    if (spriteA->z != spriteB->z) {
        return (spriteA->z - spriteB->z);
    }
    
    // 2. Z値が同じならIDが小さい方を優先して返す(描画順の固定、チラつき防止)
    return (spriteA->id - spriteB->id);
}

int main() {
    srand((unsigned int)time(NULL));

    // スプライトの実体を一括確保
    Sprite sprites[SPRITE_COUNT];
    for (int i = 0; i < SPRITE_COUNT; i++) {
        sprites[i].id = i + 1;
        sprites[i].z = rand() % 100; // 0 - 99のランダムなZ値
    }

    // 描画順を管理するための「ポインタの配列」を用意する
    Sprite* draw_pointers[SPRITE_COUNT];
    
    // 初期化:まずはスプライトの実体の住所(ポインタ)をそのままコピー
    for (int i = 0; i < SPRITE_COUNT; i++) {
        draw_pointers[i] = &sprites[i];
    }

    // クイックソートを実行(draw_pointers の中身だけがZ値順に並び替わる)
    // 引数: (ソートする配列, 要素数, 1要素のサイズ, 比較関数)
    qsort(draw_pointers, SPRITE_COUNT, sizeof(Sprite*), compare_sprites);

    // 描画処理のシミュレーション(ポインタ配列を頭から順に回すだけ)
    printf("--- 描画実行(ポインタ配列+qsort) ---\n");
    for (int i = 0; i < SPRITE_COUNT; i++) {
        // draw_pointers[i] には、次に描画すべきスプライトの住所が入っている
        printf("[%02d番目に描画] Sprite ID: %02d (Z値: %02d)\n", 
               i + 1, draw_pointers[i]->id, draw_pointers[i]->z);
    }

    return 0;
}

Windows11 x64 25H2上で、MSYS2 の gcc を使ってコンパイルしてみた。
gcc -o zsort_sample_qsort zsort_sample_qsort.c

実行結果は以下。
> zsort_sample_qsort.exe
--- 描画実行(ポインタ配列+qsort) ---
[01番目に描画] Sprite ID: 18 (Z値: 02)
[02番目に描画] Sprite ID: 08 (Z値: 04)
[03番目に描画] Sprite ID: 04 (Z値: 14)
[04番目に描画] Sprite ID: 07 (Z値: 19)
[05番目に描画] Sprite ID: 14 (Z値: 19)
[06番目に描画] Sprite ID: 12 (Z値: 22)
[07番目に描画] Sprite ID: 17 (Z値: 23)
[08番目に描画] Sprite ID: 19 (Z値: 29)
[09番目に描画] Sprite ID: 13 (Z値: 31)
[10番目に描画] Sprite ID: 02 (Z値: 34)
[11番目に描画] Sprite ID: 20 (Z値: 36)
[12番目に描画] Sprite ID: 16 (Z値: 39)
[13番目に描画] Sprite ID: 10 (Z値: 45)
[14番目に描画] Sprite ID: 01 (Z値: 46)
[15番目に描画] Sprite ID: 05 (Z値: 47)
[16番目に描画] Sprite ID: 09 (Z値: 60)
[17番目に描画] Sprite ID: 15 (Z値: 61)
[18番目に描画] Sprite ID: 03 (Z値: 89)
[19番目に描画] Sprite ID: 11 (Z値: 91)
[20番目に描画] Sprite ID: 06 (Z値: 95)

たしかに、z値の小→大の順で結果が得られてる。

ただ、この方法だとスプライト枚数が増えた時に処理時間がかかってしまいそうな気もするのだけど…。AI (Google Gemini) は「C言語のクイックソート使ってるから全然大丈夫ッスよ」と言ってるけれど…。いやまあ、処理時間を測定してみないとなんとも言えないけれど…。

AI曰く、「z値が整数値で、取り得る値の範囲がそれほど広くないなら、オーダリングテーブル(Ordering Table)がオススメ」とも言ってきた。そうだった…。プレステ1で使ってたよな…。キーワード自体をすっかり忘れてた…。

ググったら、有名なゲームプログラマーさんがわざわざ解説してくれていた。ありがたや。

_オーダリングテーブル : プログラミング指南 - Code Knowledge

#2 [anime] 「劇場版 幼女戦記」劇場版を視聴

BS11で放送されていたので視聴。ライトノベルを原作とするTVアニメの劇場版。

ググってみたら2019年の公開だったらしい。TVアニメ1期と2期の間を埋める内容だろうか。今月から2期が放送開始されるので、それに合わせて復習/履修/宣伝を兼ねた放送なのだろう…。これを見ておかないと2期の内容が分からないということでもあるのかな。

空中戦闘シーンのカメラワークが派手派手で、これを劇場の大スクリーンで見たら迫力がありそうだなと…。

ライバルキャラ?の登場で、更に戦闘が派手派手になった印象を受けた。今後もずっと配置されて活躍するキャラなのだろう…。

TVアニメ1期を視聴してること前提の構成ではあったけれど、作画クオリティは高いし、アクションシーンも多いしで、これならファンも満足しそうだなと…。

2026/07/03(金) [n年前の日記]

#1 [prog] Emacs系エディタ用のコメント行の名称が分からない

テキストエディタの xyzzy や Emacs は、ソースファイルの最初のあたりにコメント行で色々書いておくと、そこで指定したメジャーモードや文字エンコーディングでそのファイルを開いてくれる機能がある。以下のような感じのコメント行で…。

#!python
# -*- mode: python; Encoding: utf-8; coding: utf-8 -*-
# Last updated: <2026/07/07 21:25:17 +0900>

この、2行目3行目を、何と呼べばいいのかわからないなと…。

ググったところ、「モードライン」と呼んでる場合もあったけれど…。エディタ画面の下のほうにある、現在のモードを表示している行もモードラインと呼ばれることがあるようで…。

「マジックコメント」という呼び方も見かけた。どうやら Ruby あたりから始まった呼び方のようで、今では色々な言語でもその呼び方が使われている、とAIは言っていたけれど。Emacs系エディタの世界ではマジックコメントという呼び名はそもそも使ってなかったそうで…。

このあたりのコメント行は、一体どう呼べばいいのだろう…。

いやまあ、今時フツーのプログラマーはソース書く時に Emacs系エディタは使わんやろ、Visual Studio Code か vim あたりを使うんじゃないの? という気もするので、今更どうでもいい気もするのだけど。

ただ、今回、どういう記述をすればいいのか忘れてしまって、ちょっとググろうとした時に名称が分からなくて困ったという…。

余談。xyzzyに関数を追加してた :

xyzzy の siteinit.l に、このあたりの文字列を挿入する関数を追加していたことを忘れていた。

;; 文字コード判別用の文字列を挿入
(defun insert-my-coding-check-string-utf8n()
  (interactive)
  (insert "-*- mode: <ModeString>; Encoding: utf-8; coding: utf-8 -*-"))

(defun insert-my-coding-check-string-sjis()
  (interactive)
  (insert "-*- mode: <ModeString>; Encoding: sjis; coding: sjis -*-"))

M-x insert-my-coding-check-string-(utf8n|sjis) で挿入できる、とメモしておくけれど明日には忘れてそう…。M-x insert-m まで打って補完、ぐらいは覚えておきたいけれど…。

#2 [pygame] pygameをWebブラウザ上で動かせるpygbagを試用

Python で2Dゲームを作れる、pygame というモジュール/ライブラリがある。ローカル環境で動かすことが前提のライブラリだけど、pygbag というツール? モジュール? を利用すると、pygame を利用しているスクリプトをWebブラウザ上でも動かせると知ったので試用してみることにした。

環境は Windows11 x64 25H2 + Python 3.10.10 64bit + pygame-ce 2.5.6。CPU : AMD Ryzen 5 5600X。GPU : NVIDIA GeForce GTX 1060 6GB。

インストール :

インストールは以下。
pip install pygbag
or
python -m pip install pygbag

今回は pygbag 0.9.3 がインストールされた。

スクリプトを修正 :

pygameを使ったスクリプトは、そのままでは pygbag 用にならないので、ほんのちょっとだけ修正が必要らしい。以下を参考にして修正。

_【pygbag】「たった10分で」pygameをブラウザ上で動かす! #Python - Qiita

以下を修正すればいいのかな…?
  • スクリプト名は main.py にしておく。
  • スクリプトや画像の類は任意のフォルダに入れておく。
  • import asyncio を最初のあたりに追加。
  • def main(): を async def main(): に変更。
  • clock.tick() の直後に await asyncio.sleep(0) を追加。
  • main関数を asyncio.run(main()) で呼び出すように変更。

pygbagで変換 :

pygbag を呼び出して、Webブラウザで実行できる状態に変換する。スクリプトが入っているフォルダと同階層で以下を打つ。
python -m pygbag フォルダ名

変換終了後、Webサーバが実行されて待ち状態になるので、Webブラウザで http://localhost:8000/ にアクセスすれば、pygameスクリプトをWebブラウザで実行できる。

終了はコマンドプロンプト上で Ctrl + C。

Webサーバに公開 :

フォルダ名\build\web\ の中に公開用のファイル群一式が入っている。今回は以下が入っていた。これをWebサーバ上にアップロードすればいいのだろう…。
favicon.png
hellopygbag.apk
hellopygbag.tar.gz
index.html

Webサーバが Apache の場合、かつ、このあたりのファイル種類について設定がされてない場合は、.htaccess でファイル種類を指定する必要があるかもしれない。
AddType application/wasm .wasm
AddType application/octet-stream .data
AddType application/octet-stream .apk

.gz が x-gzip に割り当てられてない場合は以下の記述も必要、とAI (Google Gemini)が言っている。自分の環境では指定しなくても動いてくれた。おそらく Apache2 全体の設定で既に指定されているのだろう…。
<IfModule mod_mime.module>
    AddEncoding x-gzip .gz
</IfModule>

AIは、キャッシュを使わないようにする設定も提示してきたけれど、その指定は必要なのかな…。

サンプル :

Webサーバに置いてみたけれど、実行できるだろうか…。

_pygbag sample

ページを開いて、ロードが終わると、Firefoxの場合は「準備できたからタッチせよ」と英文で言ってくるのでページをクリックすれば動く。はず。動くといいなあ…。Google Chrome の場合は、ロードが終わればそのまま実行開始になった。

Firefox 152.0.4、Google Chrome 150.0.7871.4上では動いてくれた。手元の環境、CPU : AMD Ryzen 5 5600X、GPU : NVIDIA GeForce GTX 1060 6GB 上では結構滑らかに動いている。

ソースと画像は以下。 AI(Google Gemini) に作成してもらった。このくらいのスクリプトなら一発で生成してくれるのね…。

_main.py
_image.png

#3 [pc][prog] ripgrepをインストールしてみた

Windows11 x64 25H2上で ripgrep なるツールをインストールしてみた。AI(Google Gemini)によると、Rustで書かれた爆速のgrep、らしい。バイナリファイルを除外したり、色付けされたりするらしい。VSCode(Visual Studio Code)でも使われているのだとか。

_【捜索生活向上1】ファイル検索ツール「ripgrep」を利用して、俊足かつ効率的に見つけ出す。 初心者 - Qiita

今回は choco (Chocolatey)経由でインストールした。管理者権限でコマンドプロンプトを開いて、以下を打った。
choco install ripgrep

rg.exe というのが ripgrep のコマンド名らしい。以下の場所にインストールされた。
> which rg
"C:\ProgramData\chocolatey\bin\rg.exe"

AI(Google Gemini)によると、以下のような使い分けがいいだろうとのこと。

元々、VSCodeの拡張の todo-tree が、「ripgrepが見つからないから手動でインストールせよ」と言ってきたので今回インストールしてみたけれど、たしかに VSCode のインストール場所を探したら rg.exe が入っていた。VSCode も使っているというのはおそらく本当らしい。ちなみに以下の場所に入っていた。
C:\Users\(USERNAME)\AppData\Local\Programs\Microsoft VS Code\4fe60c8b1c\resources\app\node_modules\@vscode\ripgrep-universal\bin\win32-x64\rg.exe

choco経由版をアンインストールした :

zipで入手できる版があると知った。

_Releases - BurntSushi/ripgrep

こちらを使うことにしよう…。ripgrep-15.1.0-x86_64-pc-windows-msvc.zip を入手して解凍。中に入ってる rg.exe をパスの通った場所に置く。今回は D:\home2\bin\ 以下に置いた。

> rg --version
ripgrep 15.1.0 (rev af60c2de9d)

features:+pcre2
simd(compile):+SSE2,-SSSE3,-AVX2
simd(runtime):+SSE2,+SSSE3,+AVX2

PCRE2 10.45 is available (JIT is available)

choco経由でインストールした版はアンインストールした。
choco uninstall ripgrep

2026/07/04() [n年前の日記]

#1 [windows] 画像ビューワ mImageViewer を試用

mImageViewer という画像ビューワがあると知った。

_mImageViewer - 高速画像ビューワー for Windows

Rust言語で作成されたアプリで、一般的な画像ビューワとしての機能を持っている上に、画像生成AIで生成した画像に記録されているメタデータ(プロンプト・タグ)を表示することもできるらしい。気になる。Windows11 x64 25H2上で試用してみることにした。

インストール :

インストーラ版やポータブル版が用意されているので、今回はポータブル版を利用させてもらった。mImageViewer_portable_v2.2.0.zip を入手して解凍。任意のフォルダに置いて、mimageviewer.exe を実行すれば起動する。今回は D:\home2\bin\ViX\mImageViewer_portable\ にインストールしておいた。

初回起動時に、AIを使うかどうかの選択がある。画像をフルスクリーン表示する際、AIを使ってノイズ除去やアップスケールをしながら表示することができるのだとか。

ただ、AI云々はGPUを使って処理をするのだろうし、画像生成AI(Stable Diffusion web UI)を動かしながら利用するとVRAMの奪い合いが起きそうなので今回は何の処理もしない設定にしておいた。

感想 :

サムネイル表示はかなり速い気がする…。Rust製アプリだから、なのだろうか…?

画像内のメタデータをどうやって確認したらいいのか分からなくて悩んだけれど、画像をフルスクリーン表示にして、マウスカーソルを画面の右のほうに持っていったらメタデータが表示された。コピーボタンも用意されているあたりは助かる。

また、メタデータ以外にも、各種処理を行うためのUIも表示される模様。非破壊編集までできると謳われてる…。実に今風…。

かなりイイ感じのビューワではなかろうか…。

ただ、フルスクリーン表示する際、画像の拡大縮小アルゴリズムを選べたらなあ、とも思ったけれど、そのあたりはAIを利用したアップスケールで代替可能と判断されてもおかしくはないのかも…。

2026/07/06追記 :


2026/07/05() [n年前の日記]

#1 [nitijyou] 体調がよろしくない

お腹を壊した感じがする…。何度もトイレに駆け込んでる…。

飲んでるジュースのせいだろうか? 塩が入ってると謳うジュースを飲むと腹の調子が悪くなるような気も…。塩が入ってると水分の吸収が早まるという話を聞いた記憶もあるけれど、その代わり胃腸にダメージを与えるのではなかったかな…。だから経口補水液は日常的にガブガブ飲んだらダメ、とかなんとか…。

でもそんなことを言ってたら味噌汁はどうなってしまうのだろう? アレも塩分たっぷりなのでは…。実は毎日味噌汁を飲んでいると胃腸がダメージを受けてたりするのかな…。

2026/07/06(月) [n年前の日記]

#1 [prog] スプライトのzソートについて調べてる。その3

スプライトの描画順をz値に基づいて決定したい。

プレステ1の頃に使っていたオーダリングテーブル(ot, Ordering table)について調べてた。当時は当たり前のように使ってたけど、かなり昔のことなのですっかり忘れてる…。

以下のpdfが分かりやすかった。

_Tech Note\Ordering Table Primer - ordtbl.pdf

配列の中に、otの次の場所を示すポインタ、もしくは描画プリミティブの情報が入ってる場所のポインタを入れて、値が 0xffffff なら終了、という仕組みだったらしい。

もっとも、この仕組みの肝は、z値を整数値にして、z値の範囲分の配列を作っておけば、ソート処理不要で描画順を登録できるあたりだろうから…。ポインタ云々は当時C言語で書いていたからそうしていただけで、今時の言語であればもっと分かりやすい記録/登録の仕方ができそうな気もする。

2026/07/07(火) [n年前の日記]

#1 [prog] スプライトのzソートについて調べてる。その4

スプライトの描画順をz値に基づいて決定したい。

AI (Google Gemini) に、Python + pygame でオーダリングテーブル(ot, Ordering table)の処理をするサンプルを作ってもらった。

サンプル1 :

矩形で塗り潰すだけの複数のオブジェクトを生成して、z値に応じてオーダリングテーブルで描画順を決めるサンプルスクリプト。

_01_ot_sample1_main.py
"""
Ordering Table のサンプル(pygbag対応 + マウスクリック + Z値連動色変化版)

Windows11 x64 25H2 + Python 3.10.10 64bit + pygame-ce 2.5.7
"""

import asyncio
import random
import sys
import pygame

# 画面サイズと設定
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60

# オーダリングテーブルの最大サイズ(Z値の範囲: 0 〜 99)
MAX_Z_LAYERS = 100


class CustomSprite:
    """独自のZ値を持つゲームオブジェクト"""

    def __init__(self, x, y, width, height, z):
        self.rect = pygame.Rect(x, y, width, height)
        self.z = z  # 浮動小数点数などの任意の数値

        # --- Z値(0.0?99.9)に応じて色を計算 ---
        # 0.0で128、99.9で約32になるように補間
        ratio = z / 100.0
        color_val = int(192 - (160 * ratio))
        self.color = (color_val, color_val, color_val)

    def draw(self, surface, font):
        # 描画処理(わかりやすいようにZ値もテキストで表示)
        pygame.draw.rect(surface, self.color, self.rect, 0)

        # 枠線描画
        pygame.draw.rect(surface, pygame.Color(255, 255, 255, 255), self.rect, 2)

        text = font.render(f"Z: {self.z:.1f}", True, (255, 255, 255))
        surface.blit(text, (self.rect.x + 5, self.rect.y + 5))


async def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption("Ordering Table Draw System")
    clock = pygame.time.Clock()

    font = pygame.font.Font(None, 24)

    initfg = True

    # メインループ
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
                elif event.key == pygame.K_q:
                    running = False
                elif event.key == pygame.K_r:
                    initfg = True
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    initfg = True

        if initfg:
            # ----------------------------------------
            # 1. オブジェクトの生成
            # ----------------------------------------
            sprites = []
            for _ in range(15):
                x = random.randint(100, 600)
                y = random.randint(100, 400)
                z = random.uniform(0.0, 99.9)
                # colorの指定を無くし、内部でZ値から自動計算するように変更
                sprites.append(CustomSprite(x, y, 100, 100, z))

            initfg = False

        # 画面クリア
        screen.fill((0, 0, 0))

        # -------------------------------------------------------------
        # 2. オーダリングテーブルの初期化
        # -------------------------------------------------------------
        ordering_table = [[] for _ in range(MAX_Z_LAYERS)]

        # -------------------------------------------------------------
        # 3. オブジェクトを整数値に変換したZ値のレイヤーに登録
        # -------------------------------------------------------------
        for sprite in sprites:
            z_index = int(sprite.z)
            z_index = max(0, min(z_index, MAX_Z_LAYERS - 1))
            ordering_table[z_index].append(sprite)

        # -------------------------------------------------------------
        # 4. オーダリングテーブルに基づいて奥から一気に描画
        # -------------------------------------------------------------
        for z_layer in reversed(ordering_table):
            for sprite in z_layer:
                sprite.draw(screen, font)

        pygame.display.flip()
        clock.tick(FPS)

        await asyncio.sleep(0)

    pygame.quit()
    sys.exit()


if __name__ == "__main__":
    asyncio.run(main())

pygbag を使って、Webブラウザ上でも実行できるようにした。マウスクリック、もしくはRキーで、オブジェクトを生成し直す。

_01_ot_sample1

z値の大小で描画順が決定されてることが分かる。

サンプル2 :

先日作成した、 _スプライトが球状に描画されるスクリプト を、オーダリングテーブルで処理するようにしてみた。

_image.png
_02_ot_sample2_main.py
"""
スプライトで球を表示するサンプル(オーダリングテーブル版・半径可変モデル)。
Google Gemini に作ってもらった。

Windows11 x64 25H2 + Python 3.10.10 64bit
"""

import pygame
import sys
import math
import asyncio

# 初期設定
pygame.init()
WIDTH, HEIGHT = 1280, 720
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("3D Point Cloud Sphere with Sprites (Ordering Table)")
clock = pygame.time.Clock()

# --- 球体上の点群(3D座標)を生成 ---
NUM_POINTS = 256
BASE_RADIUS = 300  # 基準となる半径
PULSE_AMPLITUDE = 200  # 半径の振り幅

# 最初は半径 1.0 の単位球として座標を保持しておくと、後から半径を掛け算しやすくなります
base_points = []
phi = math.pi * (math.sqrt(5.0) - 1.0)

for i in range(NUM_POINTS):
    y = 1.0 - (i / float(NUM_POINTS - 1)) * 2.0
    radius_at_y = math.sqrt(1.0 - y * y)
    theta = phi * i
    x = math.cos(theta) * radius_at_y
    z = math.sin(theta) * radius_at_y
    # 単位球の座標として格納
    base_points.append([x, y, z])

# --- オーダリングテーブルの設定 ---
TABLE_SIZE = 200  # 解像度(バケツの数)


async def main():
    # 画像の読み込み
    try:
        sprite_image = pygame.image.load("./image.png").convert_alpha()
    except Exception:
        print("image.png が見つからないため、仮のスプライトを作成します。")
        sprite_image = pygame.Surface((32, 32), pygame.SRCALPHA)
        pygame.draw.circle(sprite_image, (255, 0, 0), (16, 16), 16)
        pygame.draw.circle(sprite_image, (255, 255, 255), (12, 12), 4)

    SPRITE_W, SPRITE_H = sprite_image.get_size()
    angle_y = 0
    angle_x = 0
    angle_radius = 0  # 半径変化用のラジアン値

    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
                elif event.key == pygame.K_q:
                    running = False

        # 画面のクリア
        screen.fill((15, 15, 15))

        # アニメーション速度
        angle_y += 0.015
        angle_x += 0.001
        angle_radius += 0.01  # 半径が変化するスピード(好みに応じて調整)

        # --- 現在のフレームの半径を計算 ---
        # BASE_RADIUS を中心に、±PULSE_AMPLITUDE の範囲で波打つ
        current_radius = BASE_RADIUS + math.sin(angle_radius) * PULSE_AMPLITUDE

        # --- オーダリングテーブルの初期化 ---
        ordering_table = [[] for _ in range(TABLE_SIZE)]

        # 3次元回転と座標変換、およびテーブルへの登録
        for pt in base_points:
            # 単位球の座標に、現在のフレームの半径を掛け合わせる
            x = pt[0] * current_radius
            y = pt[1] * current_radius
            z = pt[2] * current_radius

            # Y軸周りの回転
            cos_y, sin_y = math.cos(angle_y), math.sin(angle_y)
            x1 = x * cos_y - z * sin_y
            z1 = x * sin_y + z * cos_y

            # X軸周りの回転
            cos_x, sin_x = math.cos(angle_x), math.sin(angle_x)
            y2 = y * cos_x - z1 * sin_x
            z2 = y * sin_x + z1 * cos_x

            # --- Z値をテーブルのインデックスに変換 ---
            # z2 はおおよそ -current_radius から +current_radius の範囲。
            norm_z = (z2 + current_radius) / (2 * current_radius)

            # 念のため範囲外をクリップ
            table_idx = int(norm_z * (TABLE_SIZE - 1))
            table_idx = max(0, min(TABLE_SIZE - 1, table_idx))

            # 画面座標の計算
            screen_x = int(x1 + (WIDTH // 2) - (SPRITE_W // 2))
            screen_y = int(y2 + (HEIGHT // 2) - (SPRITE_H // 2))

            # テーブルの該当する深度のバケツに追加
            ordering_table[table_idx].append((screen_x, screen_y))

        # --- 描画処理 (奥から手前へ) ---
        for bucket in ordering_table:
            for screen_x, screen_y in bucket:
                screen.blit(sprite_image, (screen_x, screen_y))

        # 画面更新
        pygame.display.flip()

        clock.tick(60)
        await asyncio.sleep(0)

    pygame.quit()
    sys.exit()


if __name__ == "__main__":
    asyncio.run(main())

これも pygbag でWebブラウザ上でも動かせるようにしてみた。

_02_ot_sample2

只のソート処理でも良さそう :

ここまで試しておいてアレだけど…。実は只のソート処理でも良さそうな気配があって…。

先日、 _C言語で作ったzソート処理をするサンプル では、4096個のスプライト相当をz値でクイックソートしても、CPU : Ryzen 5 5600X の環境なら 0.0005 - 0.0006 秒しかかからないようで…。60FPSなら1フレームの時間が 1/60 秒 = 0.0166667秒 だけど、1/27 とか 1/33 程度の処理時間でソート処理が終わってしまう。

2Dゲームを今時のハードウェア上で動かす分には、クイックソートで処理しちゃっても十分なのかもしれない…。非力なCPU上で動かすとか、もっと膨大なスプライト枚数を管理するなら話は違うのかもしれないけれど…。

#2 [rust] RustをWindows11にインストールしておいた

プログラミング言語の Rust を Windows11 x64 25H2 にインストールしておいた。今回は Rust 1.96.1 がインストールされた。

一旦 rustup self uninstall でアンインストールしてから、rustup-init.exe を実行してインストールした。

作業手順については以前メモしてあった。

_mieki256's diary - Rustで使えるGUIライブラリを調べてる
_mieki256's diary - RustをWindows10にインストール
_mieki256's diary - RustをWindows10にインストール

利用するには C++コンパイラが必要らしいけど、Visual Studio Community 2022 をインストールしてある環境だからそのあたりはクリアしているだろう…。たぶん。

インストール場所を変更したいので、環境変数を指定しておく。事前に環境変数を指定しておくと、その場所にインストールしてくれるらしい。
入手した rustup-init.exe 64bit版を実行すると以下のメッセージが表示された。

warn: It looks like you have an existing rustup settings file at:
warn: D:\Rust\.rustup\settings.toml
warn: Rustup will install the default toolchain as specified in the settings file,
warn: instead of the one inferred from the default host triple.

Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  D:\Rust\.rustup

This can be modified with the RUSTUP_HOME environment variable.

The Cargo home directory is located at:

  D:\Rust\.cargo

This can be modified with the CARGO_HOME environment variable.

The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:

  D:\Rust\.cargo\bin

This path will then be added to your PATH environment variable by
modifying the PATH registry key at HKEY_CURRENT_USER\Environment.

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

urrent installation options:


   default host triple: x86_64-pc-windows-msvc
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with standard installation (default - just press enter)
2) Customize installation
3) Cancel installation
>

1を選択してインストール処理を進める。色々なファイルがダウンロードされてインストールされていく。

rustc 1.96.1 がインストールされた、と表示された。

Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload its PATH environment variable to include
Cargo's bin directory (D:\Rust\.cargo\bin).

Press the Enter key to continue.

Enterを叩けばコンソールが終了して、環境変数PATHに cargo関連ツールのパスが追加される。ユーザ側の環境変数 PATH に追加された模様。追加というか、PATH の一番最初に挿入されてるけれど…。

インストール場所やバージョンを確認。
> where cargo
D:\Rust\.cargo\bin\cargo.exe

> where rustup
D:\Rust\.cargo\bin\rustup.exe

> cargo --version
cargo 1.96.1 (356927216 2026-06-26)

> rustup --version
rustup 1.29.0 (28d1352db 2026-03-05)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: the currently active `rustc` version is `rustc 1.96.1 (31fca3adb 2026-06-26)`

2026/07/08(水) [n年前の日記]

#1 [xyzzy] xyzzyにRustモードを追加したかった

Rustの勉強を始めてみたけれど、普段使ってるテキストエディタ、xyzzy 0.2.2.253 を Rust に対応させたくなった。色分け表示してくれるだけでもありがたいのだけど…。

ググったところ以下のページを見かけて喜んだのだけど…。

_okayu3/xyzzy-rust-mode: A major mode for Rust programming language of xyzzy editor(another emacsen editor)


しかし、(load-library "rust-mode") をしただけで以下のエラーが表示されてしまって悩んだ。
変数が定義されていません: editor::*rust-mode-map*」

原因は文字コードだった…。

最初、rust-mode.l をそのままバイトコンパイルせずに使おうとしたので気づかなかった。試しにバイトコンパイルしようとしたらエラーが表示されたので、そこでやっと気づいた…。公開されているファイルの文字コードがutf-8になっていたので sjis、CRLF で保存し直したところ、バイトコンパイルも通ったし、(load-library "rust-mode") もエラーが出なくなった。

ただ、119行あたりに、よく分からないコントロールコードが入っているようにも見える…。gihub上で見るとコントロールコードは表示されていないけれど、zipで入手して解凍して rust-mode.l を取り出すとコントロールコードが入っていることが分かる。これはこのままでもいいのだろうか…。

#2 [prog] MeryにRust用構文ファイルを追加した

テキストエディタ Mery にもRust用構文ファイルを追加しておいた。色分け表示してくれるだけでもありがたい。

_構文ファイル - MeryWiki
「表示」メニューの「編集モード > 編集モードの設定 > プロパティ」の下部にある「インポート」ボタンで "msy" ファイルをインポートして使用します。

_Rust - MeryWiki

記述されてる内容を rust.msy としてテキスト保存。表示 → 編集モード → 編集モードの設定。Rust を新規作成してプロパティをクリック。インポートで rust.msy を選択して読み込む。拡張子に rs を指定。

2026/07/09(木) [n年前の日記]

#1 [nitijyou] 暑い

気温32度。暑い…。

明日は34度ぐらいになるらしい…。

#2 [python] opencv-pythonをインストールした

ちょっと実験をしたくて、Windows11 x64 25H2 + Python 3.10.10 x64上で、opencv関係のモジュールをインストールした。既に入っていたけれど最新版にアップデート。

python -m pip uninstall opencv-python opencv-python-headless -y
python -m pip install opencv-python opencv-python-headless opencv-contrib-python -U

numpyのバージョンが変わってしまって、他のモジュールに影響を与えてしまった…。

RROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
pgzero 1.2.1 requires pygame~=2.0, which is not installed.
rembg 2.0.59 requires opencv-python-headless, which is not installed.
numba 0.60.0 requires numpy<2.1,>=1.22, but you have numpy 2.2.6 which is incompatible.


numba をアップデートしたら、numpy 2.2 も利用できる状態になった。

python -m pip install numba -U

> py --version
Python 3.10.10

> py -m pip list | grep opencv
opencv-contrib-python     5.0.0.93
opencv-python             5.0.0.93
opencv-python-headless    5.0.0.93

> py -m pip list | grep numba
numba                     0.66.0

#3 [python] pgzeroをデフォルト環境からアンインストールした

今まで Windows11 x64 25H2 + Python 3.10.10 x64上で、pygame をより簡単に使えるようにする pgzero (Pygame Zero) をインストールしてあったのだけど。

_Pygame Zero へようこそ - Pygame Zero 1.2 ドキュメント
_pgzero - PyPI

pgzero が pygame を要求してしまう。今現在、手元の環境では pygame ではなく pygame-ce を利用しているので、pgzero の扱いがちょっと面倒臭い。

今後も利用頻度は少ないだろうし、仮想環境を作成して、pgzero を利用したい時は仮想環境を使って利用することにした。

デフォルト環境から pgzero をアンインストール。
python -m pip uninstall pgzero

venvディレクトリを作成して、その中に仮想環境を用意した。
python -m venv venv

venv\Scripts\activate.bat を実行して仮想環境を有効にする。
venv\Scripts\activate

pgzero をインストール。pygame、numpy もインストールされる。
python -m pip install pgzero

以下のモジュールが入ってる状態になった。
> python -m pip list
Package    Version
---------- -------
numpy      2.2.6
pgzero     1.2.1
pip        26.1.2
pygame     2.6.1
setuptools 65.5.0

仮想環境から抜ける時は deactivate と打つ。

2026/07/10(金) [n年前の日記]

#1 [nitijyou] 今日も暑い

気温34度。暑い…。

気温が上がらないうちに犬の散歩をすべく日の出とほぼ同時に家を出て朝の犬の散歩はどうにかなったけれど。夕方、日が沈むか沈まないかの時間でも気温30度…。

#2 [python] Python+opencvを試してた

以下の記事が気になったので手元でも動作確認。Windows11 x64 25H2 + Python + python-opencv でアレコレ動かしてた。

_描画した線をつまんで編集できる、CLIP STUDIOのようなベクターレイヤーを実装する Python - Qiita

> py -m pip list | grep -E "opencv|numpy"
numpy                     2.2.6
opencv-contrib-python     5.0.0.93
opencv-python             5.0.0.93
opencv-python-headless    5.0.0.93

間引きアルゴリズム :


2026/07/11() [n年前の日記]

#1 [cg_tools] Synfig Studio 1.5.5 dev をインストール

無料で利用/寄付募集のアニメ制作ソフト Synfig Studio 1.5.5 dev が 2026/03 頃に公開されていたと知ったので入手してインストールしておいた。環境は Windows11 x64 25H2。

_Synfig - Free and open-source animation software
_Releases - synfig/synfig

今回は Portable版(?)をインストール。Windows x64版の SynfigStudio-1.5.5-2026.03.15-win64-79bf7.zip を入手して解凍。今回は D:\Prog\SynfigStudio-1.5.5-2026.03.15-win64-79bf7_portable\ にコピーしてインストールしておいた。

synfigstudio.bat を実行すると起動する。初回起動時は何かの処理をしているのか、数分待たされる…。そのまま放置して別の作業をしていたら、そのうちウインドウが表示された。

少し触ってみようとしたけれど、使い方を忘れている…。

2026/07/12() [n年前の日記]

#1 [cg_tools] 画面分割をするプロンプトを試してる

画像生成AI Stable Diffusion web UI Forge - Neo + Anima を動かしてたら、たまたま何かの拍子に画面分割されたレイアウトの生成結果が出てきて、これはこれでなんだか面白いなと関連するタグをググって試しているところ。

期待した結果が出てこない。境界線で完全に画面を分割して、別々の視点で内容を生成したいと思っているのだけど、オブジェクトが混ざって前後に位置してるようなレイアウトになってしまったり、背景がどちらも共通のものになってしまったりする。multiple views, split view だけでは足りないのかな…。comic panel や 2koma, 3koma 等も入れてみたけど期待した結果にならない。結局、Photopea で境界線を入れたり背景を黒く塗りつぶしてi2iで生成し直してどうにかすることに…。なかなか難しい…。

2026/07/13(月) [n年前の日記]

#1 [cg_tools] リファレンス用ビューアをいくつか試用

Windows11 x64 25H2上で、リファレンス画像用ビューアをいくつか試用。

余談。ビューア、ビューアー、ビューワ、一体どの表記が正しいのやら…。いや、どれでもいいらしいけど…。

_【禁断の語尾】「ビューア」か「ビューアー」か、それが問題だ。|さとっくすぽち

PureRefを試用 :

_PureRef

有名なリファレンス画像用ビューア。寄付歓迎のアプリだろうか。今回は試用のつもりなので$0を入力して入手してみた。

ポータブル版らしい PureRef-2.1.3_x64.zip をダウンロードして解凍。今回は D:\home2\bin\ViX\PureRef_2.x.x_Portable\ 以下にコピー。

PureRef.exe を実行すると起動する。

  • 開いたウインドウに画像をドラッグアンドドロップすれば画像を閲覧することができる。
  • 一つ一つの画像を任意の大きさにして配置したり、全選択して整列して並べたりできる。
  • 基本的には右クリックでメニューが表示されるので、その中からやりたいことを選べばいい。

BeeRefを試用 :

_BeeRef | A Simple Reference Image Viewer
_rbreu/beeref: BeeRef Reference Image Viewer

PureRef に似ている感じのビューア。github でソースが公開されている。BeeRef-0.3.3.exe を入手。今回は D:\home2\bin\ViX\BeeRef\ に置いた。

実行したらセットアップが始まるのかなと思ったけれどそうではなかった。.exe を実行するだけでウインドウが開いて、そのまま使い始めることができる。どうやら Python で作られていて、Pyinstaller で1ファイルにexe化してある模様。ということは一旦テンポラリフォルダに解凍されて、そちらから起動してるのかな…?

各画像を回転して表示することができるあたりが特徴なのだろうか。

Butterfly Viewerを試用 :

_olive-groves/butterfly_viewer: Side-by-side image viewer with synchronized zoom and sliding overlays. Drag and drop to instantly compare multiple images on your desktop. Very open source.
_butterfly_viewer Documentation

4つまでの画像を表示して、同じ位置に表示しながら違いを確認できるビューア。Python + PyQt5 で実装されているらしい。

butterfly_viewer_v1.1_win64_setup.exe.zip を入手して解凍するとセットアップファイルが入ってる。今回は D:\Prog\Butterfly Viewer\ にインストールした。

butterfly_viewer.exe を実行すると起動する。

ウインドウの中央に画像をドラッグアンドドロップするだけで画像が表示されるけど、左上に画像をドラッグアンドドロップする場所が4つ用意されていて、そこにドラッグアンドドロップしてやれば画像の比較ができる。画像を指定してから Create をクリックすれば、画像がウインドウ内に表示される。ウインドウ内でマウスカーソルを動かせば、その位置で画面が分割され、2〜4つの画像がそれぞれの領域に表示されるので、内容の違いを確認することができる。

参考ページ :

#2 [nitijyou] また目が見えなくなった

目の前にチカチカと光る三角のギザギザが浮かんできて、視界の左半分が見えなくなった。おそらく閃輝暗点だろう…。30分ぐらい横になったら消えてくれた。

手元のメモを見直したら、5月頃にも発生していた。

2026/07/14(火) [n年前の日記]

#1 [prog] Windows用grep.exeの罠

これって数日前にメモしてたかな…。忘れた…。とりあえずメモしておくか…。

Windows11 x64 25H2上で、grep (grep.exe) のヘルプ(--help)やバージョン確認(--version)をしようとしてハマった。-h や --help や --version を打っても、何も出てこない。おかしい。

> grep -h
Error: No file sets specified

> grep --help
Error: No file sets specified

> grep --version
Error: No file sets specified

自分の環境では以下の版を D:\home2\bin\ 以下に置いてあって、それが呼び出されるものと思っていたのだけど…。

_Grep for Windows

where で確認したら妙なことになってた。

> where grep
D:\Program Files (x86)\Embarcadero\Studio\23.0\bin\grep.exe
D:\home2\bin\grep.exe

Embarcadero云々のほうが先に呼ばれている…。Embarcadero というと、Delphi かな? Delphi にも grep.exe が添付されていて、そちらが先に呼ばれている?

Turbo grep なるものがあるらしい :

AI (Google Gemini)に尋ねてみたら、「それは Turbo GREP じゃないか? だったら grep ? でヘルプ表示が出るかも」と言ってきた。

試してみた。

> grep ?
Turbo GREP 5.6 Copyright (c) 1992-2010 Embarcadero Technologies, Inc.
Syntax:  GREP [-rlcnvidzewoqhu] searchstring file[s] or @filelist

Options are one or more option characters preceded by "-", and optionally
followed by "+" (turn option on), or "-" (turn it off).  The default is "+".
   -r+  Regular expression search       -l-  File names only
   -c-  match Count only                -n-  Line numbers
   -v-  Non-matching lines only         -i-  Ignore case
   -d-  Search subdirectories           -z-  Verbose
   -e   Next argument is searchstring   -w-  Word search
   -o-  UNIX output format                   Default set: [0-9A-Z_]
   -q-  Quiet: supress normal output
   -h-  Supress display of filename
   -u xxx Create a copy of grep named 'xxx' with current options set as default

A regular expression is one or more occurrences of:  One or more characters
optionally enclosed in quotes.  The following symbols are treated specially:
      ^  start of line             $  end of line
      .  any character             \ quote next character
      *  match zero or more        +  match one or more
      [aeiou0-9]   match a, e, i, o, u, and 0 thru 9 ;
      [^aeiou0-9]  match anything but a, e, i, o, u, and 0 thru 9

マジだ。Turbo GREP 5.6 が呼び出されてしまっていたのか。

OR検索の謎 :

AI曰く、「Turbo GREP なら OR検索は使えないはず」とのこと。

妙だな…。以下でも動いてるように見えるけど…。

> py -m pip list | grep -E "opencv|numpy"
numpy                     2.2.6
opencv-contrib-python     5.0.0.93
opencv-python             5.0.0.93
opencv-python-headless    5.0.0.93

色々試してたら、そもそも Turbo GREP 5.6 なら、-E をつけなくてもOR検索できるように見えた。

> py -m pip list | grep "opencv|numpy"
numpy                     2.2.6
opencv-contrib-python     5.0.0.93
opencv-python             5.0.0.93
opencv-python-headless    5.0.0.93

Turbo GREP のヘルプ表示では、-r をつければ正規表現で指定できると書いてあったのでそれも試してみたけれど、その場合も動いてるように見える…。どうなってるんだ…?

以下のテキストファイルを作成して、Turbo GREP版でOR検索を試してみた。
hoge
fuga
piyo
hoge|fuga

> "D:\Program Files (x86)\Embarcadero\Studio\23.0\bin\grep.exe" "hoge|fuga" test.txt
test.txt
hoge
fuga
hoge|fuga

やはりOR検索が動いちゃってるように見える…。いや、動かないよりは動いたほうがいいんだけど。内部的には機能追加されてるけれど、ヘルプ表示だけが古いまま、ということなのかな…。

環境変数PATHの順番で、D:\home2\bin\ のほうを先に登録してそちらが呼ばれるようにしたいけれど、それをしてしまうと Delphi を動かした時に不具合が出そうで…。どうしたものか…。

2026/07/15追記 :

GNU版の grep.exe をリネームコピーして gnugrep.exe にしておいた。自分の環境では gnugrep と打てば GNU版 grep を利用できる、とメモしておく。もっとも自分のことだから明日には忘れてそう…。

Rust で書き直されて爆速になったという、ripgrep (rg.exe) を使うように心掛けたほうがいいのかもしれない…。

あるいは egrep.exe を ―― 指定した検索パターンを拡張正規表現として扱う grep を利用することにするとか…。

以上、14 日分です。

過去ログ表示

Prev - 2026/07 -
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project