もうどうにも取返しがつかないこと

しばらく前の話。

 

夜明けごろ、夢を見た。ああ、でもこれはかつてあった出来事だとわかった。

幼い頃、地元の肉屋の前に、誰かが仕留めたイノシシが置かれていることが度々あった。当時の私はそれに妙に惹かれて、ぼうっとそれを眺めていることが多かった。そんなある日、とある男性に声をかけられた。

「私が誰かわかるかい?」

見知らぬ老人。私は「わからない」と答える。その応えに、彼は苦笑していたのかも知れない。飴をくれたような記憶がある。

「そうか、わからないか」

「わからないよ」

そんな言葉を交わした後、イノシシを触る私をしばらく眺めた後、彼を待っていたと思しき女性と寂しげにその場を離れていった。そういう記憶だ。

唐突に目が醒めた。記憶のピースが嵌っていく感触。

…私の父母は私の幼い頃に離婚していた。2、3歳の頃の遠く、色褪せた記憶だ。母と再会できたのは30も半ばになってからだ。既に祖父は他界し、祖母は…父方の祖母との約束だからと、私と親交を深めることを良しとしてはくれなかった。

再会した時、祖母は、祖父はよくイノシシを仕留めては街中の肉屋に卸ていたという話をしてくれた。その時は「ああ、あの肉屋の前にあったイノシシは彼が仕留めたものだったのか」という程度の認識だったのだが…

違う。

その言葉に込められた意味はそれだけじゃない。あの時、飴をくれた男性は、彼と一緒にした女性は、祖父と祖母だったのだ。

 

私には、昨年生まれた孫がいる。娘の息子だ。つまり、彼と私の関係に等しい。孫を抱いた時に感じる愛おしさは何物にも代えがたい。そんな感情が自分にも湧くのかと驚いたものだったが…そういう対象である孫の私に、「お前など知らない」と言われた祖父の心情は如何ばかりものであったのか。謝りたい。だが、それはもう叶わない。布団の中でひとしきり涙し…いつか私も「向こう」に行った時には真っ先に謝りに行こう、そんなことを心に決めた。

 

※この内容は11/18にJ-Waveau FG LIFETIME BLUESで紹介されましたが…全面的に夢の話に改定されてしまいましたねw

超獣機神ダンクーガの打ち切りの原因を検証する

HAGANE WORKSダンクーガの発売日に向けて、個人的にダンクーガ熱が高まってきているのですが、

以前から気になっていることがあります。

それはWikipediaダンクーガの項目にある、打ち切りの原因の説明。

オモチャが売れまくって年末に売る物が無くなったからと書かれている一方で、もう片方では、オモチャが売れなかったからと書かれています。

正反対じゃないか。どっちなんだ。

 

と言うわけで実際の資料を手に入れて記載を確認した上で検証してみることにしました。

Wikipediaによると、それぞれの記載の元ネタは、

です。

まあムックの方は元から持ってたんですが

前者の奥田誠治氏の「アニメの仕事は面白すぎる」を確認すると、確かに85年のアメリカの超合金ブームに対してオモチャ(在庫)を全て送った結果、売る物が無くなったから、と書かれていました。

対して、後者のムックではプロデューサー氏が「オモチャが売れなかったのが打ち切りの理由です」と明言されていました。

わかってたけど、正反対です。

じゃあ当時の外野から見た印象はどうだったと言うと…これは当時の私の記憶になるんですが(つまり怪しい! 眉に唾をつけて読みましょう!)、ダンクーガのオモチャって、あまり店頭に並んでるところを見たことがなかったんですよね。

オマケに少々高価で、ガンプラとかを見た後だと不格好。

私にはちょっと手が出せなかったので、止む無く非変形版の安い方を買って溜飲を下したのですが、

こっちの方が安いし、スタイルもいい

それでも変形、合体というギミックは諦めきれず、どうせ年末を過ぎたら安くなるだろうから、それを買おうと目論んだのですが、結果的にそんなことは起きなかったんです。
まあ、この時の後悔が今も私を苛み、結果として30年経ってもトイが出ると買わずにはいられなくなってるわけですが…そう考えると、後者の証言はちょっとおかしい。

 

以上のことを踏まえて、

「そもそもあまり売れてなかった」

アメリカの超合金ブームを当てこんで(国内で売れてなかったから)、全部アメリカに送って売り切った」

「全部アメリカに送った結果、年末商戦では売る物もないので打ち切りへ(在庫がなければ宣伝をする必要もない」

というのが本当のところなんじゃないかと私は結論しました。

勿論、「バンダイがプロデューサーに諦めさせる為に、細かい情報を与えていなかった」という可能性もありますが。

 

ちなみに奥田氏の本によると、超合金はアニメ番組が始まる以前には完成してたみたいです…凄いな、本当にオモチャを売る為の番組だったんだ…。

 

 

Tkinterで、image付きListbox的なモノを実装してみた( Tkinter List with image and text

f:id:lynmock:20220214095512p:plain
初めてのPythonソフトとして、こんなのを作った、という話です

先日、Raspberry Pi4にSSDを奢ってみたので、せっかくだからPythonを使えるようになって積極的にオモチャにしてやろうと勉強することにしました。

f:id:lynmock:20220214140418j:plain

まずは軽くTwitterクライアント*1を作ってみようと考えたものの、Pythonの主流GUIライブラリであるTkinterには、画像の使えるListboxがない様子。
Stack Overflowを見ても「Listboxで画像を使う方法を教えて」「そんな機能はない」などというやり取りが見受けられ、軽く検索してみても、それを実現するコードは見つかりませんでした。なんか大昔にTwitterクライアントを作ろうとAWTの勉強をしてみたものの同様のことで躓き、Swingに転がったのを思い出しますね。
問題は今回はライセンスとか考えると、そういう都合のいい別のライブラリがないところですが。

てなわけで、先の3連休の最終日を潰して画像の使えるListbox的なモノを丁稚UPしてみました。まあ多分本格的にやってるヒト達はこんなのホイホイと作ってるのでしょうが、検索した時に何も出てこないのは初心者には辛かろう、という意味での公開です…。

import tkinter as tk
import tkinter.ttk as ttk
from PIL import Image, ImageTk

class ScrollableFrame(ttk.Frame):
    # based https://daeudaeu.com/scrollbar/
    def __init__(self, container):
        super().__init__(container)
        self.canvas = tk.Canvas(self)
        self.scrollable_frame = ttk.Frame(self.canvas)
        self.scrollable_frame.bind(
            "<Configure>",
            lambda e: self.canvas.configure(
                scrollregion=self.canvas.bbox("all")
            )
        )
        self.canvas.bind("<MouseWheel>", self.mouse_y_scroll)
        self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
        self.scrollbar_y = ttk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.scrollbar_y.pack(side=tk.RIGHT, fill="y")
        self.canvas.configure(yscrollcommand=self.scrollbar_y.set)
        self.canvas.pack(side=tk.LEFT, fill="both", expand=True)
        self.canvas.focus_set()
    def mouse_y_scroll(self, event):
        unitCount = 0
        if event.delta > 0:
            unitCount = -1
        elif event.delta < 0:
            unitCount = 1
        self.canvas.yview_scroll(unitCount, 'units')

class WrappingLabel(ttk.Label):
    def __init__(self, master=None, **kwargs):
        ttk.Label.__init__(self, master, **kwargs)
        # -90 is a correction value to avoid overlapping Label and scrollbar.
        self.bind('<Configure>', lambda e: self.config(wraplength=frame.winfo_width() - 90))
        self.bind("<MouseWheel>", frame.mouse_y_scroll)
        self.bind("<Button-1>", self.click)
    def setIndex(self, i):
        self.rowIndex = i
    def click(self, event):
        global selectedIndex,label_list
        if selectedIndex == self.rowIndex:
            return
        set_list_background(0, self.rowIndex)            


def press_down_key(self):
    global selectedIndex,label_list
    if (selectedIndex < 0 or selectedIndex == len(label_list) -1):
        return
    set_list_background(1)
   
def press_up_key(self):
    global selectedIndex,label_list
    if (selectedIndex <= 0):
        return
    set_list_background(-1)

def set_list_background(indexCorrect, newIndex = -1):
    global selectedIndex, label_list
     # Return the selected label to the original background color
    selectedLabel = label_list[selectedIndex]
    selectedLabel.config(foreground = 'black', background = get_list_background(selectedIndex)) 
    # Change the background color of the newly selected label to blue
    if newIndex >= 0:
        selectedIndex = newIndex #click
    else:
        selectedIndex = selectedIndex + indexCorrect
    selectedLabel = label_list[selectedIndex]
    selectedLabel.config(foreground = 'white', background = '#2080ff')

def get_list_background(index):
    if  index%2 == 0:
        return "#FFFFFF"
    else:
        return "#DDDDDD"


root = tk.Tk()
root.geometry("500x700+0+0")
root.bind("<Down>", press_down_key)
root.bind("<Up>", press_up_key)

style = ttk.Style()
style.theme_use("classic")

frame = ScrollableFrame(root)
frame.pack(fill="both", expand=True)

image_list = []
label_list = []
selectedIndex = -1

for i in range(100):

    img = Image.open('icon.png')
    img = img.resize((48, 48))
    img = ImageTk.PhotoImage(img)
    image_list.append(img)

    label = WrappingLabel(
        frame.scrollable_frame, 
        text = str (i) +":Good morning. In less than an hour, aircraft from here will join others from around the world. And you will be launching the largest aerial battle in the history of mankind. Mankind. That word should have new meaning for all of us today. ", 
        image = image_list[i], 
        foreground = "black",
        background = get_list_background(i),
        compound = "left",
        padding = [10],
        wraplength = 100)
    label.pack(expand=True, fill=tk.X) 
    label.setIndex(i)
    label.bind("<MouseWheel>", frame.mouse_y_scroll)

    label_list.append(label)
    
root.mainloop()

Labelデザインやデータの構造の部分は都合のいいように変更して使ってください。挙動はこちらに動画を上げてみましたのでご確認ください。

www.youtube.com

開発&動作確認はMac OS Monterey、Python 3.10.2(2.7.18かも)で行いました(RaspberryPiじゃないのかよ)
何しろPythonについては素人なので、修正すべきところがあったら教えてくれると嬉しいです。

あ、あと、気に入ったヒトは、お財布が温かい時に気が向いたら、こちらの欲しい物リストから何かくれると私が超喜びますw

ほんじゃね。

※ScrollableFrameの部分は https://daeudaeu.com/scrollbar/ に掲載されたコードを元にしています。


追伸
本当はカーソルの位置に追従してスクロールするのを実装していたのですが、スクロールバーをクリックした時にどうしたらいいのかわからんので諦めました

www.youtube.com
下に行く時だけできた…まあ気が向いたら完成させます

考えてみたらコイツらを使えばスマートにできたんだ…

*1:Twitterクライアントって色々な機能が要求されるので、一つの言語やフレームワークを覚えるのに都合がいいのです

日立のMSX2の仕様に翻弄された

1986年、パナソニックソニーは、それまで5万円以上が標準だったMSX2の価格を一気に引き下げる、FS-A1、HB-F1をリリース。その安さから、当時の「パソコンが気になっていた少年少女達(我々のことだ、わかっとるか)」の支持を受けて一気に普及台数を伸ばすことになった。

f:id:lynmock:20210827103119j:plain f:id:lynmock:20210827102211j:plain

 が、新しく安いモノが出るならば、古くて高いモノが残るのは世の常。当時の家電量販店には、「型遅れ」となってしまったMSX2達が並び、定価を無視して、場合によってはFS-A1、HB-F1以下のプライスタグを付けられていた。

となると…今度は逆にそっちに目をつける捻くれたヤツも出てくる。そう、当時の私のように。
私は(やめればいいのに)、19800円というそれらのMSX2の中から、日立のMB-H3、キヤノンのV-25という機種に目を付けた。前者は手書きタブレット付き(!)、後者はとにかく格好いいデザインがウリである。

f:id:lynmock:20210827103346j:plain f:id:lynmock:20210827103407j:plain

結局、数日悩んだ上でV-25を選択したのだが、マトモに知識のない中でこれを選んだことを、その後1年悔み続けることになる。
ご存じの方ならば既に数行前でニヤニヤされていることであろう。そう、MB-H3と共に、この機種はVRAMが通常128KBの半分、64KBしかないのである!!!
しかも、MB-H3の方はまだ日立によるVRAMアップデートサービスが行われていたにも関わらず、V-25の方は放置。友人達には散々「新しいMSX2のゲーム買ったケド…あ、お前のでは遊べないね」とからかわれたのだった。
その後、私は雑誌の売買コーナーを駆使して、毎年のようにリリースされるMSX系の新型に買い替えることになるのだけど、まあそれはおいといて…この30年、ずっと気になっていたことがある。
先のMB-H3、VRAMが増やせるのならばそのように設計されているハズ。ならば自分の手でそれをやってみたい! 幸いにして情報はこちらにあったので、あとはモノを手に入れるだけである。早速オークションにてジャンク品のMB-H3を入手してみた。
どっこい、いざRGB to HDMI接続で繋いでみたら画面が映らない。

f:id:lynmock:20210827104229j:plain

電解コンデンサが逝っているのでは?と言われたので、せっせと基板上のコンデンサの仕様を調べたりしてみたが、試しにビデオ出力で繋いでみたらちゃんと動く。

f:id:lynmock:20210827104305j:plain

RGB信号はVDPで生成して、そこからゴニョゴニョしてビデオ信号にしているハズ。ということは、RGB端子周りが怪しい?
…とここまで考えたところで、私がMSX2を手に入れるより前は、同じRGBでもピン配列が異なるモノがある、という話を思い出した。
果たしてMSX Resource Centerで調べたらご覧の通り。見事にピン配列が違っていましたorz
これはRGBケーブルを入手して改造する必要がありますね…。

f:id:lynmock:20210827104118p:plain

とりあえずまたオークションでRGBケーブルを入手しました…

 

Androidアプリ・ジフスタ〜GifStampをリリースしました

Androidユーザの皆さん、Twitterにネタとしてアニメーションgifをもっと使ってみたいと思ったことないだろうか。いや、別にTwitterに限った話ではないのだけど。
あるいは、ゲームをプレイしていて、「ここを投稿したい」と思ったことは?

もちろん、数多のAndroidアプリの中には、その用途に使えるモノが多数ある。だが、大抵は録画後にクロップしたりトリミングしたりと面倒な操作が伴うものだ。

違う、そうじゃない。僕たちはもっと手軽にアニメgifを作成して投稿して遊びたいのだ。(※個人の感想です)

と、言うわけで今回作成してリリースしたのがこのジフスタ GifStampだ。


DLはこちらから
※1/9にDLされたヒトは、一旦削除して、こちらからDLしてください

使い方は簡単。例えばYoutubeの動画から作成する場合の手順は以下の通り

STEP.1 ジフスタを起動する

STEP.2 Youtubeアプリでネタ元動画を再生する

STEP.3 gifに含めたいポイントがきたら録画ボタンを押す(録画コントローラが消えます)
STEP.4 録画したいポイントが終わったら指を画面を離す(離さなくても6秒を過ぎると自動的に録画終了する)
STEP.5 TwitterSNSなどに投稿する(できあがったgifに納得がいかなかったらCANCELボタンを押してやり直す

勿論、上に上げた手順ではゲームプレイ中には録画できない。その場合は、アプリを起動した時に表示される画面にある「オート録画機能」にチェックを入れればいい。そうすると、録画ボタンを押してから6秒間の録画を行うようになる。


ここね

また、当然ながら録画コントローラは移動可能だ。☓ボタンを長押しすると、コントローラ移動モードになるので、指で自由に移動させられる。これで投稿したいアプリのUIに干渉しないようにすることができる。


移動モード


どうかな。これだけgifアニメを作る敷居を下げれば、気軽にL○NEスタンプのようにサクサクと作成して投稿することができるんじゃないかな。

というわけでAndroidユーザの皆さんがガンガンダウンロードするといいと思いますね。今のところは広告もない無料アプリなので、是非!

こういうのをガンガン作って遊ぼうぜ!

皆さんはもう予約しました? 私は絶賛Forza Horizon4とHorizonZero Dawnプレイ中なので一旦様子見です…

【オボエガキ】bitriseでUnityをBuildしたら通らなかった

bitriseでUnityプロジェクトをビルドしたい。
こちらを参考にしてbitrise.ymlを作成(要所にあるバージョンはアップデート、$UNITY_SERIAL、$UNITY_EMAIL、$UNITY_PWは下記画像を参考にして設定)してbuildしたが、"Activate Unity"で下記のエラーが出て通らない。

DisplayProgressbar: Unity Package Manager
[Package Manager] Done resolving packages in 0.27s seconds
[Package Manager] Failed to resolve packages: [Packages] directory does not exist. No packages loaded.

A re-import of the project may be required to fix the issue or a manual modification of Packages/manifest.json file.
[Package Manager] Server::Kill – Server was shutdown

PackageManagerなんて使ってないのに何故…

とりあえず今回はPackageManagerを使う予定はないので、「-noUpm」オプションを付けて回避することにした。

/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit batchmode -serial $UNITY_SERIAL -username $UNITY_EMAIL -password $UNITY_PW -logfile

/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit -noUpm -batchmode -serial $UNITY_SERIAL -username $UNITY_EMAIL -password $UNITY_PW -logfile