using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace MainMap2DTest
{
///
/// This is a game component that implements IUpdateable.
///
public class MainMap : Microsoft.Xna.Framework.GameComponent
{
// ゲームクラスの宣言
private Game1 thisGame = null;
// 共通クラスの宣言
private Common common = null;
// 入力管理クラスの宣言
private InputManager inputManager = null;
// メインマップ画像の宣言
private Texture2D mainMap01 = null;
// コンソール表示領域の設定(x座標、y座標、幅、高さ)
private Rectangle consoleRec = Rectangle.Empty;
public Rectangle ConsoleRec
{
get
{
return consoleRec;
}
}
// マップ表示位置の宣言
private Vector2 mapViewPos = Vector2.Zero;
public Vector2 MapViewPos
{
get
{
return mapViewPos;
}
}
// マップ表示スケールの宣言
private Vector2 mapViewScale = Vector2.Zero;
public Vector2 MapViewScale
{
get
{
return mapViewScale;
}
}
// 最奥の縮小率(奥の画像を縮小して遠近感を演出する)
private float minRate = 0;
public float MinRate
{
get
{
return minRate;
}
}
// コンストラクタ
public MainMap(Game game, Common common, InputManager inputManager)
: base(game)
{
// TODO: Construct any child components here
thisGame = (Game1)game;
this.common = common;
this.inputManager = inputManager;
}
///
/// Allows the game component to perform any initialization it needs to before starting
/// to run. This is where it can query for any required services and load content.
///
public override void Initialize()
{
// TODO: Add your initialization code here
// コンソール表示領域の初期設定(x座標、y座標、幅、高さ)
consoleRec = new Rectangle(0, 0, 800, 600);
// マップ表示位置の初期設定
mapViewPos = new Vector2(0, 0);
// マップ表示スケールの初期設定
mapViewScale = new Vector2(2.0f, 2.0f * (9.0f / 16.0f));
// 最奥の縮小率の初期設定(奥の画像を縮小して遠近感を演出する)
minRate = 0.3f;
base.Initialize();
}
///
/// Allows the game component to update itself.
///
/// Provides a snapshot of timing values.
public override void Update(GameTime gameTime)
{
// TODO: Add your update code here
// 上キーで上スクロール
if (inputManager.KeyboardState.IsKeyDown(Keys.Up))
mapViewPos.Y--;
// 下キーで下スクロール
if (inputManager.KeyboardState.IsKeyDown(Keys.Down))
mapViewPos.Y++;
// 左キーで左スクロール
if (inputManager.KeyboardState.IsKeyDown(Keys.Left))
mapViewPos.X--;
// 右キーで右スクロール
if (inputManager.KeyboardState.IsKeyDown(Keys.Right))
mapViewPos.X++;
// Pキーで拡大
if (inputManager.KeyboardState.IsKeyDown(Keys.P))
{
// 拡大後のスケールを算出
Vector2 newMapViewScale = mapViewScale;
newMapViewScale.X += 0.02f;
newMapViewScale.Y = newMapViewScale.X * (9.0f / 16.0f);
// 上限チェック
if (newMapViewScale.X < 5.0f && newMapViewScale.Y < 5.0f)
{
// 拡大前の中央座標を算出
Vector2 oldCenter;
oldCenter.X = (((float)consoleRec.Width * minRate) / 2.0f) / mapViewScale.X;
oldCenter.X += ((float)consoleRec.Width / 2.0f) / mapViewScale.X;
oldCenter.Y = mapViewPos.Y + ((float)consoleRec.Height / 2.0f) / mapViewScale.Y;
// 拡大後の中央座標を算出
Vector2 newCenter;
newCenter.X = (((float)consoleRec.Width * minRate) / 2.0f) / newMapViewScale.X;
newCenter.X += ((float)consoleRec.Width / 2.0f) / newMapViewScale.X;
newCenter.Y = mapViewPos.Y + ((float)consoleRec.Height / 2.0f) / newMapViewScale.Y;
// 表示開始座標の修正
mapViewPos.X += oldCenter.X - newCenter.X;
mapViewPos.Y += oldCenter.Y - newCenter.Y;
// 拡大後のスケールを設定
mapViewScale = newMapViewScale;
}
}
// Lキーで縮小
if (inputManager.KeyboardState.IsKeyDown(Keys.L))
{
// 縮小後のスケールを算出
Vector2 newMapViewScale = mapViewScale;
newMapViewScale.X -= 0.02f;
newMapViewScale.Y = newMapViewScale.X * (9.0f / 16.0f);
// 下限チェック
if (newMapViewScale.X >= 0.3f && newMapViewScale.Y >= 0.3f)
{
// 縮小前の中央座標を算出
Vector2 oldCenter;
oldCenter.X = (((float)consoleRec.Width * minRate) / 2.0f) / mapViewScale.X;
oldCenter.X += ((float)consoleRec.Width / 2.0f) / mapViewScale.X;
oldCenter.Y = mapViewPos.Y + ((float)consoleRec.Height / 2.0f) / MapViewScale.Y;
// 縮小後の中央座標を算出
Vector2 newCenter;
newCenter.X = (((float)consoleRec.Width * minRate) / 2.0f) / newMapViewScale.X;
newCenter.X += ((float)consoleRec.Width / 2.0f) / newMapViewScale.X;
newCenter.Y = mapViewPos.Y + ((float)consoleRec.Height / 2.0f) / newMapViewScale.Y;
// 表示開始座標の修正
mapViewPos.X += oldCenter.X - newCenter.X;
mapViewPos.Y += oldCenter.Y - newCenter.Y;
// 縮小後のスケールを設定
mapViewScale = newMapViewScale;
}
}
base.Update(gameTime);
}
// メインマップ関連呼び出し
public void Load(ContentManager content)
{
mainMap01 = content.Load("MainMap01");
}
// メインマップ関連表示
public void Draw(SpriteBatch spriteBatch)
{
// ラスタースクロール
for (int i = 0; i < (float)consoleRec.Height / mapViewScale.Y; i++)
{
// 奥行きに応じて縮小率を算出(minRate = 0.3 の場合、scaleDownRate = 0 〜 0.3 の範囲)
float scaleDownRate = ((float)i / ((float)consoleRec.Height / mapViewScale.Y)) * minRate;
// 表示開始座標の設定
Vector2 pos = new Vector2((float)consoleRec.X, (float)consoleRec.Y + (float)i * mapViewScale.Y);
// 抽出元画像領域の設定
int sourceRecPosX = (int)mapViewPos.X + (int)((((float)consoleRec.Width * scaleDownRate) / 2) / mapViewScale.X);
int sourceRecPosY = (int)mapViewPos.Y + i;
int sourceRecWidth = (int)(((float)consoleRec.Width / (1.0 - (minRate - scaleDownRate))) / mapViewScale.X);
int sourceRecHeight = (int)mapViewScale.Y + 1;
Rectangle sourceRectangle = new Rectangle(sourceRecPosX, sourceRecPosY, sourceRecWidth, sourceRecHeight);
// 表示スケールの設定
Vector2 drawScale = new Vector2(((float)consoleRec.Width / (float)sourceRectangle.Width), 1.0f);
// 1ライン毎に表示する
spriteBatch.Draw(mainMap01, pos, sourceRectangle, Color.White, 0, Vector2.Zero, drawScale, SpriteEffects.None, 1.0f);
}
// メッセージ表示
spriteBatch.DrawString(common.Font1, "mapViewPos.X = " + mapViewPos.X, new Vector2(10, 500), Color.Red);
spriteBatch.DrawString(common.Font1, "mapViewPos.Y = " + mapViewPos.Y, new Vector2(10, 525), Color.Red);
spriteBatch.DrawString(common.Font1, "mapViewScale.X = " + mapViewScale.X, new Vector2(10, 550), Color.Red);
spriteBatch.DrawString(common.Font1, "mapViewScale.Y = " + mapViewScale.Y, new Vector2(10, 575), Color.Red);
// 中央を示す
spriteBatch.DrawString(common.Font1, "L", new Vector2(consoleRec.Width / 2 + consoleRec.X, consoleRec.Height / 2 + consoleRec.Y), Color.Red);
spriteBatch.DrawString(common.Font1, "L", new Vector2(consoleRec.Width / 2 + consoleRec.X, consoleRec.Height / 2 + consoleRec.Y), Color.Red, MathHelper.ToRadians(90.0f), new Vector2(0, 0), new Vector2(1.0f, 1.0f), SpriteEffects.None, 0);
spriteBatch.DrawString(common.Font1, "L", new Vector2(consoleRec.Width / 2 + consoleRec.X, consoleRec.Height / 2 + consoleRec.Y), Color.Red, MathHelper.ToRadians(180.0f), new Vector2(0, 0), new Vector2(1.0f, 1.0f), SpriteEffects.None, 0);
spriteBatch.DrawString(common.Font1, "L", new Vector2(consoleRec.Width / 2 + consoleRec.X, consoleRec.Height / 2 + consoleRec.Y), Color.Red, MathHelper.ToRadians(270.0f),new Vector2(0, 0),new Vector2(1.0f, 1.0f),SpriteEffects.None, 0);
}
}
}