Gaming Life

一日24時間、ゲームは10時間

レオパレス民族大移動に巻き込まれた①

レオパレス民族大移動に巻き込まれた。

https://twitter.com/ai_9684_dct/status/1094171497399169026

家電付きの魅力に囚われレオパレスを選んだのだが、まさかこんなことになるとは。とにかく引っ越しの準備を急いでしなければならない。

で、先程レオパレスの担当者が謝罪と今後の予定について話しに部屋までやってきたので、そこで判明したことを共有。

  1. 本来退去時に必要な清掃費等は一切かからない
  2. 引っ越し先はこちら側の条件を聞きレオパレス側が候補を挙げ、そこから選ぶ。レオパレス物件から優先しての案内になるが、他社物件の可能性もある。
  3. 引っ越しにかかる費用は「全額」レオパレスが負担。(※ここでいう「全額」がどこまでを指すかは不明。見舞金が出るかどうかも言わなかった)
  4. 家電備え付けでない他社物件に引っ越す際、現在住んでいる住居に備え付けられている家電を持ち出すことができる。

特に家電の心配をしなくても良くなったのはデカい。

今後進展があれば書ける範囲で随時ブログに書くと思います。

※現在募集停止【告知】2D経営シミュレーション系ゲームのドッター募集

※今回の記事は個人的な告知です。

現在、私を含む開発メンバー二人で、2Dの経営シミュレーション系ゲームを開発しています。

今年末のデジゲー博、もしくは冬コミで頒布を目標として開発を進めていますが、ドット絵の素材の用意に非常に苦労しています。

そこで、2Dのドット絵を描いてくださる方を募集します。

依頼内容

  • C++(OpenSiv3Dライブラリ)で開発中の経営シミュレーション系ゲームで使用する人物系のドット絵の作成

「48x48のサイズ、差分は各キャラ2個ずつ」の仕様を満たしていればどんなキャラクターでも構いません。

報酬

  • 応相談。金銭的な報酬は多額は出せないと思います……

その他

  • 開発の中心メンバーとして加入という形でも、外注という形でも構いません。

連絡先

  • このブログのコメント欄
  • Twitterアカウント @ai_9684_dct

大々的には募集しませんが、プログラマーとして参加したいという方もいらっしゃれば連絡をください。

どうかよろしくお願いいたします。

UE4 マテリアルとRenderTargetを使ってライフゲームを作ってみる

一体どこに需要があるのかわからないが、マテリアルをとRenderTargetを使ってライフゲームを作ってみた。

wikipediaだったり検索すればすぐに分かりやすい説明が見つけられるので、ここではライフゲームがなんぞやという説明はしない。

バージョン

UE4.21.2

概要

パラメータとしてTextureを与えると、次のタイムステップのライフゲームの結果を吐き出すマテリアルを作成。

ブループリントでRenderTargetを2つ(RT1とRT2とする)用意し、最初に上のマテリアルで計算した結果をRT1、RT2に書き込む。

続けて、

  • RT2をマテリアルのパラメータに与えその結果をRT1に書き込む
  • RT1をマテリアルのパラメータに与えその結果をRT2に書き込む

をTickを使って交互に実行することでライフゲームの時間軸を進めていく。

マテリアルの中身

  • M_LifeGame

f:id:ai_gaminglife:20190202133223p:plain

注意はBase Colorに繋ぐのではなくEmmisive Colorに繋がねばならないこと。理由は後述。

  • MF_8NeighbourPixel

f:id:ai_gaminglife:20190202133236p:plain

f:id:ai_gaminglife:20190202133249p:plain

今見ているピクセルの8近傍ピクセルのR値を取得する関数。

キモはTexel SizeノードとTexCoord。

Texel SizeはTexture Propertyと検索すれば使えるノードで、入力として与えたテクスチャのピクセルサイズを取得することができる。

TexCoordには今見ているピクセルのUV座標が入っている。

  • MF_8NeghbourLifeGame

f:id:ai_gaminglife:20190202133258p:plain

MF_8NeighborPixelで取得した8近傍ピクセルのR値を四捨五入。それと現在のピクセルのR値を使って現在のピクセルの生存・死亡・誕生をCustomノードを使って判定する。

今回採用したライフゲームのルールは、

  • 今死んでいる時周囲のピクセルがちょうど3つ生きていれば誕生する
  • 今生きている時周囲のピクセルが2か3つ生きていれば生存する
  • 今生きている時周囲のピクセルが1つ生きていれば過疎で死亡する
  • 今生きている時周囲のピクセルが4つ以上生きていれば過密で死亡する

Customノードの中身は以下の通り。

float1 count = 0;
if(N1 == 0){count++;}
if(N2 == 0){count++;}
if(N3 == 0){count++;}
if(N4 == 0){count++;}
if(N5 == 0){count++;}
if(N6 == 0){count++;}
if(N7 == 0){count++;}
if(N8 == 0){count++;}

if(thisPixel==0)
{
    if(count <= 1)
    {
        return float3(1.0, 1.0, 1.0);
    }
    if(count >= 4)
    {
        return float3(1.0, 1.0, 1.0);
    }
    else
    {
        return float3(0.0, 0.0, 0.0);
    }
}
else
{
    if(count == 3)
    {
        return float3(0.0, 0.0, 0.0);
    }
    else
    {
        return float3(1.0, 1.0, 1.0);
    }
}

ブループリントの中身

  • 構成

Static Mesh Actorを継承し、MeshにPlaneなりBoxなりを割り当てる。マテリアルには先程作成したM_LifeGameを設定。

ライフゲームの初期状態として与えるTexture2D型の変数、InitialTextureを用意。Instance Editableにチェックを入れて置くと便利。

  • Construction Script

f:id:ai_gaminglife:20190202133309p:plain

メッシュのDynamic Material Instanceを作成し変数LifeGameDMIとして保存しておく。続けてSet Texture Parameter Valueを使ってライフゲームの初期状態を与える。

  • Event Begin Play

f:id:ai_gaminglife:20190202133318p:plain

初期状態テクスチャと同じサイズのレンダーターゲットを2枚作成。それぞれにLifeGameDMIの結果を書き込む。

ここにハマりポイントが2つある。

1つはCreate Render Target 2Dするタイミング。

この関数をConstruction Scriptで実行すると正しく動作しないので、必ずBeginPlayで作成する。

もう1つはレンダーターゲットに描くマテリアルについて。

Draw Material to Render TargetするのはEmissive Colorの結果のみ。Base Colorの結果は一切関係ない。先程ライフゲームの結果は必ずEmissive Colorに繋がなければいけないといったのはこういうこと。

  • Event Tick

f:id:ai_gaminglife:20190202133335p:plain

FlipFlopを使って交互に実行する。

最後にClass SettingでTickが呼ばれる回数を好みに設定して完成。

まとめ

Customノードの中身を変えれば簡単に他のルールのライフゲームを再現できそう。Draw Material to Render Targetはかなり面白いことができるのでもうすこし遊んでみたい。

参考

qiita.com

それでも小学生にプログラミングの授業はあってほしい

某バズった刺身タンポポ記事、大学生時分の私には身に覚えがある事が多すぎて余りに頭の痛い話だった。

note.mu

運良く地方の国立理系に通わせて貰っているが、プログラミングの講義の質は本当に先生次第。基本に忠実に、かつ最新の規格に沿って教えてくれる先生もいれば、まだC言語しか触っていない学科で、第二回で世界に挨拶し、第三回で説明もなくjavaでクラスを作らされ、置いてけぼりの学生をよそに講義予定の30分前に「もういいよね?」帰宅する先生もいる。

他大の話だが、リストを自作し、それも含めて課題を提出したのに「ライブラリに頼るな」というありがたいフィードバックを頂いたというお話をTLで観測したこともある(出来が良すぎたからどこかからコピペしたとでも思われたんだろうか)。

教えられる学生側もまぁ問題はあって、エラーメッセージ読まない、サンプルを丸写しだけして的はずれなことをやってる、質問の意図が意味不明など……元記事の通り色々問題はある。(もしこの記事をガチ同級生が読んでたらスマン。これは特定個人宛のメッセージではないし、私の知る同級生は皆私にないもの沢山持ってて羨ましいって日々思ってる)

大学でさえこの有様だから、政府が進める「小学校でのプログラミング教育」なんぞ上手くいくわけがなく。断言できる。

文科省の考えるプログラミング教育

文科省の資料によると、プログラミング教育の目的は、「プログラミング的思考を育成」らしい。

まぁそんなの無理だと思う。

バイトで小学生に算数を教えることがあるが、絶望的に出来ない子はいる。掛け算すらままならないような彼らに「プログラミング的思考を育成」なんて目的でやるプログラミング教育は絶対にうまくいかない。彼らにプログラミング・コンピュータに対する苦手意識を植え込むだけ。彼らはいずれ「圏外でLINEが繋がらないバグをどうにかしろ!」とクレームを入れるリテラシー皆無のモンスタークレーマーとなるのだろう。

結局のところ、伝統などと理由をつけて元号公表を必死に遅らせようとする政治が主導するプログラミング教育に期待してはならないのである。

だが小学校のプログラミング教育に賛成

悲観的な話ばかりしてきたが、私は小学校でのプログラミング教育は是非してほしい、と考えている。ただし、プログラミング的思考の習得などという高尚な理由ではなく、プログラミングに夢を抱く純真無垢な少年少女の「その幻想をぶち壊す」目的でなら、である。

閑話休題

私が本格的にプログラミングの勉強を始めたのは2年半前。小学校の頃から漠然と抱き、高校生時に読んだ「社長が訊く」で絶対になりたいと決めたゲームプログラマーという夢。夢自体は持っていたがその夢に向けて動き始めたのはつい最近になってから。理由は単純で「プログラミングの学び方」を知らなかったから。

田舎者で小心者の私は身近にプログラマーがおらず、探すことも出来ず。結局大学進学で親元を離れるまでプログラミングはしなかった。それでもパソコンは大好きで、実家のオンボロPCでOfficeを弄ったり、ブラウザゲームを遊んだり、Firefoxにアドオンを大量に突っ込んでマルウェアをインストールしてしまい大目玉を食らったりしてきた。

大学で漸くプログラミングが学べそうな情報系に進学した。あとで聞くと、大学の同期もざっくりと「プログラミングが学べそうだから」という理由で弊学科に進学している方が多いらしい。

入学した時はこの学科に来るような人はプログラミングの経験の有無はあれど、皆PCスキルは一定以上持っていると思っていた。

しかし実際は物理化学では私より遥かにいい成績を取れる人がexcelをロクに使えない という現実。プログラミングは出来なくともOfficeが使えたaiくんはいつの間にやら「パソコン詳しいオタク」扱いされるようになったのである。

変に持ち上げられてしまった以上、それに見合うスキルを得たいと、何冊も技術書を買って、独学でプログラミングを学ぶようになった。ここでようやく私は、交友関係、社会性を生贄に捧げることで「プログラミング書いたことない」から「プログラミングかけなくはない」にクラスチェンジすることができたのだ。

プログラミングの向き不向きは早めに判断したほうがいい

長々自分語りしてしまったが、言いたい事は一つ。

「もっと早くプログラミング勉強したかった!!!!!!」   私はゲームを作るためなら大学でのキラキラな交友関係や社会性を投げ捨ても構わないと割り切り、独学で(勿論講義で貰った資料、課題も参考にしたが)プログラミングを学び、一人でミニゲームを作れるくらいにはなれた。

しかしもっと早くから勉強できていれば今頃とんでもないゲームが作れていたかもしれない。今頃ゲーム会社のスーパープログラマーになれていたかもしれない。そんな後悔は尽きない。(まあまあ長いこと勉強してるのにその程度かって指摘はやめて。心折れる)

大学に入るまでプログラミングをしてこなかったのは、結局のところきっかけがなかったから。そして学び方が分からなかったからなのだろう。

もし小学校でプログラミング教育が実現すれば、プログラミングの才能、面白さに目覚めた小学生が私の様な後悔をすることなくとんでもない3Dゲームを作るかもしれないし、その若さ故の柔軟な発想で世界を変えるサービスを開発するかもしれない。

逆に今のままであれば、プログラミングで薔薇色の未来が待っているという幻想を抱き情報系の大学、専門学校に進み、そこで自分には向いていないと悟り四年(二年)をつまらなく過ごしてしまう人が生産され続けるだろう。

悲しいことにプログラミングは向き不向きがはっきり出る技能。大人になってそれを判断するよりかは、もっと早い段階で判断させ、向かない人にはプログラミングへの幻想を捨ててもらい別の道に迷いなく進んでもらう。向いている人には授業を足がかりにその才能を早くに開花させてもらう。

これならばプログラミング教育に賛成できる。

締め

随分元記事と趣旨がずれた話をしてしまった。

こんな記事を書くことにしたのは(打ち消し) 自分のツイートがバズってブログ告知ぶら下げたらアクセス伸びたから乗っかって記事書こうとおもった 元記事にプログラミング教育なんて無理、といった話があったから。TLで稀に見かける、真剣に小・中学生向けのプログラミング教育機材開発に取り組んでいる方を見ていると、そんなに悲観しなくてもと思う。

いつかこういったプログラミング教育機材でプログラミングに目覚めた子から産まれた傑作ゲームが遊んでみたい。

2018振り返りと来年の話

本当はしっかりした記事を書きたかったのだが年末時間が取れなかったので振り返りのツイートで。年明け時間があればちゃんとした記事を書きたい。

来年は就活に卒研色々忙しくなりそうで、ブログ更新頻度も下がると思われ。それでも最低月1ブログ更新、そして大学卒業までにゲームリリースはしたいなあ。

Python 連番テキストファイルを結合する

test_0.txt, test_1.txt, test_2.txt, test_3.txt...と連番で用意したテキストファイルを順番通りに結合して、test.txtという一つのファイルとして書き出すプログラム。

import glob
import os.path


# ファイルの結合
def join_file(filePath):
    fileList = create_filelist(filePath)
    with open(filePath, 'wb') as saveFile:
        for f in fileList:
            data = open(f, "rb").read()
            saveFile.write(data)
            saveFile.flush()


# 連番ファイルのリスト作成
def create_filelist(filePath):
    pathList = []
    for index in range(100000):
        filename = file_indexed(filePath, index)
        # ファイルが存在しなければ終了
        if not os.path.exists(filename):
            break
        else:
            pathList.append(filename)

    return pathList


# ファイル名に指定のindex値をふる
def file_indexed(filePath, index):
    name, ext = os.path.splitext(filePath)

    return "{0}_{1}{2}".format(name, index, ext)


if __name__ == "__main__":
    join_file("testData/test.txt")  # 相対パス

まとめ

catでいいやん。

Ubuntu + VSCodeでAsciiDocを書く環境を整える

以前の記事ではWindows上でAsciidocを書く環境を整えたが、Ubuntuでも同じことがしたくなったので導入してみた。今回はその作業メモ。

検証環境

Rubyの導入

このサイトを参考にRubyを導入

qiita.com

Asciidoctorパッケージをインストール

Rubyを導入できればgemコマンドが叩ける。というわけで以下実行。

$ gem install asciidoctor
$ gem install --pre asciidoctor-pdf
$ gem install asciidoctor-pdf-cjk
$ gem install asciidoctor-diagram

VSCodeで.adocのリアルタイムプレビューを有効にする

拡張機能からAsciiDocと検索して最初に表示されるAsciiDoc pluginをインストール。

続いて、Settingを開き(ファイル→基本設定→設定)、検索欄にasciidocと入力。

Use_asciidoctor_jsのチェックを外す。(最近のAsciiDoc pluginの更新でこの設定の名前が変更になった。以前の設定のままでプレビューが効かなくなったらまずここを疑うべき。)

VSCodeを再起動する。

Ctrl + Shift + P → AsciiDoc Open Preview to the side を実行すればプレビューが出来るようになる。