mieki256's diary



2021/02/13() [n年前の日記]

#1 [hsp][hns] hns上でHSPのスクリプトソースを色付け表示してみたい

この日記ページは、hns (Hyper NIKKI System) というWeb日記生成システムで表示しているのだけど。 *1

_Hyper NIKKI System Project

プログラムソース部分については、SyntaxHighlighter という JavaScript を利用させてもらって色付け表示していて。

_syntaxhighlighter/syntaxhighlighter

SyntaxHighlighter は、メジャーなプログラミング言語には対応しているのだけど、HSP には対応していない。どうにかできないものか…。と思ってググってみたら、HSP用の SyntaxHighlighter Brush ファイルを公開してくれている方が。ありがたや。使わせてもらったり。

_HSP用のSyntaxHighlighter定義用ファイル(shBrushHsp.js) | Codetter(こーどったー)

brushファイルというのは、それぞれの言語の色分け表示に対応させるための定義が書かれているファイル、とでも言うか…。例えば C++ソースの色分け表示なら shBrushCpp.js で定義されてるし、Perlの色分け表示なら shBrushPerl.js で定義されてる。なので、HSPに対応させるなら、shBrushHsp.js を作って対応させることになる。

ちと問題があった。 :

試してみたところ、一部で問題が…。

shbrushhsp_ss01.png

shbrushhsp_ss02.png

  • 「key & $80」が「key &; $80」に。
  • 「count >= wait_frame」が「count >;= wait_frame」に。
何故か「;」が挿入されてしまうようだなと…。

コメント行への対応がアレっぽい。 :

色々試してみたけれど、どうやら shBrushHsp.js 内で、「;」を使ったコメント行に対応させるための行を入れると、件の症状が出るようで。

「;」がコメントになってる言語って他に何があったかなと調べてみたら、Lisp がそういう言語仕様のようで。であれば、shBrushLisp.js を参考にすればどうにかなりそうな予感。

shBrushHsp.js の一部を、以下のように書き換えてみた。

        this.regexList=[
            {regex:SyntaxHighlighter.regexLib.singleLineCComments,  css:'comments'},
            {regex:SyntaxHighlighter.regexLib.multiLineCComments,   css:'comments'},
            {regex:SyntaxHighlighter.regexLib.doubleQuotedString,   css:'string'},
            
            {regex: new RegExp('&\\w+;', 'g'),                      css:'plain'},
            {regex: new RegExp(';.*', 'g'),                         css:'comments'},
            
            {regex: /\#\w+/gm,                                      css:'preprocessor'},
            {regex: /\*\w+/gm,                                      css:'functions'},
            {regex: /\$\w+/gm,                                      css:'value'},
            
            {regex:new RegExp(this.getKeywords(keywords),'gm'),     css:'keyword'}
            ];

動作テスト。 :

試しに、HSPスクリプトっぽいものを仮で書いて動作確認してみる。

言語の指定をしない場合は以下のように表示される。
; HSPスクリプトソースの色分け表示のテスト
; コメント文
// これもコメント文
/*
これもコメント文
*/

#define winid 3

    a = $80

*mainloop
    stick key, $FF
    if key & $80 : goto *endjob
    if count >= wait_frame {
        step = step + 1
    }
    if count <= 10 : goto *endjob
    if count = 0 : goto *endjob
    if count ! 0 : goto *endjob
    goto *mainloop

*jobend
    end

SyntaxHighlighter で色付け表示してみる。これでどうかな…。
; HSPスクリプトソースの色分け表示のテスト
; コメント文
// これもコメント文
/*
これもコメント文
*/

#define winid 3

    a = $80

*mainloop
    stick key, $FF
    if key & $80 : goto *endjob
    if count >= wait_frame {
        step = step + 1
    }
    if count <= 10 : goto *endjob
    if count = 0 : goto *endjob
    if count ! 0 : goto *endjob
    goto *mainloop

*jobend
    end

おかしな表示ではなさそう。これでどうにかなった…かな…。たぶん。

一応、修正した版も置いておきます。

_shbrushhsp.js.txt

自分の手元の hns を修正。 :

一応、自分の手元の hns について修正した部分をメモしておく。他の人にとっては意味不明でも、作業メモを残しておかないと、後で似た作業をする時に自分が困るので…。

手元で動いている SyntaxHighlighter は、Version 3.0.83 (July 02 2010)。前述の shBrushHsp.js とバージョンは一致してた。

  • scripts/ 以下に shBrushHsp.js として保存。
  • hns の theme.ph 内に「,"hsp scripts/shBrushHsp.js"」を追記。

theme.ph の最初のあたりは、こんな感じの記述になった。
################################################################
# Extend HTML
package HNS::ExtHTML;
$DOCTYPE = qq(<?xml version="1.0"?>\n<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"\n"http://www.w3.org/TR/html4/loose.dtd">\n);
#$Head = undef;
$Head = qq[
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="shortcut icon" href="icons/favicon.ico">
<link rel="alternate" type="application/rss+xml" title="RSS" href="${HNS::System::MyDiaryURI}rss.cgi">
<META http-equiv="Content-Style-Type" content="text/css">
<link rel="stylesheet" href="./import.css" type="text/css" media="all">

<link type="text/css" rel="stylesheet" href="styles/shCore.css">
<link type="text/css" rel="stylesheet" href="styles/shCoreDefault.css">
<script type="text/javascript" src="scripts/shCore.js"></script>
<script type="text/javascript" src="scripts/shAutoloader.js"></script>
<script type="text/javascript" src="scripts/shBrushXml.js"></script>
<script type="text/javascript">
window.onload=function(){
    SyntaxHighlighter.autoloader(
        "bash                     scripts/shBrushBash.js"
        ,"as3 actionscript3       scripts/shBrushAS3.js"
        ,"cpp c                   scripts/shBrushCpp.js"
        ,"c-sharp csharp          scripts/shBrushCSharp.js"
        ,"css                     scripts/shBrushCss.js"
        ,"js jscript javascript   scripts/shBrushJScript.js"
        ,"perl pl                 scripts/shBrushPerl.js"
        ,"text plain              scripts/shBrushPlain.js"
        ,"python py               scripts/shBrushPython.js"
        ,"ruby rails ror          scripts/shBrushRuby.js"
        ,"vb vbnet                scripts/shBrushVb.js"
        ,"lisp                    scripts/shBrushLisp.js"
        ,"lua                     scripts/shBrushLua.js"
        ,"hsp                     scripts/shBrushHsp.js"
    );
    SyntaxHighlighter.all();
}
</script>
];

加えて、lib/HNS/Hnf/Command.pm を弄って、「PRE perl」「PRE hsp」といった指定もできるようにしてあった…はず…。このあたりは記憶が怪しい…。
# PRE
package HNS::Hnf::Command::PRE;
use vars qw(@ISA $Template $EndTemplate $NumAttr $IsOneline $AllowCommands
            $IsBeginSection $CountName $OmittableEnd
            $TemplateWithCode $EndTemplateWithCode
            $TemplateWithoutCode $EndTemplateWithoutCode);

@ISA = qw(HNS::Hnf::Command::Cite);
$NumAttr = 1;
$Template                = qq(<pre class="plain">);
$EndTemplate             = qq(</pre>);
$TemplateWithoutCode     = qq(<pre class="plain">);
$EndTemplateWithoutCode  = qq(</pre>);
$TemplateWithCode      = qq(<pre class="brush: %1">);
$EndTemplateWithCode   = "</pre>";
# $TemplateWithCode        = qq(<pre><code>);
# $EndTemplateWithCode     = qq(</code></pre>);
$AllowCommands = [$HNS::Hnf::Command::Entities{'Inline'}];

sub AsHTML ($$$){
    my ($self, $start, $params) = @_;
    my $codelang = $self->{attr}->[1];
    if ( $codelang ) {
        $Template = $TemplateWithCode;
        $EndTemplate = $EndTemplateWithCode;
    } else {
        $Template = $TemplateWithoutCode;
        $EndTemplate = $EndTemplateWithoutCode;
    }
    return $self->SUPER::AsHTML($start, $params);
}

*1: ブログじゃなくて、ウェブ日記。

#2 [python][pygame] PygameをWindows10上でインストール

Pygame というのは…Pythonを使って2Dゲームを作れるライブラリ、という説明でいいのだろうか。

_pygame.org/news
_pygame - Wikipedia

メインPCにインストールしてみたり。環境は以下。

経緯。 :

ツッコミが入ったことをキッカケにして _昔の日記ページ に目を通したのだけど。自分自身も過去の自分にツッコミを入れたくなってしまった…。

「Pygameで描画するスクリプトって、どのプログラムのことだよ!?」
「Python のバージョンは? Pygame のバージョンは? なんでそこらへんをメモしてないのよ!?」

みたいな。コレじゃダメだよ…>過去の自分。動作ログにすらなってないやん。

まあ、Raspberry Pi Zero W が想像していた以上に非力でガッカリしました、という当時の気分だけは分かるのだけど…。おそらく、ガッカリし過ぎて、それ以外のことがどうでもよくなって、環境その他をメモするのをスポンと忘れたのだろう…。

さておき。当時動かしたスクリプトって一体どれだっけ? 今も残ってるのかな? とHDDの中を漁ってたら、そもそも今のメインPC(Windows10機)に Pygame をインストールしてなかったことに気付いた。去年の8月頃にSSDが突然死して、Windows10を再インストールしてから、そのあたりの環境復旧をしてなかったので、この際 Pygame をインストールしておこう、と。

Pygame をインストール。 :

pip でインストール。
pip install pygame
> pip list | grep pygame
pygame            2.0.1
Pygame 2.0.1 がインストールされた。

…えっ。2.0.1?

Pygame が 2.x.x になってた。 :

インストールしてみて驚いた。Pygame って 2.0.0 になってたの? ずっと 1.9.x だったはずだけど、とうとう 2.0.0 に?

_Releases - pygame/pygame
_Release pygame 2.0 - the happy dance birthday release - pygame/pygame

2020/10/29 に、2.0.0 が公開されていたらしい。一時期は開発が停滞してアレだったのに…。素晴らしい。よくぞここまで。

ということは、SDL も SDL1 から SDL2 になって描画が高速化されてたりするのだろうか?

libsdl version 2 support. Technically pygame 2.0 still works with SDL 1, but we recommend SDL2 which is vastly improved over SDL1 for most use cases. Probably we will remove SDL 1 support starting pygame 2.1.
「libsdlバージョン2をサポートしてるけど、Pygame 2.0 は SDL1」ってどういうことやねん…。結局、SDL1 のままなのか、そうじゃないのか。

とりあえず、pygame.get_sdl_version() を呼べば、(x, x, x) の形で、Pygame が使ってるSDLのバージョンが得られるらしい。
    sdlver = "SDL ver: %d.%d.%d" % (pygame.get_sdl_version())
「2.0.14」と表示された。すると、Pygame 2.0.1 Windows版では、SDL2が使われていると考えていいのかな。

そもそもDOS窓上から Pygameを使ったスクリプトを実行したら、SDLのバージョンも表示されていた。
> python pygame_fullscreen.py
pygame 2.0.1 (SDL 2.0.14, Python 3.8.7)
Hello from the pygame community. https://www.pygame.org/contribute.html
やはり SDL 2.0.14 を使っているっぽい。

ちなみに、Pygame 1.x.x + SDL1 は、どんな環境でも安定動作させるためにデフォルトではソフトウェア描画をしていて、そのせいで描画速度が遅かったりしたのだけど。SDL2 はハードウェア描画を積極的に使うようになっているから高速に描画できる場面がほとんど、という話だったはず。「Pygameは描画が遅い」というのは過去の話ですよ、と思ってもいいのかも…しれない? たぶん。分からんけど。

Pygameを使ったスクリプトを動かしてみた。 :

HDDの中から、Pygame を使って描画するスクリプトを発掘してきた。Pygame 2.0.1 用に少し修正して実行。ていうか、昔の日記ページにも一応置いてあった模様…。

_Raspberry Pi3上でpygameのスクリプトを動かしてみた
_DXRubyその他の動作速度を確認した結果をメモ

スクリプトの処理内容は…。
  • ウインドウサイズは 640 x 480。
  • 64 x 64ドットのスプライトを、160枚描画。
  • BGを、2枚描画。
  • oggを再生。
  • 1キーを押すと、ウインドウ表示とフルスクリーン表示が切り替わる。
  • 2,3,4キーでスプライトやBGの描画On/Offを切り替えられる。

これだけ表示して60FPSが出るようなら、昔風のリアルタイム2Dアクションゲームなら十分作れるはずだよなと…。



_pygame_fullscreen.py
import pygame
from pygame.locals import *
import math
import os
import sys

SCR_RECT = Rect(0, 0, 640, 480)
mode_v = 0


class MySprite(pygame.sprite.Sprite):
    u"""スプライトクラス."""

    def __init__(self, img, x, y, vx, vy):
        u"""初期化処理."""
        pygame.sprite.Sprite.__init__(self)

        # self.image = pygame.image.load(filename).convert_alpha()
        self.image = img
        self.w = self.image.get_width()
        self.h = self.image.get_height()
        self.whf = self.w / 2
        self.hhf = self.h / 2
        self.fpx = float(x)
        self.fpy = float(y)
        self.fpvx = float(vx)
        self.fpvy = float(vy)
        self.rect = Rect(int(self.fpx - self.whf),
                         int(self.fpy - self.hhf),
                         self.w, self.h)

    def update(self):
        u"""毎フレーム呼ばれる処理."""
        self.fpx += self.fpvx
        self.fpy += self.fpvy
        self.rect = Rect(int(self.fpx - self.whf),
                         int(self.fpy - self.hhf),
                         self.w, self.h)
        if self.rect.left <= 0 or self.rect.right >= SCR_RECT.width:
            self.fpvx *= -1
        if self.rect.top <= 0 or self.rect.bottom >= SCR_RECT.height:
            self.fpvy *= -1
        # self.rect = self.rect.clamp(SCR_RECT)


def draw_bg(bx, by, bg, screen):
    u"""BG描画処理."""
    bx = int(bx)
    by = int(by)
    for ofs in [[0, 0], [512, 0], [0, -512], [512, -512]]:
        screen.blit(bg, (bx + ofs[0], by + ofs[1]))


def main():
    u"""メイン処理."""
    global mode_v

    fullscreen_flag = False
    running = True
    cap = ""

    # pygame初期化
    pygame.init()

    if True:
        mode_v = pygame.DOUBLEBUF
        screen = pygame.display.set_mode(SCR_RECT.size, mode_v)
    else:
        mode_v = pygame.OPENGL | pygame.DOUBLEBUF
        screen = pygame.display.set_mode(SCR_RECT.size, mode_v, vsync=1)

    pygame.display.set_caption("Pygame Full Screen Demo")

    # フォント指定
    font = pygame.font.Font("res/Vegur-Bold.otf", 18)

    # BG画像読み込み
    bg1 = pygame.image.load("res/bg1.png").convert()
    bg2 = pygame.image.load("res/bg2.png").convert_alpha()

    # スプライトグループを作成してスプライトクラスに割り当て
    sprgrp = pygame.sprite.OrderedUpdates()

    # スプライトを作成
    pmax = 160
    sprimg = pygame.image.load("res/ufo.png").convert_alpha()
    # ckey = sprimg.get_at((0,0))
    # sprimg.set_colorkey(ckey)
    x = SCR_RECT.width / 2
    y = SCR_RECT.height / 2
    for i in range(pmax):
        rad = math.radians(i * 360 / pmax)
        vx = 3.0 * math.cos(rad)
        vy = 3.0 * math.sin(rad)
        sprgrp.add(MySprite(sprimg, x, y, vx, vy))

    # BGM start
    pygame.mixer.music.load("res/bgm32.ogg")
    pygame.mixer.music.play(-1)

    drvname = "DRIVER: %s" % (pygame.display.get_driver())
    sdlver = "SDL ver: %d.%d.%d" % (pygame.get_sdl_version())

    bgx = [0, 0]
    bgy = [0, 0]

    sprdraw = True
    bg0draw = True
    bg1draw = True
    frame_count = 0
    clock = pygame.time.Clock()

    # main loop
    while running:

        # キー入力に対する処理
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE or event.key == K_q:
                    # ESCキーで終了
                    running = False

                elif event.key == K_1:
                    # フルスクリーンモードへの切り替え
                    fullscreen_flag = not fullscreen_flag
                    pygame.display.toggle_fullscreen()

                    drvname = "DRIVER: %s" % (pygame.display.get_driver())

                elif event.key == K_2:
                    # スプライト描画のon/off切り替え
                    sprdraw = not sprdraw

                elif event.key == K_3:
                    # BG0描画のon/off切り替え
                    bg0draw = not bg0draw

                elif event.key == K_4:
                    # BG1描画のon/off切り替え
                    bg1draw = not bg1draw

        # BG
        bgx[0] = -64 + (64 * math.cos(math.radians(frame_count)))
        bgx[1] = -128 + (128 * math.cos(math.radians(frame_count)))
        bgy[0] = (bgy[0] + 2) % 512
        bgy[1] = (bgy[1] + 6) % 512
        if bg0draw:
            draw_bg(bgx[0], bgy[0], bg1, screen)
        if bg1draw:
            draw_bg(bgx[1], bgy[1], bg2, screen)

        # スプライト座標更新
        sprgrp.update()

        # スプライト描画
        if sprdraw:
            sprgrp.draw(screen)

        # テキスト描画
        strdt = [
            cap,
            drvname,
            sdlver,
            "1: FULL/WDW",
            "2: SPR ON/OFF",
            "3: BG0 ON/OFF",
            "4: BG1 ON/OFF",
            "ESC,Q: EXIT"
        ]
        fontcolor = (255, 255, 255)
        fy = 8
        for s in strdt:
            screen.blit(font.render(s, True, fontcolor), (16, fy))
            fy += 18

        # ウインドウタイトルの文字列を設定
        if not fullscreen_flag:
            pygame.display.set_caption(cap)

        # 60fpsになるよう時間待ち
        clock.tick(60)
        # clock.tick_busy_loop(60)

        # pygame.display.update()
        pygame.display.flip()

        cap = '%5.2f FPS' % clock.get_fps()
        frame_count = frame_count + 1

    pygame.quit()
    sys.exit()


if __name__ == "__main__":
    main()

使用画像、ogg、フォントファイルは以下。解凍して、res/ フォルダの中にコピー。画像とoggはCC0ライセンスってことで。

_res.zip

フォントは、CC0ライセンスの Vegur フォントを使わせてもらいました。ありがたや。

_Vegur | ドットコロン

とりあえず、これでメインPC(Windows10機)上に Pygame をインストールして使える状態になったことを確認できた。

補足。pygame.display.toggle_fullscreen() について。 :

以前書いたスクリプトでは、ウインドウ表示とフルスクリーン表示の切り替えに、pygame.display.set_mode() を使っていたのだけど。

_display - Pygameドキュメント 日本語訳

Pygame 2.0.0 以降は pygame.display.toggle_fullscreen() を呼ぶだけで、ウインドウ表示とフルスクリーン表示の切り替えができるようになっているらしいので、今回はソレを利用することにした。

_pygame.display - pygame v2.0.1.dev1 documentation

pygame.display.toggle_fullscreen() は Pygame 1.x.x の頃から存在していたのだけど、X11(Linuxのデスクトップ画面)でしか使えなかったそうで…。Pygame 2.0.0 からは Windows や Mac 上でも正常動作するようになったので、コレを使わない理由は無いよね、ということになっているらしい。

_Update display.toggle_fullscreen() docs for pygame 2 - Issue #1990 - pygame/pygame - GitHub

#3 [nitijyou] 夜に地震

23:08頃、大きな地震。かなり長い間、激しく揺れた。自分が居る福島県須賀川市は震度6弱だったらしい。今度こそ家が倒壊するのではと不安になるほどの揺れだった。

東日本大震災の時に部屋の中がめちゃくちゃになったので、以後それなりに地震対策をしていたつもりだったけど、全然足りてなかった…。PCデスクの上に置いてあった、光学メディア類のケースが床に落ちて、DVDケースやBDケースが割れてしまった。また、もうすっかり油断していて、ダンボール箱等も雑に積み重ねていたものだから、半数近くがひっくり返って、中に入ってたPCパーツ類も散乱。

ただ、本棚は壁に固定していたので、今回は倒れずに済んだ。箪笥(?)の類も、下のほうに重いモノを入れるように心掛けていたので、コレも倒れずに済んだ。

録画用PCは横倒しに。メインPCはPCデスクから落ちそうなところで留まってくれた。液晶ディスプレイを地震対策用のアレコレで固定してたので、PCデスクの柱と液晶ディスプレイに挟まれて若干移動距離が減らせたのかもしれない。

壁に立てかけてあったMIDIキーボードが倒れて、壁のコンセントのあたりを直撃して、コンセントが抜けそうになっていた…。

気象庁の会見によると、これからも同程度の余震があり得るとの話で。対策しておかないと…。

以上、1 日分です。

過去ログ表示

Prev - 2021/02 - Next
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

カテゴリで表示

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


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

Powered by hns-2.19.6, HyperNikkiSystem Project