ソースファイル一式 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 ]++;
}
}
}
}