テクニック
2008年11月01日
MacOS9フォーマットのフロッピーディスクをWindowsで読む方法
久しぶりにMacOSフォーマットのフロッピーディスクというものを渡されました。
「フロッピーディスクでデータのやり取りというのはもう止めましょう」という心の叫びもあったりするわけですが。せめて、MS-DOSフォーマットのフロッピーディスクだったら、まだいいのですが。
で、どうするか、ってことで、インターネットを使って検索しました。
いろいろと漁っていたところ、次のページを見つけました。
同じ目に遭っている方のために、リンクしておきます。
HFV Explorer (紹介ページ)
http://homepage3.nifty.com/toshi3/emu/hfvexplorer.html
ありがとうございます。↑の方。助かりました。
※ただし、USBドライブではダメという話です。対応はXPまでだし。
ちなみに、手元にVistaしかない、って場合やUSBドライブしかないときには、フリーソフトではなくなってしまいますが、MacDriveという手もあるようです。
MacDrive
http://www.e-frontier.co.jp/macdrive/7/
とりあえず1週間の試用期間版もあるので、これで回避するということも・・・。
「フロッピーディスクでデータのやり取りというのはもう止めましょう」という心の叫びもあったりするわけですが。せめて、MS-DOSフォーマットのフロッピーディスクだったら、まだいいのですが。
で、どうするか、ってことで、インターネットを使って検索しました。
いろいろと漁っていたところ、次のページを見つけました。
同じ目に遭っている方のために、リンクしておきます。
HFV Explorer (紹介ページ)
http://homepage3.nifty.com/toshi3/emu/hfvexplorer.html
ありがとうございます。↑の方。助かりました。
※ただし、USBドライブではダメという話です。対応はXPまでだし。
ちなみに、手元にVistaしかない、って場合やUSBドライブしかないときには、フリーソフトではなくなってしまいますが、MacDriveという手もあるようです。
MacDrive
http://www.e-frontier.co.jp/macdrive/7/
とりあえず1週間の試用期間版もあるので、これで回避するということも・・・。
2007年07月29日
【講座006】壁の跳ね返り
UpdateSpriteメソッドの前回の続きをみていきましょう。
int MaxX = graphics.GraphicsDevice.Viewport.Width
- myTexture.Width;
int MinX = 0;
int MaxY = graphics.GraphicsDevice.Viewport.Height
- myTexture.Height;
int MinY = 0;
図で理解した方がいいので、下図をみてください。
スプライトを表示する際には、スプライトの左上の座標を使うのですが、その最小値、最大値を、それぞれ(MinX, MinY)と(MaxX, MaxY)で表しています。
左上が(0,0)であることは、もういいとして、それを(MinX, MinY)に入れているのはわかると思います。右下の最大値の方をどうやって求めているか、ということが重要です。
ウィンドウの幅は、graphics.GraphicsDevice.Viewport.Widthで得られ、
ウィンドウの高さは、graphics.GraphicsDevice.Viewport.Heightで得られます。
そこから、スプライトの幅・高さ(myTexture.Width・myTexture.Height)をそれぞれ引いたところを(MaxX, MaxY)としているわけですね。
さて、続いて、if〜else if構文が2つ続きます。これはC#の書き方ですが、他の言語でも似たような書き方をよくします。プログラムでは非常に一般的なので、ちょっと勉強しましょう。
if (条件1)
{
処理1
}
else if (条件2)
{
処理2
}
となっているのですが、「条件1が満たされていれば(真だったら、とか、Trueだったら、という言い方をすることもあります。)、処理1を行います。もし、条件1が満たされていなかったら(偽だったら、とか、Falseだったら、といったりします。)、条件2を判断し、条件2が満たされていたら、処理2を行います。」という構文です。
この構文のポイントは、「処理1と処理2が同時に実行されることはなく、かつ、どちらも実行されないこともある」ということです。
さて、実際には何が書かれているのでしょうか。1つ目のif〜else if構文を見てみましょう。
if (spritePosition.X > MaxX)
{
spriteSpeed.X *= -1;
spritePosition.X = MaxX;
}
else if (spritePosition.X < MinX)
{
spriteSpeed.X *= -1;
spritePosition.X = MinX;
}
条件1は「spritePosition.X > MaxX」ですね。これは、「スプライトが右の壁をこえてしまったか?」を意味します。前回の講座でやりましたが、すでにspritePositionには、動く量が加えられていることに注意してください。
もし、スプライトが右の壁を越えてしまっていたら、スプライトのスピードは左右反転(この場合は右→左になるわけですが)しろ、となっています。これは、
spriteSpeed.X *= -1;
がそれを意味していますが、前回の+=と、同様に
x *= a;
と書かれていると、x に a を掛ける、ということを意味していますから、spriteSpeed.X に -1 が掛けられるということになります。より、具体的には、spriteSpeed.X が右の壁を越えてしまうときには、50.0が入っていたはずですから、spriteSpeed.X は -50.0 が入れられたのと同じことになります。
そして、右の壁を越えてしまってはいけませんから、
spritePosition.X = MaxX;
として、スプライトの位置を壁にぶつかった状態にしてしまいます。
続いて、条件1が満たされていなかったときには、条件2を判断します。条件2は「spritePosition.X < MinX」です。これは「左の壁を越えてしまったか?」を判断しています。これが満たされていた場合には、またスピードを左右逆転(今回の場合は、左→右への反転)して、スプライトの位置を左の壁にぶつかった状態にしています。
いかがでしょうか?同様のことがY軸方向でも行われます。
if (spritePosition.Y > MaxY)
{
spriteSpeed.Y *= -1;
spritePosition.Y = MaxY;
}
else if (spritePosition.Y < MinY)
{
spriteSpeed.Y *= -1;
spritePosition.Y = MinY;
}
こちらもX軸と同様ですから、同じように考えてみてください。ウィンドウの枠を壁に見立てて、スプライトが跳ね返る、という処理を行っていることがわかります。
これで、このサンプルの解説は終わりになりますが、ちょっと時間をもらって、その後、いくつか改造をしてみたいと思います。
int MaxX = graphics.GraphicsDevice.Viewport.Width
- myTexture.Width;
int MinX = 0;
int MaxY = graphics.GraphicsDevice.Viewport.Height
- myTexture.Height;
int MinY = 0;
図で理解した方がいいので、下図をみてください。
スプライトを表示する際には、スプライトの左上の座標を使うのですが、その最小値、最大値を、それぞれ(MinX, MinY)と(MaxX, MaxY)で表しています。
左上が(0,0)であることは、もういいとして、それを(MinX, MinY)に入れているのはわかると思います。右下の最大値の方をどうやって求めているか、ということが重要です。
ウィンドウの幅は、graphics.GraphicsDevice.Viewport.Widthで得られ、
ウィンドウの高さは、graphics.GraphicsDevice.Viewport.Heightで得られます。
そこから、スプライトの幅・高さ(myTexture.Width・myTexture.Height)をそれぞれ引いたところを(MaxX, MaxY)としているわけですね。
さて、続いて、if〜else if構文が2つ続きます。これはC#の書き方ですが、他の言語でも似たような書き方をよくします。プログラムでは非常に一般的なので、ちょっと勉強しましょう。
if (条件1)
{
処理1
}
else if (条件2)
{
処理2
}
となっているのですが、「条件1が満たされていれば(真だったら、とか、Trueだったら、という言い方をすることもあります。)、処理1を行います。もし、条件1が満たされていなかったら(偽だったら、とか、Falseだったら、といったりします。)、条件2を判断し、条件2が満たされていたら、処理2を行います。」という構文です。
この構文のポイントは、「処理1と処理2が同時に実行されることはなく、かつ、どちらも実行されないこともある」ということです。
さて、実際には何が書かれているのでしょうか。1つ目のif〜else if構文を見てみましょう。
if (spritePosition.X > MaxX)
{
spriteSpeed.X *= -1;
spritePosition.X = MaxX;
}
else if (spritePosition.X < MinX)
{
spriteSpeed.X *= -1;
spritePosition.X = MinX;
}
条件1は「spritePosition.X > MaxX」ですね。これは、「スプライトが右の壁をこえてしまったか?」を意味します。前回の講座でやりましたが、すでにspritePositionには、動く量が加えられていることに注意してください。
もし、スプライトが右の壁を越えてしまっていたら、スプライトのスピードは左右反転(この場合は右→左になるわけですが)しろ、となっています。これは、
spriteSpeed.X *= -1;
がそれを意味していますが、前回の+=と、同様に
x *= a;
と書かれていると、x に a を掛ける、ということを意味していますから、spriteSpeed.X に -1 が掛けられるということになります。より、具体的には、spriteSpeed.X が右の壁を越えてしまうときには、50.0が入っていたはずですから、spriteSpeed.X は -50.0 が入れられたのと同じことになります。
そして、右の壁を越えてしまってはいけませんから、
spritePosition.X = MaxX;
として、スプライトの位置を壁にぶつかった状態にしてしまいます。
続いて、条件1が満たされていなかったときには、条件2を判断します。条件2は「spritePosition.X < MinX」です。これは「左の壁を越えてしまったか?」を判断しています。これが満たされていた場合には、またスピードを左右逆転(今回の場合は、左→右への反転)して、スプライトの位置を左の壁にぶつかった状態にしています。
いかがでしょうか?同様のことがY軸方向でも行われます。
if (spritePosition.Y > MaxY)
{
spriteSpeed.Y *= -1;
spritePosition.Y = MaxY;
}
else if (spritePosition.Y < MinY)
{
spriteSpeed.Y *= -1;
spritePosition.Y = MinY;
}
こちらもX軸と同様ですから、同じように考えてみてください。ウィンドウの枠を壁に見立てて、スプライトが跳ね返る、という処理を行っていることがわかります。
これで、このサンプルの解説は終わりになりますが、ちょっと時間をもらって、その後、いくつか改造をしてみたいと思います。
2007年07月28日
【講座005】スプライトの速度
Updateメソッドに書き加えられたのは、次の1行でした。
UpdateSprite(gameTime);
これは、UpdateSpriteメソッドを実行する、ということを意味していますが、構造化プログラミング(って懐かしい言葉だな)では、できるかぎり大雑把にプログラムの構造を理解できるように、こうやって、詳細処理は別に書く、ということを行います。
ですから、実処理はUpdateSpriteに書かれているわけですね。そういうわけで、UpdateSpriteメソッドを見ていくわけですが、今回はスプライトを動かしている式を見てみます。たった、1行の解説ですが、XNAのゲームプログラミングでは重要なポイントになるはずです。
UpdateSpriteメソッドの最初の1行は次のようなものでした。
spritePosition += spriteSpeed *
(float)gameTime.ElapsedGameTime.TotalSeconds;
ここで、C#の文法を勉強しましょう。
x += a;
と書かれている場合には、xにはaが加えられます。
y -= b;
と書かれている場合には、yからはbが引かれます。これと同義の文は、
y += -b;
ということになります。たとえば、
x += 10;
であれば、xには10が加えられるし、
y += -3.7;
であれば、yには-3.7が加えられる、すなわち、yから3.7が引かれます。ということは、先の文を解釈すると、
「spritePositionに、spriteSpeed * (float)gameTime.ElapsedGameTime.TotalSecondsが加えられる」となるわけです。
spritePositionには初期値(0, 0)が設定されていて、Drawメソッドで、この位置にスプライトが描画されることを意味していました。このspritePositionに下線の部分の計算結果が足され、スプライトの場所が変わっていくことを意味しています。
ところで、spriteSpeedは(50.0, 50.0)を入れてありました。その先の(float)gameTime.ElapsedGameTime.TotalSecondsってなんでしょうか?それを理解しなければなりません。そこで、このElapsedGameTimeにカーソルを合わせて、[F1]でHelpを呼んでみます。
gameTime.ElapsedGameTime は最後にUpdateが実行されたときから、これまでに経過した時間を意味しているようです。で、ついでに言うと、TimeSpan構造体なので、そのプロパティに、TotalSecondsってのがありまして、秒の単位で値を返してくれるわけですから、「gameTime.ElapsedGameTime.TotalSecondsは、最後のUpdateからどのくらい経過したかを表している(秒単位)」となります。
また、TotalSecondsはdouble型で定義されています。speedSpriteのVector2クラスのメンバーは、float型なので、型がそろっていないと掛け算がうまくいかないことがあります。このため、(float)というのを付けて、speedSpriteと掛け算を行っているわけですね。
これは何を意味しているのでしょうか?実は、speedSpriteっていうスプライトの動くスピードを表している変数は、「秒速」を意味していた、ということになります。ですから、前回のUpdateから、今回のUpdateまでの経過時間を速度に掛け算することで、スプライトを動かす量(ピクセル数)を求めた、ということになります。
ゲームプログラミングにおいては、キャラクタをどのくらいのスピードで動かすのか、というのは非常に重要な問題です。昔、BASICでゲームを作ったことがある方ならば、
for t = 0 to 100: Next t
などという構文を挟んで、キャラクタの動かすスピードを調整したことがあるのではないでしょうか。こういった無駄なループを回して、時間調節を行うテクニックがあったのですが、コンピュータの性能が格段に上がった現在、このような方法を使うことは無意味です。そこで、算数の時間に習った
(距離)=(時間)×(速度)
を使って、動かすスピードを求めていく手法が現在では一般的です。
UpdateSpriteメソッドは、もう少し続きます。このまま、単に足すだけですと、ウインドウの外にスプライトが出てしまいますから、ウィンドウの枠が壁となって跳ね返るアルゴリズムが必要になってくるわけですね。それを次回に見ていきましょう。
UpdateSprite(gameTime);
これは、UpdateSpriteメソッドを実行する、ということを意味していますが、構造化プログラミング(って懐かしい言葉だな)では、できるかぎり大雑把にプログラムの構造を理解できるように、こうやって、詳細処理は別に書く、ということを行います。
ですから、実処理はUpdateSpriteに書かれているわけですね。そういうわけで、UpdateSpriteメソッドを見ていくわけですが、今回はスプライトを動かしている式を見てみます。たった、1行の解説ですが、XNAのゲームプログラミングでは重要なポイントになるはずです。
UpdateSpriteメソッドの最初の1行は次のようなものでした。
spritePosition += spriteSpeed *
(float)gameTime.ElapsedGameTime.TotalSeconds;
ここで、C#の文法を勉強しましょう。
x += a;
と書かれている場合には、xにはaが加えられます。
y -= b;
と書かれている場合には、yからはbが引かれます。これと同義の文は、
y += -b;
ということになります。たとえば、
x += 10;
であれば、xには10が加えられるし、
y += -3.7;
であれば、yには-3.7が加えられる、すなわち、yから3.7が引かれます。ということは、先の文を解釈すると、
「spritePositionに、spriteSpeed * (float)gameTime.ElapsedGameTime.TotalSecondsが加えられる」となるわけです。
spritePositionには初期値(0, 0)が設定されていて、Drawメソッドで、この位置にスプライトが描画されることを意味していました。このspritePositionに下線の部分の計算結果が足され、スプライトの場所が変わっていくことを意味しています。
ところで、spriteSpeedは(50.0, 50.0)を入れてありました。その先の(float)gameTime.ElapsedGameTime.TotalSecondsってなんでしょうか?それを理解しなければなりません。そこで、このElapsedGameTimeにカーソルを合わせて、[F1]でHelpを呼んでみます。
gameTime.ElapsedGameTime は最後にUpdateが実行されたときから、これまでに経過した時間を意味しているようです。で、ついでに言うと、TimeSpan構造体なので、そのプロパティに、TotalSecondsってのがありまして、秒の単位で値を返してくれるわけですから、「gameTime.ElapsedGameTime.TotalSecondsは、最後のUpdateからどのくらい経過したかを表している(秒単位)」となります。
また、TotalSecondsはdouble型で定義されています。speedSpriteのVector2クラスのメンバーは、float型なので、型がそろっていないと掛け算がうまくいかないことがあります。このため、(float)というのを付けて、speedSpriteと掛け算を行っているわけですね。
これは何を意味しているのでしょうか?実は、speedSpriteっていうスプライトの動くスピードを表している変数は、「秒速」を意味していた、ということになります。ですから、前回のUpdateから、今回のUpdateまでの経過時間を速度に掛け算することで、スプライトを動かす量(ピクセル数)を求めた、ということになります。
ゲームプログラミングにおいては、キャラクタをどのくらいのスピードで動かすのか、というのは非常に重要な問題です。昔、BASICでゲームを作ったことがある方ならば、
for t = 0 to 100: Next t
などという構文を挟んで、キャラクタの動かすスピードを調整したことがあるのではないでしょうか。こういった無駄なループを回して、時間調節を行うテクニックがあったのですが、コンピュータの性能が格段に上がった現在、このような方法を使うことは無意味です。そこで、算数の時間に習った
(距離)=(時間)×(速度)
を使って、動かすスピードを求めていく手法が現在では一般的です。
UpdateSpriteメソッドは、もう少し続きます。このまま、単に足すだけですと、ウインドウの外にスプライトが出てしまいますから、ウィンドウの枠が壁となって跳ね返るアルゴリズムが必要になってくるわけですね。それを次回に見ていきましょう。