ソースファイル一式 source code
07-FSAct3.zip
MITライセンスです。
This software/source is licensed under the MIT License, see LICENSE.txt.
FSAct3.cs
// #6 固定画面アクション3 FS Action3 2017/11/29 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.Bitmap[] sBM = {
new System.Drawing.Bitmap( "block.png" ),
new System.Drawing.Bitmap( "flag.png" ),
};
public static byte[,] sMap = new byte[ 23, 30 ];
public static void create()
{
for( int x = 0; x < sMap.GetLength( 1 ); x++ ){
sMap[ sMap.GetLength( 0 ) - 1, x ] = 1;
sMap[ sMap.GetLength( 0 ) - 2, x ] = 1;
}
byte v = 1;
int n = 1;
for( int y = 5; y <= 17; y += 4 ){
for( int x = 0; 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
{
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 Unit( int x, int y, int dx, int dy )
{
mX = x;
mY = y;
mDX = dx;
mDY = dy;
}
public int getAngle4i( Unit u )
{
return( Util.GetAngle4i( u.mX - mX, u.mY - mY ) );
}
public bool isBlock()
{
return( Map.IsBlock( mX, mY ) );
}
public void jump( int dy )
{
if( mJump == 0 ){
mJump = 1;
}
mDY = dy;
}
public virtual void step()
{
if( mJump > 0 ){
mJump++;
}
mX += mDX;
if( isBlock() ){
mDX = -mDX;
mX += mDX;
}
mY += mDY;
if( mJump > 0 && mDY < 6 * 256 / DOT ){ // 重力
mDY += 8;
}
if( mDY < 0 && isBlock() ){ // 上昇中
if( !Map.IsBlock( mX + 16, mY ) ){
mX += 16;
}else if( !Map.IsBlock( mX - 16, mY ) ){
mX -= 16;
}else{ // 天井にぶつかる
mDY = 0;
mY = (int)( ( (int)( mY / 256.0f - 0.5f ) + 1.5f ) * 256 );
}
}
if( mDY > 0 && isBlock() ){ // 下降中
mDY = 0; // 着地
mY = (int)( ( (int)( mY / 256.0f - 0.5f ) + 0.5f ) * 256 );
mJump = 0;
}
if( mJump == 0 && !Map.IsBlock( mX, mY + 256 / DOT ) ){ // 地面から落ちる
mJump = 1;
mY += 256 / DOT;
mDY = 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
{
static System.Drawing.Bitmap[] sBM = {
new System.Drawing.Bitmap( "player.png" ),
new System.Drawing.Bitmap( "player2.png" )
};
static System.Drawing.Rectangle sRect = new System.Drawing.Rectangle( 0, 0, 8, 8 );
public int mType;
public int mBtnA;
public int mBtnB;
public int mBtnL;
public int mBtnR;
int mAngle;
public Player( int type ) : base( 128, 20 * 256 + 128, 0, 0 )
{
mType = type;
}
public void draw( System.Drawing.Graphics g )
{
sRect.X = ( (int)( mX * 4 / 256 ) & 1 ) * DOT;
sRect.Y = mAngle * DOT;
if( mJump != 0 ){
sRect.X = 0;
}
g.DrawImage( sBM[ mType ], mX * DOT / 256.0f - DTH, mY * DOT / 256.0f - DTH, sRect, System.Drawing.GraphicsUnit.Pixel );
}
public void jump()
{
if( mJump == 0 ){ // 接地中の場合
if( Math.Abs( mDX ) > 32 ){
jump( -88 );
}else{
jump( -80 );
}
}else if( mDY < 0 ){ // 上昇中の場合
mDY -= 5;
}
}
public override void step()
{
if( mBtnA > 0 ){
jump();
}
int max = 32;
if( mBtnB > 0 ){
max = 56;
}
if( mBtnL > 0 ){
mAngle = 0;
mDX -= 2;
if( mDX < -max ){
mDX = -max;
}
}else if( mBtnR > 0 ){
mAngle = 1;
mDX += 2;
if( mDX > max ){
mDX = max;
}
}else if( mDX != 0 ){
mDX -= Math.Sign( mDX ) * 4;
}
base.step();
if( mX <= 128 || mX >= Map.sMap.GetLength( 1 ) * 256 - 128 ){
mDX = 0;
}
if( Map.sMap[ (int)( mY / 256 ), (int)( mX / 256 ) ] == 2 ){
FSAct3.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 mType;
public int mState;
public int Speed{ get{ return( 8 * ( mType + 1 ) * ( mState * 3 + 1 ) ); } }
public Enemy( int type ) : base( FSAct3.sRnd.Next( Map.sMap.GetLength( 1 ) - 2 ) * 256 + 128, 128, ( FSAct3.sRnd.Next( 2 ) * 16 - 8 ) * ( type + 1 ), 0 )
{
mType = type;
}
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;
}
sRectS.X = mState * DOT;
g.DrawImage( sBM[ mType ], sRectD, sRectS, System.Drawing.GraphicsUnit.Pixel );
}
public void kill()
{
sList.Add( new Enemy( mType ) );
sList.Remove( this );
}
public void step( List le )
{
step();
if( mX <= 128 || mX >= Map.sMap.GetLength( 1 ) * 256 - 128 ){
mDX = Math.Sign( Map.sMap.GetLength( 1 ) * 128 - mX ) * Speed;
}
foreach( Enemy en in le ){
if( en == this || !isCollision( en ) ){
continue;
}
bool km = ( mState == 1 && mDX != 0 );
bool ke = ( en.mState == 1 && en.mDX != 0 );
if( km ) en.kill();
if( ke ) kill();
if( km || ke ){
continue;
}
mDX = Math.Sign( mX - en.mX ) * Speed;
if( mDX == 0 ){
mDX = Speed;
}
en.mDX = -mDX;
}
}
}
class FSAct3 : MyForm
{
public static Random sRnd = new Random();
System.Drawing.Font mFont = new System.Drawing.Font( "MS Gothic", 5 );
int mCount;
List mLPlayer = new List();
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( "固定画面アクション2 FS Action2", mFont, mSBWhite, 60, 30 );
g.DrawString( "PRESS ANY KEY", mFont, mSBWhite, 90, 90 );
return;
}
Map.draw( g );
foreach( Player pl in mLPlayer ){
pl.draw( g );
}
foreach( Enemy en in Enemy.sList ){
en.draw( g );
}
g.DrawString( "TIME " + mCount, mFont, mSBWhite, 0, 0 );
g.DrawString( "STAGE " + mStage, mFont, mSBWhite, 40, 0 );
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( mKey[ (int)System.Windows.Forms.Keys.R ] == 1 ) input( 1, true );
if( mKey[ (int)System.Windows.Forms.Keys.Z ] > 0 ) input( 1, false );
if( mKey[ (int)System.Windows.Forms.Keys.Z ] == 0 ) release( 1 );
Player p = getPlayer( 1 );
if( p != null ){
p.mBtnB = mKey[ (int)System.Windows.Forms.Keys.X ];
p.mBtnL = mKey[ (int)System.Windows.Forms.Keys.Left ];
p.mBtnR = mKey[ (int)System.Windows.Forms.Keys.Right ];
}
if( sGameClear || sGameOver ){
return;
}
mCount++;
foreach( Player pl in mLPlayer ){
pl.step();
for( int i = Enemy.sList.Count - 1; i >= 0; i-- ){
Enemy en = Enemy.sList[ i ];
if( !pl.isCollision( en ) ){ // 敵に接触
continue;
}
int an = pl.getAngle4i( en );
if( en.mType == 1 && en.mState == 1 ){
if( en.mDX == 0 ){
en.mDX = Math.Sign( en.mX - pl.mX );
en.mDX *= en.Speed;
if( pl.mJump > 0 ){
pl.jump( -64 );
}
}else if( an == 1 ){
en.mDX = 0;
pl.jump( -64 );
}
continue;
}
if( an != 1 ){ // 敵にやられる
sGameOver = true;
continue;
}
pl.jump( -64 );
if( en.mType == 0 ){ // スライムだった場合
en.kill();
continue;
}
if( en.mState == 0 ){
en.mState = 1;
en.mDX = 0;
continue;
}
en.mDX = Math.Sign( en.mX - pl.mX );
if( en.mDX == 0 ){
en.mDX = 1;
}
en.mDX *= en.Speed;
}
}
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();
mLPlayer.Add( new Player( type ) );
}else if( sGameClear ){
mStage++;
start();
mLPlayer.Add( new Player( type ) );
}else if( res ){
mStage = 1;
start();
mLPlayer.Add( new Player( type ) );
}else if( mLPlayer[ 0 ].mType != type ){
if( mLPlayer.Count == 1 ){
mLPlayer.Add( new Player( type ) );
}else{
mLPlayer[ 1 ].mBtnA = 1;
}
}else{
mLPlayer[ 0 ].mBtnA = 1;
}
}
Player getPlayer( int type )
{
foreach( Player p in mLPlayer ){
if( p.mType == type ){
return( p );
}
}
return( null );
}
void release( int type )
{
Player p = getPlayer( type );
if( p != null ){
p.mBtnA = 0;
}
}
void start()
{
mScene = 1;
sGameClear = false;
sGameOver = false;
mCount = 0;
mLPlayer.Clear();
Enemy.sList = new List();
for( int i = 0; i < mStage * 2; i++ ){
Enemy.sList.Add( new Enemy( 0 ) );
Enemy.sList.Add( new Enemy( 1 ) );
}
Map.create();
}
[STAThread]
static void Main()
{
System.Windows.Forms.Application.Run( new FSAct3() );
}
}
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 int[] mKey = new int[ 0x100 ];
public int[] mMouseB = new int[ 0x20 ];
public int MouseLeft{ get{ return( mMouseB[ (int)Math.Log( (int)System.Windows.Forms.MouseButtons.Left , 2 ) ] ); } }
public int MouseMiddle{ get{ return( mMouseB[ (int)Math.Log( (int)System.Windows.Forms.MouseButtons.Middle, 2 ) ] ); } }
public int MouseRight{ get{ return( mMouseB[ (int)Math.Log( (int)System.Windows.Forms.MouseButtons.Right , 2 ) ] ); } }
protected override void OnKeyDown( System.Windows.Forms.KeyEventArgs e )
{
mKey[ (int)e.KeyCode ] = 1;
base.OnKeyDown( e );
}
protected override void OnKeyUp( System.Windows.Forms.KeyEventArgs e )
{
mKey[ (int)e.KeyCode ] = 0;
base.OnKeyUp( e );
}
protected override void OnMouseDown( System.Windows.Forms.MouseEventArgs e )
{
mMouseB[ (int)Math.Log( (int)e.Button, 2 ) ] = 1;
base.OnMouseDown( e );
}
protected override void OnMouseUp( System.Windows.Forms.MouseEventArgs e )
{
mMouseB[ (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 );
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 < mKey.Length; i++ ){
if( mKey[ i ] > 0 ){
mKey[ i ]++;
}
}
for( int i = 0; i < mMouseB.Length; i++ ){
if( mMouseB[ i ] > 0 ){
mMouseB[ i ]++;
}
}
}
}