ソースファイル一式 source code
17-LDAct10.zip
MITライセンスです。
This software/source is licensed under the MIT License, see LICENSE.txt.
LDAct10.cs
//	#17 見下ろし型アクション10 LD Action10 2017/12/13 T.Umezawa
using System;
using System.Collections.Generic;
class Util
{
	public static Random		sRnd = new Random();
	public static int GetAngle4i( double dx, double dy )
	{
		return( (int)( ( GetAngle360( dx, dy ) + 45 ) / 90 ) & 0x03 );
	}
	public static double GetAngle360( double dx, double dy )
	{
		double	r = Math.Atan2( dy, dx ) * 180 / Math.PI;
		if( r < 0 ){
			r += 360;
		}
		return( r );
	}
	public static int Rnd( int mx )
	{
		return( sRnd.Next( mx ) );
	}
}
class Map
{
	public static readonly int	WIDTH = 31;
	public static readonly int	HEIGHT = 21;
	public static readonly byte	FLOOR  = 0;
	public static readonly byte	FLAG   = 1;
	public static readonly byte	BLOCK  = 2;
	public static readonly byte	WALL   = 3;
	static System.Drawing.SolidBrush	sSBFloor = new System.Drawing.SolidBrush( System.Drawing.Color.FromArgb( 0x22, 0x00, 0x00 ) );
	static System.Drawing.Bitmap[]	sBM = {
		new System.Drawing.Bitmap( "flag.png" ),
		new System.Drawing.Bitmap( "block.png" ),
		new System.Drawing.Bitmap( "wall.png" ),
	};
	public static byte[,]		sMap = new byte[ HEIGHT, WIDTH ];
	public static int CountNeighbor( int mx, int my, byte v )
	{
		int		r = 0;
		if( sMap[ my - 1, mx ] == v )	r++;
		if( sMap[ my + 1, mx ] == v )	r++;
		if( sMap[ my, mx - 1 ] == v )	r++;
		if( sMap[ my, mx + 1 ] == v )	r++;
		return( r );
	}
	public static void create()
	{
		Array.Clear( sMap, 0, sMap.Length );
		for( int y = 0; y < HEIGHT; y++ ){
			sMap[ y, 0 ] = WALL;
			sMap[ y, WIDTH - 1 ] = WALL;
		}
		for( int x = 0; x < WIDTH; x++ ){
			sMap[ 0, x ] = WALL;
			sMap[ HEIGHT - 1, x ] = WALL;
		}
		for( int y = 2; y < HEIGHT - 2; y += 2 ){
			for( int x = 2; x < WIDTH - 2; x += 2 ){
				sMap[ y, x ] = BLOCK;
			}
		}
		//	迷路作成
		for( int y = 2; y < HEIGHT - 2; y += 2 ){
			for( int x = 2; x < WIDTH - 2; x += 2 ){
				if( isWall( x, y ) ){
					continue;
				}
				int		a = Util.Rnd( 4 );
				if( a == 0 )	sMap[ y - 1, x ] = BLOCK;
				if( a == 1 )	sMap[ y + 1, x ] = BLOCK;
				if( a == 2 )	sMap[ y, x - 1 ] = BLOCK;
				if( a == 3 )	sMap[ y, x + 1 ] = BLOCK;
			}
		}
		sMap[ 3, 27 ] = FLAG;
	}
	public static int Get( int x, int y )
	{
		return( sMap[ (int)( y / 256 ), (int)( x / 256 ) ] );
	}
	public static void Set( int x, int y, byte v )
	{
		sMap[ (int)( y / 256 ), (int)( x / 256 ) ] = v;
	}
	public static bool IsCenter( int x, int y )
	{
		return( ( x & 0xff ) == 0x80 && ( y & 0xff ) == 0x80 );
	}
	static bool isWall( int x, int y )
	{
		return( sMap[ y - 1, x ] != 0 ||
		        sMap[ y + 1, x ] != 0 ||
		        sMap[ y, x - 1 ] != 0 ||
		        sMap[ y, x + 1 ] != 0 );
	}
	public static void draw( System.Drawing.Graphics g )
	{
		for( int y = 0; y < HEIGHT; y++ ){
			for( int x = 0; x < WIDTH; x++ ){
				if( sMap[ y, x ] == 0 ){
					g.FillRectangle( sSBFloor, x * Unit.DOT, y * Unit.DOT, Unit.DOT - 1, Unit.DOT - 1 );
				}else{
					g.DrawImage( sBM[ sMap[ y, x ] - 1 ], x * Unit.DOT, y * Unit.DOT );
				}
			}
		}
	}
	public static bool IsArea( int x, int y )
	{
		return( x >= 0 && x < WIDTH &&
		        y >= 0 && y < HEIGHT );
	}
	public static bool IsBlock( int x, int y )
	{
		x -= 128;
		y -= 128;
		int		x0 = x / 256;
		int		y0 = y / 256;
		int		x1 = ( x + 255 ) / 256;
		int		y1 = ( y + 255 ) / 256;
		return( IsBlockM( x0, y0 ) ||
		        IsBlockM( x1, y0 ) ||
		        IsBlockM( x0, y1 ) ||
		        IsBlockM( x1, y1 ) );
	}
	public static bool IsBlockM( int x, int y )
	{
		return( !IsArea( x, y ) || sMap[ y, x ] == BLOCK || sMap[ y, x ] == WALL );
	}
}
class Unit
{
	protected static System.Drawing.Font		sFont = new System.Drawing.Font( "MS P Gothic", 5 );
	protected static System.Drawing.SolidBrush	sSBWhite = new System.Drawing.SolidBrush( System.Drawing.Color.White );
	public static readonly int		DOT = 8;
	public static readonly int		DTH = DOT / 2;
	public int		mX, mY;
	public int		mDX, mDY;
	public int		mHP;
	public int		mMHP;
	public int		mLV = 1;
	public int		mEXP;
	public int		mType;
	public int		mAngle;
	public int Attack{	get{	return( ( mLV + 1 + Util.Rnd( 2 ) ) / 2 );	}	}
	public int EXP{
		get{ return( mEXP ); }
		set{
			mEXP = value;
			while( mLV * ( mLV + 1 ) * 8 <= mEXP ){
				mLV++;
				mMHP += 5;
			}
		}
	}
	public Unit( int x, int y, int dx, int dy )
	{
		mX = x;
		mY = y;
		mDX = dx;
		mDY = dy;
	}
	public virtual void step()
	{
		if( mHP < mMHP &&
		    ( ( ( LDAct9.sCount & 0x3f ) == 0 ) ||
		      Map.CountNeighbor( mX / 256, mY / 256, 0 ) <= 1 ) ){
			mHP++;
		}
		if( ( mX & 0xff ) == 0x80 && ( mY & 0xff ) == 0x80 &&
			Map.IsBlockM( mX / 256 + Math.Sign( mDX ), 
			              mY / 256 + Math.Sign( mDY ) ) ){
			mDX = 0;
			mDY = 0;
		}
		mX += mDX;
		mY += mDY;
	}
	public bool isCollision( Unit u )
	{
		return( Math.Abs( mX - u.mX ) < 6.0f * 256 / DOT && Math.Abs( mY - u.mY ) < 6.0f * 256 / DOT );
	}
}
class Player : Unit
{
	public static List	sList = new List();
	static System.Drawing.Bitmap[]	sBM = {
		new System.Drawing.Bitmap( "player.png" ),
	};
	static System.Drawing.Rectangle	sRect = new System.Drawing.Rectangle( 0, 0, 12, 12 );
	public int		mItem;
	public string	mID;
	public string	mName;
	static int[,] sKeyPad = {
		{
			(int)System.Windows.Forms.Keys.Down,
			(int)System.Windows.Forms.Keys.Left,
			(int)System.Windows.Forms.Keys.Right,
			(int)System.Windows.Forms.Keys.Up,
			(int)System.Windows.Forms.Keys.Z,
		},{
			(int)System.Windows.Forms.Keys.NumPad2,
			(int)System.Windows.Forms.Keys.NumPad4,
			(int)System.Windows.Forms.Keys.NumPad6,
			(int)System.Windows.Forms.Keys.NumPad8,
			(int)System.Windows.Forms.Keys.NumPad5,
		}
	};
	public int AX{	get{
		if( mAngle == 1 )	return( -1 );
		if( mAngle == 2 )	return(  1 );
		return( 0 );
	}	}
	public int AY{	get{
		if( mAngle == 0 )	return(  1 );
		if( mAngle == 3 )	return( -1 );
		return( 0 );
	}	}
	public Player( string id, string name ) : base( 256 * 3 + 128, ( Map.HEIGHT - 4 ) * 256 + 128, 0, 0 )
	{
		mID = id;
		mName = name;
		mHP = mMHP = 30;
	}
	public void draw( System.Drawing.Graphics g )
	{
		sRect.X = ( (int)( ( mX + mY ) * 4 / 256 ) & 1 ) * ( DOT + DOT / 2 );
		sRect.Y = mAngle * ( DOT + DOT / 2 );
		g.DrawImage( sBM[ 0 ], mX * DOT / 256.0f  - DTH - 2, mY * DOT / 256.0f - DTH - 2, sRect, System.Drawing.GraphicsUnit.Pixel );
		g.DrawString( "" + mHP, sFont, sSBWhite, mX * DOT / 256.0f + DTH, mY * DOT / 256.0f - DTH );
		g.DrawString( "" + mLV, sFont, sSBWhite, mX * DOT / 256.0f - DTH * 2.5f, mY * DOT / 256.0f - DTH );
	}
	public void drawStatus( System.Drawing.Graphics g )
	{
		g.DrawString( mName, sFont, sSBWhite, 4, 170 );
		g.DrawString( "Lv " + mLV             , sFont, sSBWhite, 44, 170 );
		g.DrawString( "HP " + mHP + "/" + mMHP, sFont, sSBWhite, 68, 170 );
		g.DrawString( "土:" + mItem           , sFont, sSBWhite, 108, 170 );
	}
	public int getMap()
	{
		return( Map.Get( mX, mY ) );
	}
	public static Player getPlayer( string id )
	{
		foreach( Player p in sList ){
			if( p.mID == id ){
				return( p );
			}
		}
		return( null );
	}
	public bool isMove()
	{
		return( mDX != 0 || mDY != 0 );
	}
	public void start()
	{
		mHP = mMHP;
		mX = 256 * 3 + 128;
		mY = ( Map.HEIGHT - 4 ) * 256 + 128;
		mDX = 0;
		mDY = 0;
	}
	public static void startAll()
	{
		foreach( Player pl in sList ){
			pl.start();
		}
	}
	public override void step()
	{
		if( Map.IsCenter( mX, mY ) ){
			mDX = 0;
			mDY = 0;
		}
		if( mDX == 0 && mDY == 0 ){
			int		i = 0;
			if( mID == "T" ){
				i = 1;
			}
			bool	key = true;
			if( MyForm.sKey[ sKeyPad[ i, 0 ] ] > 0 ){	mAngle = 0;	mDY = 32;	}else
			if( MyForm.sKey[ sKeyPad[ i, 1 ] ] > 0 ){	mAngle = 1;	mDX = -32;	}else
			if( MyForm.sKey[ sKeyPad[ i, 2 ] ] > 0 ){	mAngle = 2;	mDX = 32;	}else
			if( MyForm.sKey[ sKeyPad[ i, 3 ] ] > 0 ){	mAngle = 3;	mDY = -32;	}else
			if( MyForm.sKey[ sKeyPad[ i, 4 ] ] == 2 ){
				int		x = mX + AX * 0x100;
				int		y = mY + AY * 0x100;
				int		m = Map.Get( x, y );
				if( m == Map.BLOCK ){
					Map.Set( x, y, Map.FLOOR );
					mItem++;
				}
				if( m == Map.FLOOR && mItem > 0 ){
					Map.Set( x, y, Map.BLOCK );
					mItem--;
				}
			}else{
				key = false;
			}
			if( key ){
				LDAct9.sPlayer = this;
			}
		}
		base.step();
		if( Map.sMap[ (int)( mY / 256 ), (int)( mX / 256 ) ] == Map.FLAG ){
			EXP += LDAct9.sStage * 20;
			LDAct9.sStageClear = 4 * 30;
		}
	}
}
class Enemy : Unit
{
	public static List			sList;
	static System.Drawing.RectangleF	sRectD = new System.Drawing.RectangleF( 0, 0, 12, 12 );
	static System.Drawing.RectangleF	sRectS = new System.Drawing.RectangleF( 0, 0, 12, 12 );
	static System.Drawing.Bitmap[]	sBM = {
		new System.Drawing.Bitmap( "monster.png" ),
		new System.Drawing.Bitmap( "player2.png" ),
		new System.Drawing.Bitmap( "monster2.png" ),
	};
	public static int[]		sSpeed = { 8, 32, 16 };
	public Enemy( int type, int lv ) : base( Util.Rnd( Map.WIDTH / 2 ) * 512 + 256 + 128, Util.Rnd( 4 ) * 512 + 256 + 128, 0, 0 )
	{
		mType = type;
		mLV = lv;
		mHP = mMHP = ( type + 1 ) * ( mLV + 1 ) * 5;
	}
	public void draw( System.Drawing.Graphics g )
	{
		sRectS.X = ( (int)( ( mX + mY ) * 4 / 256 ) & 1 ) * ( DOT + DOT / 2 );
		sRectS.Y = mAngle * ( DOT + DOT / 2 );
		sRectD.X = mX * DOT / 256.0f - DTH - 2;
		sRectD.Y = mY * DOT / 256.0f - DTH - 2;
		g.DrawImage( sBM[ mType ], sRectD, sRectS, System.Drawing.GraphicsUnit.Pixel );
		g.DrawString( "" + mHP, sFont, sSBWhite, mX * DOT / 256.0f + DTH, mY * DOT / 256.0f - DTH );
		g.DrawString( "" + mLV, sFont, sSBWhite, mX * DOT / 256.0f - DTH * 2.5f, mY * DOT / 256.0f - DTH );
	}
	public void step( List le )
	{
		step();
		if( ( mDX == 0 && mDY == 0 ) ||
		    ( Map.CountNeighbor( mX / 256, mY / 256, 0 ) > 2 &&
		      Map.IsCenter( mX, mY ) ) ){
			int		s = sSpeed[ mType ];
			mDX = Util.Rnd( 3 ) * s - s;
			if( mDX == 0 ){
				mDY = Util.Rnd( 3 ) * s - s;
			}else{
				mDY = 0;
			}
			if( mDY > 0 )	mAngle = 0;
			if( mDX < 0 )	mAngle = 1;
			if( mDX > 0 )	mAngle = 2;
			if( mDY < 0 )	mAngle = 3;
		}
	}
}
class LDAct9 : MyForm
{
	System.Drawing.Font			mFont = new System.Drawing.Font( "MS P Gothic", 5 );
	public static int			sCount;
	public static int			sStageClear;
	public static int			sStageFailed;
	public static int			sStage;
	int							mScene;
	static bool					sPause;
	public static Player		sPlayer;
	protected override void OnLoad( EventArgs e )
	{
		base.OnLoad( e );
		mTimer.Start();
	}
	protected override void onMyPaint( System.Drawing.Graphics g )
	{
		if( mScene == 0 ){
			g.DrawString( "見下ろし型アクション10 LD Action10", mFont, mSBWhite, 60, 30 );
			g.DrawString( "PRESS Z KEY", mFont, mSBWhite, 90, 90 );
			return;
		}
		g.TranslateTransform( -4, 0 );
		Map.draw( g );
		foreach( Player pl in Player.sList ){
			pl.draw( g );
		}
		foreach( Enemy en in Enemy.sList ){
			en.draw( g );
		}
		g.TranslateTransform( 4, 0 );
		g.DrawString( "TIME "  + sCount, mFont, mSBWhite, 200, 170 );
		g.DrawString( "STAGE " + sStage, mFont, mSBWhite, 164, 170 );
		if( sStageClear > 0 ){
			g.DrawString( "STAGE CLEAR!", mFont, mSBWhite, 90, 90 );
		}
		if( sStageFailed > 0 ){
			g.DrawString( "STAGE FAILED", mFont, mSBWhite, 90, 90 );
		}
		if( sPause ){
			g.DrawString( "  PAUSE  ", mFont, mSBWhite, 90, 90 );
		}
		if( sPlayer != null ){
			sPlayer.drawStatus( g );
		}
	}
	protected override void onMyTimer( object sender, System.Timers.ElapsedEventArgs e )
	{
		base.onMyTimer( sender, e );
		if( sKey[ (int)System.Windows.Forms.Keys.R ] == 2 )	input( "K", true  );
		if( sKey[ (int)System.Windows.Forms.Keys.Z ] >  0 )	input( "K", false );
		if( sKey[ (int)System.Windows.Forms.Keys.P ] == 2 )	sPause ^= true;
		if( sKey[ (int)System.Windows.Forms.Keys.NumPad5 ] > 0 )	input( "T", false );
		if( sPause ){
			Invalidate();
			return;
		}
		if( --sCount == 0 && sStage > 1 ){	//	時間制限判定
			sStageFailed = 4 * 30;
			Invalidate();
		}
		if( sStageClear > 0 ){				//	ゲームクリア表示中
			if( --sStageClear == 1 ){
				nextStage();
			}
			return;
		}
		if( sStageFailed > 0 ){				//	時間制限到達表示中
			if( --sStageFailed == 1 ){
				sStage -= 2;
				nextStage();
			}
			return;
		}
		for( int i = Player.sList.Count - 1; i >= 0; i-- ){
			Player pl = Player.sList[ i ];
			pl.step();
			for( int j = Enemy.sList.Count - 1; j >= 0; j-- ){
				Enemy	en = Enemy.sList[ j ];
				if( !pl.isCollision( en ) ){	//	敵に接触していない場合
					continue;
				}
				pl.mHP -= en.Attack;
				en.mHP -= pl.Attack;
				pl.EXP += en.mLV;
				en.EXP += pl.mLV;
				if( pl.mHP <= 0 ){
					sStageFailed = 4 * 30;
				}
				if( en.mHP <= 0 ){
					Enemy.sList.RemoveAt( j );
				}
			}
			//	プレイヤー同士の修行
			for( int j = Player.sList.Count - 1; j >= 0; j-- ){
				Player	p = Player.sList[ j ];
				if( p == pl ){
					continue;
				}
				if( p.mHP  == p.mMHP  && p.isMove() && 
				    pl.mHP == pl.mMHP && pl.isMove() &&
				    p.isCollision( pl ) ){
					p.EXP++;
					pl.EXP++;
					p.mHP--;
					pl.mHP--;
				}
			}
		}
		//	敵進行処理
		for( int i = Enemy.sList.Count - 1; i >= 0; i-- ){
			Enemy	en = Enemy.sList[ i ];
			en.step( Enemy.sList );
		}
		Invalidate();
	}
	void nextStage()
	{
		sStage++;
		start();
		Player.startAll();
	}
	void input( string id, bool res )
	{
		if( mScene == 0 ){
			start();
			Player.sList.Add( new Player( id, "Player1" ) );
		}else if( sStageClear == 1 ){
			nextStage();
		}else if( res ){
			sStage = 1;
			start();
			Player.sList.Clear();
			Player.sList.Add( new Player( id, "Player1" ) );
		}else if( Player.getPlayer( id ) == null ){
			Player.sList.Add( new Player( id, "Player2" ) );
		}
	}
	void start()
	{
		if( sStage < 1 ){
			sStage = 1;
		}
		mScene = 1;
		sStageClear = 0;
		sStageFailed = 0;
		sCount = ( sStage + 4 ) * 2000;
		Enemy.sList = new List();
		for( int i = 0; i < sStage; i++ ){
			Enemy.sList.Add( new Enemy( 0, Util.Rnd( sStage ) + 1 ) );
			Enemy.sList.Add( new Enemy( 0, Util.Rnd( sStage ) + 1 ) );
			Enemy.sList.Add( new Enemy( 0, Util.Rnd( sStage ) + 1 ) );
			Enemy.sList.Add( new Enemy( 0, Util.Rnd( sStage ) + 1 ) );
			Enemy.sList.Add( new Enemy( 1, Util.Rnd( sStage ) + 1 ) );
			Enemy.sList.Add( new Enemy( 1, Util.Rnd( sStage ) + 1 ) );
			Enemy.sList.Add( new Enemy( 2, Util.Rnd( sStage ) + 1 ) );
		}
		Map.create();
	}
	[STAThread]
	static void Main()
	{
		System.Windows.Forms.Application.Run( new LDAct9() );
	}
}
     
MyForm.cs
//	Form継承 2017/11/27 T.Umezawa
using System;
using System.Collections.Generic;
class MyForm : System.Windows.Forms.Form
{
	protected System.Timers.Timer		mTimer = new System.Timers.Timer();
	protected System.Drawing.SolidBrush	mSBWhite = new System.Drawing.SolidBrush( System.Drawing.Color.White );
	public static int[]		sKey = new int[ 0x100 ];
	public static int[]		sMouseB = new int[ 0x20 ];
	public static int MouseLeft{	get{	return( sMouseB[ (int)Math.Log( (int)System.Windows.Forms.MouseButtons.Left  , 2 ) ] );	}	}
	public static int MouseMiddle{	get{	return( sMouseB[ (int)Math.Log( (int)System.Windows.Forms.MouseButtons.Middle, 2 ) ] );	}	}
	public static int MouseRight{	get{	return( sMouseB[ (int)Math.Log( (int)System.Windows.Forms.MouseButtons.Right , 2 ) ] );	}	}
	protected override void OnKeyDown( System.Windows.Forms.KeyEventArgs e )
	{
		sKey[ (int)e.KeyCode ] = 1;
		base.OnKeyDown( e );
	}
	protected override void OnKeyUp( System.Windows.Forms.KeyEventArgs e )
	{
		sKey[ (int)e.KeyCode ] = 0;
		base.OnKeyUp( e );
	}
	protected override void OnMouseDown( System.Windows.Forms.MouseEventArgs e )
	{
		sMouseB[ (int)Math.Log( (int)e.Button, 2 ) ] = 1;
		base.OnMouseDown( e );
	}
	protected override void OnMouseUp( System.Windows.Forms.MouseEventArgs e )
	{
		sMouseB[ (int)Math.Log( (int)e.Button, 2 ) ] = 0;
		base.OnMouseUp( e );
	}
	protected override void OnLoad( EventArgs e )
	{
		ClientSize = new System.Drawing.Size( 960, 720 );
#if HAISHIN
		Left = 396;	//	キャプチャ都合上
		Top = 20;	//	キャプチャ都合上
#endif
		DoubleBuffered = true;
//		BackColor = System.Drawing.Color.FromArgb( 0x55, 0x88, 0xff );
		BackColor = System.Drawing.Color.Black;
		mTimer.Elapsed += new System.Timers.ElapsedEventHandler( onMyTimer );
		mTimer.Interval = 33;
	}
	protected override void OnPaint( System.Windows.Forms.PaintEventArgs e )
	{
		base.OnPaint( e );
		System.Drawing.Graphics	g = e.Graphics;
		g.ScaleTransform( 4, 4 );
		g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
		g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
		onMyPaint( g );
	}
	protected virtual void onMyPaint( System.Drawing.Graphics g )
	{
	}
	protected virtual void onMyTimer( object sender, System.Timers.ElapsedEventArgs e )
	{
		for( int i = 0; i < sKey.Length; i++ ){
			if( sKey[ i ] > 0 ){
				sKey[ i ]++;
			}
		}
		for( int i = 0; i < sMouseB.Length; i++ ){
			if( sMouseB[ i ] > 0 ){
				sMouseB[ i ]++;
			}
		}
	}
}