SVX日記
2004-08-04(Wed) 安城の友人O
やはり時間が余ったので、ガキの頃に住んでいた三河安城駅近くを車で回る。ついでにSVXに乗って初めてのオイル交換をする。なんとなく、アイドルがバラついてきた感じがしたので、3,000kmには若干早いものの交換したのだが、あまり変化ナシ。気のせいか?
オイル交換後、友人Oの家へ。乗っけて、大須へ向かう。やはり昔の友人は遠慮がいらなくてよい。昼前頃に大須に着く。大須は名古屋のいわば秋葉原。適当にショップを回りながら、目当てのボントンへ。ボントンは名古屋のいわば秋月電子!? 昔から電子工作に興味があったものの、ジャンク屋の部品を品定めできるほどではなかったので、興味本位で見ていただけだったのだが、今回はわかる!! 意外といろんなものが置いてあったんだなぁ。これなら、名古屋に引っ越してもやっていけるかも。
秋葉であまり見ないのに、コチラで意外と見た物は、スイッチング電源とアナログメータ。特にボントンのアナログメータは多種多様でひととおりチェックしてしまった。秋葉にもあるけど、キレイで高いんだよね。ココには汚いけど数百円で買えるものばかり。とりあえず、目的はないけど、ピコピコ動かしてみたいので500円で2個ほど購入。うまくいったら、今度来た時に大量に買って松本零士ごっこしてみたいところだ。
昼になったので、軽くメシを食うべく、名古屋名物コメダコーヒーへ。向かう途中、妙にレトロなスバルのディーラー!?を発見。ちょっとセピアにしてみたけど、いかがだろうか? つーか、この店なにを売っているんだろう。よくわからん。コメダコーヒーでは友人Oがクドいソフトクリームデニッシュ(!?)を食っていたが、こういうのを見て驚くオレは名古屋人の気が抜けてきているのだろうか。
驚き!! パックマンのオリジナル筐体が現存しているとは!! 昔のテーブル筐体のディスプレイが小さかったことにも驚き、そのレバーの感触も今とは違うことにも驚いた。タイトーのスピードレースって昔よく見たけど、そのまんまの姿で置いてあるってのもスゴいし、プレイしてもハンドルがシッカリ動くし。
タイトーのダライアス筐体3連発もスゲえ。ダライアスは秋葉のトライアミューズメントタワーでやってたので、久々にダライアス2をプレイ。あっけなくウニの先あたりでカメにやられてしまったが、懐かしい。友人Oは久々にゼビウスしてたが、軽くシオナイトまで行ってたりして、意外と昔の腕って残ってるみたいだ。できれば、3画面筐体にはニンジャウォーリアーズが入っててほしかったとか、ループレバー筐体には怒号層圏でなく、初代IKARIがよかったとか思ったが、それは次回に来たときに期待しよう。
2007-08-04(Sat) SVX車検終了
久々のエントリ。電車の中でmaveを作りこみまくっていて、更新する余裕がない。んがしかし、もうすっかり実用域。バグを踏むと容易に落ちるが、バグの位置を把握しちまってるから、直すよりも避けちゃう。仕事のメールサバき効率が20%は向上した気がするな。20%とはいえ、仕事の8割がメールサバきなので、快適さは精神安定性上にも重要だ。
と、最近、ソフトバンクが安いと聞き、長らく使っていたwillcomをアッサリと裏切って、鞍替えした。ソフトバンクを悪く言うヤツは多いが、フタを開けてみれば端末の魅力は一番だし、スーパーボーナスという売り方も非常に理にかなっていて、納得なのである。
で、車検の費用だが、前回に引き続き、今回も30万コースである。今回はエアコンのモータの2万が大きいとはいえ、パーツ代こそ3.5万に収まったが、エンジンの裏からオイルが漏れていたので、それだけで工賃が6万弱、ブーツの交換と塗装込みで14万超え、結局28万弱。
2009-08-04(Tue) ワイヤレスヘッドホンRe-Birth・完
昨日、完成した電源基板を送信機に実装する。送信機本体に実装済みのジャックから、新設した電源基板の入力へとひっぱり込みつつ、新設した電源基板の出力(9V)を、送信機本体の正規の電源ラインにつっ込む形に実装する必要がある。また、送信機本体に実装済みのジャックは、心棒が微妙に太いタイプなので、これを通常タイプに交換する必要がある。
一番の問題は、送信機本体に実装済みのジャックは、プリント基板として正規の電源ラインに直付けしてあるので、それを切り離す必要がある、ということ。でないと、今回作った電源降圧回路を経由せず、接続したアダプタの電圧が正規の電源ラインに直接に作用してしまう。
極めてややこしいが、プリント基板のジャック取り付け部のパターンをカッターで切りつけ、正規の電源ラインから切り離しつつ、そこからの入力を新設した電源基板の入力に接続、そちらからの出力を正規の電源ラインに接続、という、ややこしい作業が必要になった。ああ、ややこしい。
これにて、本体を立てると電源オン、寝かすと電源オフという「石油ストーブみたい化」および「適当なアダプタを挿してもOK化」の完了である。早速、適当なACアダプタを挿してサイヴァリアである。レッツBUZZ。
相変わらず到達ステージは4、ときどき5、という晴れのち曇り状態であるが、到達ステージに対する到達レベルが徐々に上がってきている。ステージ6までにレベル100に行けるんじゃないか? ミディアムユニットは攻略記事が少ないせいで、それが普通なのかよくわからんが。
小1時間遊んで、電源オフのために本体を寝かしたところ、指に異様な感覚が……3端子レギュレータがチンチンになっとる……しまった、アダプタの電源電圧が高すぎたか。(15V - 9V) x 300mA(たぶん) = 1.8W。放熱器なしでのTA7805Sの最大許容損失は2.0W。ギリギリだったわ。TA7805Sの電圧ドロップは2Vだから、11V以上、12Vのアダプタを使うのが無難なようだ。
2022-08-04(Thu) CoffeeScriptにて回転機能をMixinにより実装す
意外と飽きずにオリジナルのシューティングの製作をポチポチと進めているのだが、考えれば考えるほど、既存のシューティングに対する気付きが増えていく。
例えば、R-TYPEは初見でも1面はクリアさせたい作りなんだな、とか、ダライアスはボス以外の作りは適当だな、とかである。反面、ゼビウスは「最初は偵察機が登場する」とか「有人機は自殺的攻撃をしない」とか考えてあることに驚く。そうだよな。それは世界感を感じさせるために有効だよな。
今回、自分は「ストーリ」を強く感じさせるゲームにしたいので、単に思いつきで敵を作るのではなく、それなりの理由に基づいて登場、行動させたい。そうなると、最初は偵察機だし、その後はミサイル攻撃かな、とか思うわけだ。
で、ミサイルを作ったのだが、誘導したくなってしまい、斜めに飛ばしたくなってしまった。すると、回転機能が必要になる。先日のテトランはプリレンダだったが、汎用性を考えればリアルタイムレンダを実装するべきだ。しかもキャッシュ付きで、できるだけ軽く。
class Plane # 描画面
class Obj extends Plane # オブジェクト(スプライト)
class Ship extends Obj # 自機
class Enemy extends Obj # 敵
class MissileA extends Enemy # ミサイル
class Fixed extends Enemy # 地形に固定された敵
class ReconA extends Fixed # 偵察機
回転するのは敵に限らず、あらゆるオブジェクトが回転可能にできるべきだ。しかし、そうすると多重継承が必要になってしまう。それを避けるには、一番の根っこであるObjクラスに実装してしまう方法も考えられるが、それは気が進まない。必要に応じて回転機能が追加できるのが望ましい。
#---------------------------------------------------------------
#
# クラスの Mixin を可能にする
#
# https://coffeescript-cookbook.github.io/chapters/classes_and_objects/mixins
#
mixOf = (base, mixins...) ->
class Mixed extends base
for mixin in mixins by -1
for name, method of mixin::
Mixed::[name] = method
Mixed
class Rotnscl # 回転拡大縮小機能
class RmissileA extends mixOf Enemy, Rotnscl # 敵+回転拡大縮小機能
次は、回転パターンのキャッシュについて考える。処理負荷的にリアルタイムレンダは可能な見通しだが、毎回、回転パターンを作るのは無駄なので、一度作った回転パターンは残しておき、二度目からは勝手にそれを使うようにしたい。つまりはキャッシュだ。
キャッシュはどう実装されるべきか、といえば、そりゃオブジェクトタイプ、パターン、角度毎に残しておくべきで、個体(インスタンス)毎に行うべきではない。つまり、クラス変数に残しておくべきだ。クラス変数はCoffeeScriptにはあるのかしらん……と、思ったら、ちょっと微妙ではあるが、ある。
クラスの中、メソッドの外に「@xxx」を定義しておき、メソッド内からは「@constructor.xxx」でアクセスする。ただし、利用はそのクラスのみに閉じ、継承したクラスからはアクセスできない。今回の場合、その仕様で問題ないが。
つうわけで、こんな感じで気持ちよくグルグルと回転している。いや、canvas要素には、ネイティブな回転機能はあるようなのだが、それはそれとして、実装するのが楽しいのだから、これでいいのだ。コードはこんな感じ。
#---------------------------------------------------------------
#
# 回転拡大縮小可能オブジェクト(mixin用)
#
class Rotnscl
rotnscl: (pats, n, v, t, w = null, h = null, dx = null, dy = null) ->
pat = pats[n]
w ||= pat.width; dx ||= -(w >> 1)
h ||= pat.height; dy ||= -(h >> 1)
return(rpat) if(rpat = @constructor.rpats[rsym = "#{n}_#{t}_#{v}_#{w}_#{h}_#{dx}_#{dy}"])
unless(pdat = @constructor.pdats[psym = "#{n}"])
src_canvas = document.createElement('canvas')
src_canvas.width = pat.width
src_canvas.height = pat.height
src_context = src_canvas.getContext('2d')
src_context.drawImage(pat, 0, 0)
pdat = @constructor.pdats[psym] = src_context.getImageData(0, 0, w, h).data
rot_canvas = document.createElement('canvas')
rot_canvas.width = w
rot_canvas.height = h
rot_context = rot_canvas.getContext('2d')
rxys = Vec.v2vxy(v, t); hxys = Vec.v2vxy(v + 32 & 0x3F, t); vxys = Vec.v2vxy(v + 48 & 0x3F, t)
_vx8 = dx * rxys[1] - dy * rxys[0] - (dx << 8)
_vy8 = -(dx * rxys[0] + dy * rxys[1]) - (dy << 8)
w8 = w << 8; pw = pat.width
for y in [0...h]
_hx8 = _vx8; _hy8 = _vy8
for x in [0...w]
_hx8 += hxys[0]; _hy8 += hxys[1] # 横方向加算
continue if(_hx8 < 0 or _hx8 > w8)
p = ((_hy8 >> 8) * pw + (_hx8 >> 8)) << 2
continue unless(pdat[p] + pdat[p + 1] + pdat[p + 2]) # 黒は透過
rot_context.fillStyle = "rgb(#{pdat[p]}, #{pdat[p + 1]}, #{pdat[p + 2]})"
rot_context.fillRect(x, y, 1, 1)
_vx8 += vxys[0]; _vy8 += vxys[1] # 縦方向加算
return(@constructor.rpats[rsym] = rot_canvas)
cache_status: ->
console.log([@constructor.name, Object.keys(@constructor.pdats).length, Object.keys(@constructor.rpats).length].toString()) if(tsc % 60 == 0)
#---------------------------------------------------------------
#
# 回転オブジェクトサンプル
#
class Rsample extends mixOf Obj, Rotnscl
Plane.image_src(@pats = [
'images/rsample0.png' # 0: 46 x 46
])
@pdats = {}; @rpats = {}
constructor: (_s, x, y) ->
super(_s, x, y)
draw: ->
n = 0 # パターンナンバ
v = (tsc >> 2) % 64 # 角度
t = 0 # 倍率
rpat = @rotnscl(@constructor.pats, n, v, t)
@context.drawImage(rpat, @pos_x, @pos_y)
d0: ->
@cache_status()