3月, 2012 のアーカイブ

2Dゲームで画像を用意する時、パフォーマンスの面からゲームで使う画像を大きな画像に纏める時があります。アニメーションの実装時も同じく一つの画像にアニメーションで使う全画像(コマ)を一つの大きな画像にまとめ、一部分だけ描画します。

 

例を上げると、以下ような画像の1コマ分だけを描画します。画像はXNAのスターターキットから借りています。

 

上の画像の大きさは480 x 48なので、1コマ 48 x 48で横に10コマとして扱います。

実装にはまず、アニメーション用のクラスを宣言し、必要な変数とコンストラクタを書きます。

class Sprite
{
Texture2D m_texture;    // アニメーションを含んだ画像
Vector2 m_position;     // 位置
Point m_frameSize;      // 1コマの大きさ
Point m_currentFrame;   // 現在どのフレームかを表す
Point m_sheetSize;      // アニメーションが縦横何コマあるか
float m_timer;          // アニメーション用タイマー
float m_updateInterval; // 何秒ごとに次のコマに進むか

public Sprite(Texture2D tex, Vector2 pos, Point frameSize,
Point sheetSize, float updateInterval)
{
m_timer          = 0.0f;
m_texture        = tex;
m_position       = pos;
m_frameSize      = frameSize;
m_currentFrame   = new Point(0, 0);
m_sheetSize      = sheetSize;
m_updateInterval = updateInterval;
}

次に更新処理を実装します。現在描画するコマと、次のコマに進むかどうかの判断はこのメソッド内で実装しています。行う事は一定の時間が過ぎたら次のコマに進むだけで、それ以降は一番右のコマか、一番下のコマを通り過ぎた時の処理を行っているだけです。

 

なお、上記で紹介したサンプル画像では全ての画像が横並びでしたが、アニメーション用の画像ではよく大きさが縦横四角になっている場合も多く(480 x 480など)、その場合は横にコマを進めるだけでなく、縦にも進める必要があるので、その処理も実装しています。

public virtual void Update(float delta)
{
// タイマーを更新
m_timer += delta;

// もし次のコマに進む時間が過ぎたら
if (m_timer > m_updateInterval)
{
// タイマーをリセット
m_timer = 0.0f;

// 右に1コマ進む
m_currentFrame.X++;

// もしX軸のコマ数が、画像にあるコマ数を超えていた場合
if (m_currentFrame.X >= m_sheetSize.X)
{

// 一番左のコマへ変更
m_currentFrame.X = 0;

// 一段下のコマに変更
m_currentFrame.Y++;

if (m_currentFrame.Y >= m_sheetSize.Y)
{

// 一番上の段に変更
m_currentFrame.Y = 0;
}
}
}
}

次に描画処理です。このクラスでの描画処理は、SpriteBath.Draw()のオーバーロードの一つを使用し、第3引数に描画する画像の中で描画する範囲をRectangle型で指定します。

public virtual void Draw(SpriteBatch sp)
{
// 描画するコマを計算する
Rectangle texRect = new Rectangle(m_currentFrame.X * m_frameSize.X,
m_currentFrame.Y * m_frameSize.Y,
m_frameSize.X,
m_frameSize.Y);

// 現在のコマを描画する
sp.Draw(m_texture, m_position, texRect, Color.White,
0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
}

後は画像を読み込み、Spriteクラスを使用して描画するだけです。今回のサンプルコードはGame1クラス内で書かれています。

Sprite player;

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);

Texture2D playerTex = Content.Load<Texture2D>("player");
player = new Sprite(playerTex, new Vector2(200, 200),
new Point(48, 48), new Point(10, 1), 0.06f);
}

protected override void Update(GameTime gameTime)
{
float delta = (float)gameTime.ElapsedGameTime.TotalSeconds;
player.Update(delta);
base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

spriteBatch.Begin();
player.Draw(spriteBatch);
spriteBatch.End();

base.Draw(gameTime);
}

以上で実装は終わりです。実装後は以下のようになります。

 

 

もしアニメーションの速度が速すぎたり、遅すぎたら、Spriteクラスのコンストラクタの第5引数を変更してみてください。なお、現在の実装ではアニメーションのコマの数と、1コマの大きさは自分で計算してSpriteクラスに渡す必要があります。

またまた短めのメモです。今回は、現在の画面の解像度を獲得する方法をメモります。

 

解像度を獲得する時にgraphics.PreferredBackBufferWidthのアクセサを使用して獲得する事も出来ますが、この場合フルスクリーンは考慮されず、フルスクリーンに切り替えた時に色々とずれる可能性があります。

なので、今回はGraphicsDevice.PresentationParameters.BackBufferWidthのアクセサを使用します。これを使うことにより、呼び出した時点での解像度を獲得でき、それを元に画像を配置出来ます。

 

ちなみに、使用するとこんな感じのコードになります。

// 設定されている解像度を獲得する
//screenWidth = graphics.PreferredBackBufferWidth;
//screenHeight = graphics.PreferredBackBufferHeight;

// 現在の解像度を獲得する
screenWidth = GraphicsDevice.PresentationParameters.BackBufferWidth;
screenHeight = GraphicsDevice.PresentationParameters.BackBufferHeight;

 

以上です・・・短っ!!orz

 

今回は最近よくある、短めで基本的なメモです。

 

キーボードでの入力確認のあれこれは既に書きましたが、今回はXNAの昨日を使用して現在押されている全てのキーを獲得する方法をメモります。

 

まず、現在のキーボードの状態を獲得します。獲得したKeyboardStateから、GetPressedKeys()メソッドを呼びます。このメソッドは、KeyboardStateから押されている全てのキーをKeyの配列(Key[])として返します。

 

KeyboardState keyState = Keyboard.GetState();

// 押されているキーの一覧を取得
Keys[] currentKeys = keyState.GetPressedKeys();

 

これで全てなので、一応確認用に押されているキーを描画します。

 

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

// 押されているキーの一覧を取得
KeyboardState keyState = Keyboard.GetState();
Keys[] currentKeys = keyState.GetPressedKeys();

spriteBatch.Begin();

// 押されているキーの一覧を表示する
int ySpace = 25;
int y = 1;

for (int i = 0; i < currentKeys.Length; ++i)
{
spriteBatch.DrawString(font, currentKeys[i].ToString(), new Vector2(20.0f, y), Color.White);
y += ySpace;
}

spriteBatch.End();
base.Draw(gameTime);
}
 

 

こんな感じになります。

 

以上です。

前に公開したTetrangleが晋遊舎 iP誌に掲載されました!わーい!

 

まさか日本の雑誌に載るとは思ってなかったのでかなり驚きました。

掲載された部分の画像貼ってみます

 

 

これでTetrangleの事が雑誌に載ったのは2回目ですので、かなりうれしい。

 

雑誌を読んだ方が居るかわかりませんが、興味を持ってやってみようと思った方で起動に問題があった方は、お手数ですが、Vectorに上がっている最新版を試してみてください m_ _m

 – http://www.vector.co.jp/soft/winnt/game/se494765.html

 

おまけですが、前回雑誌に少しだけ載ったときの画像が何処にも無いので、ここに置いてみます(主に自己満足の為に XD)

 

 

そのうちXBOXを買ってXBLIGで出したいなぁ・・・