ソースファイル一式 source code
11-LDAct4.zip
MITライセンスです。
This software/source is licensed under the MIT License, see LICENSE.txt.
LDAct4.cs
//	#11 見下ろし型アクション4 LD Action4 2017/12/04 T.Umezawa
using System;
using System.Collections.Generic;
class Util
{
	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 );
	}
}
class Map
{
	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( "block.png" ),
		new System.Drawing.Bitmap( "flag.png" ),
	};
	public static byte[,]		sMap = new byte[ 21, 31 ];
	public static void create()
	{
		Array.Clear( sMap, 0, sMap.Length );
		for( int y = 0; y < sMap.GetLength( 0 ); y++ ){
			sMap[ y, 0 ] = 1;
			sMap[ y, sMap.GetLength( 1 ) - 1 ] = 1;
		}
		for( int x = 0; x < sMap.GetLength( 1 ); x++ ){
			sMap[ 0, x ] = 1;
			sMap[ sMap.GetLength( 0 ) - 1, x ] = 1;
		}
		for( int y = 2; y < sMap.GetLength( 0 ) - 2; y += 2 ){
			for( int x = 2; x < sMap.GetLength( 1 ) - 2; x += 2 ){
				sMap[ y, x ] = 1;
			}
		}
		//	迷路作成
		for( int y = 2; y < sMap.GetLength( 0 ) - 2; y += 2 ){
			for( int x = 2; x < sMap.GetLength( 1 ) - 2; x += 2 ){
				if( isWall( x, y ) ){
					continue;
				}
				int		a = LDAct4.sRnd.Next( 4 );
				if( a == 0 )	sMap[ y - 1, x ] = 1;
				if( a == 1 )	sMap[ y + 1, x ] = 1;
				if( a == 2 )	sMap[ y, x - 1 ] = 1;
				if( a == 3 )	sMap[ y, x + 1 ] = 1;
			}
		}
		sMap[ 3, 27 ] = 2;
	}
	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 < sMap.GetLength( 0 ); y++ ){
			for( int x = 0; x < sMap.GetLength( 1 ); x++ ){
				if( sMap[ y, x ] == 0 ){
					g.FillRectangle( sSBFloor, x * 8, y * 8, 7, 7 );
				}else{
					g.DrawImage( sBM[ sMap[ y, x ] - 1 ], x * 8, y * 8 );
				}
			}
		}
	}
	public static bool IsArea( int x, int y )
	{
		return( x >= 0 && x < sMap.GetLength( 1 ) &&
		        y >= 0 && y < sMap.GetLength( 0 ) );
	}
	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 ] == 1 );
	}
}
class Unit
{
	protected static System.Drawing.Font			sFont = new System.Drawing.Font( "MS 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		mJump;
	public int		mHP;
	public int		mMHP;
	public int		mLV = 1;
	public int		mEXP;
	public int		mType;
	public int EXP{
		get{ return( mEXP ); }
		set{
			mEXP = value;
			if( mLV * ( mLV + 1 ) * 4 <= mEXP ){
				mLV++;
				mMHP += 5;
			}
		}
	}
	public Unit( int x, int y, int dx, int dy )
	{
		mX = x;
		mY = y;
		mDX = dx;
		mDY = dy;
	}
	public int giveExp()
	{
		return( mLV * ( mLV + 1 ) * ( mType + 1 ) );
	}
	public bool isBlock()
	{
		return( Map.IsBlock( mX, mY ) );
	}
	public virtual void step()
	{
		if( mHP < mMHP && ( ( LDAct4.sCount & 0x3f ) == 0 ) ){
			mHP++;
		}
		if( mJump > 0 ){
			mJump++;
		}
		int		mx = Math.Sign( mDX );
		mX += mx * 16;
		mDX -= mx;
		if( isBlock() ){
			mDX = 0;
			mX -= mx * 16;
		}
		int		my = Math.Sign( mDY );
		mY += my * 16;
		mDY -= my;
		if( isBlock() ){
			mDY = 0;
			mY -= my * 16;
		}
	}
	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( 2, 2, 8, 8 );
	public int		mBtnA;
	public int		mBtnB;
	int				mAngle;
	public Player() : base( 256 * 3 + 128, ( Map.sMap.GetLength( 0 ) - 4 ) * 256 + 128, 0, 0 )
	{
		mHP = mMHP = 30;
	}
	public void draw( System.Drawing.Graphics g )
	{
		sRect.X = ( (int)( ( mX + mY ) * 4 / 256 ) & 1 ) * ( DOT + DOT / 2 ) + 2;
		sRect.Y = mAngle * ( DOT + DOT / 2 ) + 2;
		if( mJump != 0 ){
			sRect.X = 0;
		}
		g.DrawImage( sBM[ 0 ], mX * DOT / 256.0f  - DTH, mY * DOT / 256.0f - DTH, 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 start()
	{
		mHP = mMHP;
		mX = 256 * 3 + 128;
		mY = ( Map.sMap.GetLength( 0 ) - 4 ) * 256 + 128;
		mDX = 0;
		mDY = 0;
	}
	public override void step()
	{
		if( mDX == 0 && mDY == 0 ){
			if( MyForm.sKey[ (int)System.Windows.Forms.Keys.Down  ] > 0 ){	mAngle = 0;	mDY = 16;	}else
			if( MyForm.sKey[ (int)System.Windows.Forms.Keys.Left  ] > 0 ){	mAngle = 1;	mDX = -16;	}else
			if( MyForm.sKey[ (int)System.Windows.Forms.Keys.Right ] > 0 ){	mAngle = 2;	mDX = 16;	}else
			if( MyForm.sKey[ (int)System.Windows.Forms.Keys.Up    ] > 0 ){	mAngle = 3;	mDY = -16;	}
		}
		base.step();
		if( Map.sMap[ (int)( mY / 256 ), (int)( mX / 256 ) ] == 2 ){
			LDAct4.sGameClear = true;
		}
	}
}
class Enemy : Unit
{
	public static List			sList;
	static System.Drawing.RectangleF	sRectD = new System.Drawing.RectangleF( 0, 0, 8, 8 );
	static System.Drawing.RectangleF	sRectS = new System.Drawing.RectangleF( 0, 0, 8, 8 );
	static System.Drawing.Bitmap[]	sBM = {
		new System.Drawing.Bitmap( "monster.png" ),
		new System.Drawing.Bitmap( "monster2.png" ),
	};
	public int Speed{	get{	return( 8 * ( mType + 1 ) );	}	}
	public Enemy( int type, int lv ) : base( LDAct4.sRnd.Next( Map.sMap.GetLength( 1 ) - 16 ) * 512 + 256 * 15 + 128, LDAct4.sRnd.Next( 4 ) * 512 + 256 + 128, 0, 0 )
	{
		mType = type;
		mLV = lv;
		mHP = mMHP = ( type + 1 ) * ( mLV + 1 ) * 5;
	}
	public void draw( System.Drawing.Graphics g )
	{
		sRectD.Y = mY * DOT / 256.0f - DTH;
		if( mDX > 0 ){
			sRectD.X = mX * DOT / 256.0f + DTH;
			sRectD.Width = -8;
		}else{
			sRectD.X = mX * DOT / 256.0f - DTH;
			sRectD.Width = 8;
		}
		if( mDY != 0 ){
			sRectS.Y = ( 3 - Math.Sign( mDY ) ) / 2 * DOT;
		}else{
			sRectS.Y = 0;
		}
		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 ){
			mDX = LDAct4.sRnd.Next( 3 ) * 16 - 16;
			mDY = LDAct4.sRnd.Next( 3 ) * 16 - 16;
		}
		foreach( Enemy en in le ){
			if( en == this || !isCollision( en ) ){
				continue;
			}
			mDX = -mDX;
			mDY = -mDY;
			en.mDX = -en.mDX;
			en.mDY = -en.mDY;
		}
	}
}
class LDAct4 : MyForm
{
	public static Random		sRnd = new Random();
	System.Drawing.Font			mFont = new System.Drawing.Font( "MS Gothic", 5 );
	public static int			sCount;
	public static bool			sGameClear, sGameOver;
	int							mStage = 1;
	int							mScene;
	protected override void OnLoad( EventArgs e )
	{
		base.OnLoad( e );
		mTimer.Interval = 33;
		mTimer.Start();
	}
	protected override void onMyPaint( System.Drawing.Graphics g )
	{
		if( mScene == 0 ){
			g.DrawString( "見下ろし型アクション4 LD Action4", 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 " + mStage, mFont, mSBWhite, 170, 170 );
		if( sGameClear ){
			g.DrawString( "STAGE CLEAR!", mFont, mSBWhite, 90, 90 );
		}
		if( sGameOver ){
			g.DrawString( "GAME OVER", mFont, mSBWhite, 90, 90 );
		}
	}
	protected override void onMyTimer( object sender, System.Timers.ElapsedEventArgs e )
	{
		if( sKey[ (int)System.Windows.Forms.Keys.R ] == 1 )	input( 1, true  );
		if( sKey[ (int)System.Windows.Forms.Keys.Z ] >  0 )	input( 1, false );
		if( Player.sList.Count > 0 ){
			Player.sList[ 0 ].mBtnA = sKey[ (int)System.Windows.Forms.Keys.Z     ];
			Player.sList[ 0 ].mBtnB = sKey[ (int)System.Windows.Forms.Keys.X     ];
		}
		if( sGameClear || sGameOver ){
			return;
		}
		sCount++;
		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 ) ){	//	敵に接触
					pl.mHP -= en.mLV;
					en.mHP -= pl.mLV;
					if( pl.mHP <= 0 ){
						en.EXP += pl.giveExp();
						sGameOver = true;
					}
					if( en.mHP <= 0 ){
						pl.EXP += en.giveExp();
						Enemy.sList.RemoveAt( j );
					}
				}
			}
		}
		for( int i = Enemy.sList.Count - 1; i >= 0; i-- ){
			Enemy	en = Enemy.sList[ i ];
			en.step( Enemy.sList );
		}
		base.onMyTimer( sender, e );
		Invalidate();
	}
	void input( int type, bool res )
	{
		if( mScene == 0 ){
			mStage = 1;
			start();
			Player.sList.Add( new Player() );
		}else if( sGameClear ){
			mStage++;
			start();
			Player.sList[ 0 ].start();
		}else if( res ){
			mStage = 1;
			start();
			Player.sList.Clear();
			Player.sList.Add( new Player() );
		}
	}
	void start()
	{
		mScene = 1;
		sGameClear = false;
		sGameOver = false;
		sCount = 0;
		Enemy.sList = new List();
		for( int i = 0; i < mStage * 4; i++ ){
			Enemy.sList.Add( new Enemy( 0, sRnd.Next( mStage ) + 1 ) );
			Enemy.sList.Add( new Enemy( 1, sRnd.Next( mStage ) + 1 ) );
		}
		Map.create();
	}
	[STAThread]
	static void Main()
	{
		System.Windows.Forms.Application.Run( new LDAct4() );
	}
}
     
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 );
//		Left = 396;	//	キャプチャ都合上
//		Top = 20;	//	キャプチャ都合上
		DoubleBuffered = true;
//		BackColor = System.Drawing.Color.FromArgb( 0x55, 0x88, 0xff );
		BackColor = System.Drawing.Color.Black;
		mTimer.Elapsed += new System.Timers.ElapsedEventHandler( onMyTimer );
	}
	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 ]++;
			}
		}
	}
}