ソースファイル一式 source code
02-JumpAct.zip
MITライセンスです。
JumpAct.cs
//	#2 ジャンプアクション Jump Action 2017/11/21 T.Umezawa
using System;
using System.Collections.Generic;
class Unit
{
	protected int	mX, mY;
	protected int	mDX, mDY;
	protected bool	mGround = true;
	public Unit( int x, int y, int dx, int dy )
	{
		mX = x;
		mY = y;
		mDX = dx;
		mDY = dy;
	}
	public virtual void step()
	{
		mX += mDX;
		int		x0 = mX / 8;
		int		y0 = mY / 8;
		int		x1 = ( mX + 7 ) / 8;
		int		y1 = ( mY + 7 ) / 8;
		if( JumpAct.sMap[ y0, x0 ] != 0 ||
		    JumpAct.sMap[ y0, x1 ] != 0 ||
			JumpAct.sMap[ y1, x0 ] != 0 ||
			JumpAct.sMap[ y1, x1 ] != 0 ){
			mDX = -mDX;
			mX += mDX;
		}
		mY += mDY;
		x0 = mX / 8;
		y0 = mY / 8;
		x1 = ( mX + 7 ) / 8;
		y1 = ( mY + 7 ) / 8;
		if( !mGround && mDY < 6 ){
			mDY++;
		}
		if( mDY < 0 && ( JumpAct.sMap[ y0, x0 ] != 0 || JumpAct.sMap[ y0, x1 ] != 0 ) ){
			mDY = 1;
			mY = mY / 8 * 8 + 8;
		}
		if( mDY > 0 && ( JumpAct.sMap[ y1, x0 ] != 0 || JumpAct.sMap[ y1, x1 ] != 0 ) ){
			mDY = 0;
			mY = mY / 8 * 8;
			mGround = true;
		}
		if( mGround && JumpAct.sMap[ y0 + 1, x0 ] == 0 && JumpAct.sMap[ y0 + 1, x1 ] == 0 ){
			mGround = false;
			mY++;
			mDY = 1;
		}
	}
	public bool isCollision( Unit u )
	{
		return( Math.Abs( mX - u.mX ) < 7 && Math.Abs( mY - u.mY ) < 7 );
	}
}
class Player : Unit
{
	static System.Drawing.Bitmap	sBM = new System.Drawing.Bitmap( "player.png" );
	static System.Drawing.Rectangle	sRect = new System.Drawing.Rectangle( 0, 0, 8, 8 );
	public Player() : base( 0, 8 * 10, 1, 0 )
	{
	}
	public void draw( System.Drawing.Graphics g )
	{
		sRect.X = ( mX & 1 ) * 8;
		sRect.Y = ( mDX + 1 ) / 2 * 8;
		g.DrawImage( sBM, mX, mY, sRect, System.Drawing.GraphicsUnit.Pixel );
	}
	public void jump()
	{
		if( mGround ){
			mGround = false;
			mDY = -7;
		}
	}
	public override void step()
	{
		base.step();
		if( mX == 0 || mX == 120 - 8 ){
			mDX = -mDX;
		}
		if( mY < 0 ){
			JumpAct.sGameClear = true;
		}
	}
}
class Enemy : Unit
{
	static System.Drawing.Bitmap	sBM = new System.Drawing.Bitmap( "monster.png" );
	public Enemy( int x, int dx ) : base( x, 0, dx, 0 )
	{
	}
	public void draw( System.Drawing.Graphics g )
	{
		g.DrawImage( sBM, mX, mY );
	}
	public void step( List le )
	{
		step();
		if( mX == 0 || mX == 120 - 8 ){
			if( mY < 10 * 8 ){
				mDX = -mDX;
			}else{
				mX = JumpAct.sRnd.Next( 100 ) + 10;
				mY = 0;
			}
		}
		foreach( Enemy en in le ){
			if( en == this || !isCollision( en ) ){
				continue;
			}
			mDX = Math.Sign( mX - en.mX );
			if( mDX == 0 ){
				mDX = 1;
			}
			en.mDX = -mDX;
		}
	}
}
class JumpAct : MyForm
{
	public static byte[,]		sMap = new byte[ 12, 15 ];
	public static Random		sRnd = new Random();
	static readonly System.Drawing.Bitmap	sBM = new System.Drawing.Bitmap( "block.png" );
	System.Drawing.Font			mFont = new System.Drawing.Font( "MS Gothic", 4 );
	int							mCount;
	Player						mPlayer;
	List					mLEnemy = new List();
	public static bool			sGameClear, sGameOver;
	protected override void OnLoad( EventArgs e )
	{
		base.OnLoad( e );
		BackColor = System.Drawing.Color.Black;
		mPlayer = new Player();
		for( int i = 0; i < 5; i++ ){
			mLEnemy.Add( new Enemy( i * 20 + 10, sRnd.Next( 2 ) * 2 - 1 ) );
		}
		for( int x = 0; x < sMap.GetLength( 1 ); x++ ){
			sMap[ sMap.GetLength( 0 ) - 1, x ] = 1;
		}
		byte	v = 1;
		int		n = 1;
		for( int y = 2; y <= 8; y += 3 ){
			for( int x = 0; x < sMap.GetLength( 1 ); x++, n-- ){
				if( n == 0 ){
					v = (byte)( 1 - v );
					n = sRnd.Next( 2 ) + v + 1;
				}
				sMap[ y, x ] = v;
			}
		}
		mTimer.Interval = 50;
		mTimer.Start();
	}
	protected override void OnMouseDown( System.Windows.Forms.MouseEventArgs e )
	{
		mPlayer.jump();
		base.OnMouseMove( e );
	}
	protected override void OnPaint( System.Windows.Forms.PaintEventArgs e )
	{
		System.Drawing.Graphics	g = e.Graphics;
		g.ScaleTransform( 8, 8 );
		g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
		g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
		for( int y = 0; y < sMap.GetLength( 0 ); y++ ){
			for( int x = 0; x < sMap.GetLength( 1 ); x++ ){
				if( sMap[ y, x ] != 0 ){
					g.DrawImage( sBM, x * 8, y * 8 );
				}
			}
		}
		mPlayer.draw( g );
		foreach( Enemy en in mLEnemy ){
			en.draw( g );
		}
		g.DrawString( "TIME " + mCount, mFont, mSBWhite, 0, 0 );
		if( sGameClear ){
			g.DrawString( "GAME CLEAR!", mFont, mSBWhite, 40, 40 );
		}
		if( sGameOver ){
			g.DrawString( "GAME OVER", mFont, mSBWhite, 40, 40 );
		}
	}
	protected override void onMyTimer( object sender, System.Timers.ElapsedEventArgs e )
	{
		if( sGameClear || sGameOver ){
			return;
		}
		mCount++;
		mPlayer.step();
		foreach( Enemy en in mLEnemy ){
			if( ( mCount & 1 ) == 0 ){
				en.step( mLEnemy );
			}
			if( mPlayer.isCollision( en ) ){
				sGameOver = true;
			}
		}
		Invalidate();
	}
	[STAThread]
	static void Main()
	{
		System.Windows.Forms.Application.Run( new JumpAct() );
	}
}
   
MyForm.cs
//	Form継承 2017/11/21 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 );
	protected override void OnLoad( EventArgs e )
	{
		ClientSize = new System.Drawing.Size( 960, 720 );
		Left = 62;	//	キャプチャ都合上
		Top = 20;	//	キャプチャ都合上
		DoubleBuffered = true;
		mTimer.Elapsed += new System.Timers.ElapsedEventHandler( onMyTimer );
	}
	protected virtual void onMyTimer( object sender, System.Timers.ElapsedEventArgs e )
	{
	}
}