/***********************************/
/*★ SHOOT で一括管理 前田 稔 ★*/
/***********************************/
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.Runtime.InteropServices;
//☆ 弾丸を一括管理するクラス
public class SHOOT
{
class SHOT
{
public int N; //弾の種類
public float X, Y; //弾の座標
public float DX, DY; //弾の移動量
// Constructor
public SHOT(int n, float x, float y, float dx, float dy)
{
N = n;
X = x;
Y = y;
DX = dx;
DY = dy;
}
}
public Bitmap Bmp; //弾丸の画像
public Point Size; //Sprite の幅と高さ
public int Wn; //横の枚数
public ArrayList array; //弾丸を登録
// Constructor
public SHOOT(string file, int w, int h)
{
try
{ Bmp = new Bitmap(file); }
catch
{
MessageBox.Show("イメージが取得できません", "Error");
return;
}
Size = new Point(w, h);
Wn = Bmp.Width / w;
array = new ArrayList();
}
// 弾丸を一個登録する(弾の種別/発射座標/方向)
public void Add(int n, float x, float y, float dx, float dy)
{ array.Add(new SHOT(n,x,y,dx,dy)); }
// 弾丸を円状に登録する(弾の種別/発射座標)
public void Circle(int n, float x, float y)
{
float dx, dy;
for(int i=0; i<10; i++)
{ dx = (float)(Math.Sin(i*36.0/180.0*Math.PI));
dy = (float)(Math.Cos(i*36.0/180.0*Math.PI));
array.Add(new SHOT(n,x,y,dx*2f,dy*2f));
}
}
// 弾丸を並べて登録する(弾の種別/発射基点/方向/弾丸の数/間隔)
public void Line(int n, float x, float y, float dx, float dy, int num, float px, float py)
{
float wx, wy;
wx= x;
wy= y;
for(int i=0; i<num; i++)
{
array.Add(new SHOT(n,wx,wy,dx*2f,dy*2f));
wx+= px;
wy+= py;
}
}
// 弾丸の描画
public void View(Graphics g)
{
foreach(SHOT wk in array)
{
if (Bmp==null) return;
Rectangle des = new Rectangle((int)wk.X, (int)wk.Y, (int)Size.X, (int)Size.Y);
Rectangle sou = new Rectangle((wk.N%Wn)*Size.X,(wk.N/Wn)*Size.Y,Size.X,Size.Y);
g.DrawImage(Bmp,des,sou,GraphicsUnit.Pixel);
}
}
// 画像全体を描画
public void View(Graphics g, int x, int y)
{ if (Bmp!=null) g.DrawImage(Bmp,x,y); }
// 座標の移動(Rectangle を超えると削除)
public void Move(Rectangle rect)
{
SHOT wk;
for(int i=0; i<array.Count; i++)
{ wk = (SHOT)array[i];
wk.X += wk.DX;
wk.Y += wk.DY;
if (wk.X<rect.Left || wk.X>rect.Right || wk.Y<rect.Top || wk.Y>rect.Bottom)
{ array.RemoveAt(i);
i--;
}
}
}
// 当たり判定
public bool Hit(float targetx, float targety, float len)
{ float dist,wx,wy;
foreach(SHOT wk in array)
{
wx = wk.X - targetx;
wy = wk.Y - targety;
dist = (float)Math.Sqrt((double)(wx * wx + wy * wy));
if (dist<len) return true;
}
return false;
}
}
public class MyForm : Form
{
[DllImport("User32.dll")]
static extern short GetAsyncKeyState(int vKey);
SHOOT App;
private Timer timer1;
private System.ComponentModel.IContainer components;
Rectangle rect = new Rectangle(20,20,540,380);
// Constructor
public MyForm()
{
// timer1
components = new System.ComponentModel.Container();
timer1 = new System.Windows.Forms.Timer(this.components);
SuspendLayout();
timer1.Interval = 15;
timer1.Tick += new System.EventHandler(this.timer1_Tick);
// MyForm
BackColor = SystemColors.AppWorkspace;
this.Width = 640;
this.Height = 480;
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
Paint += new PaintEventHandler(MyHandler);
App = new SHOOT(@"c:\data\test\tama4.png",32,32);
timer1.Start();
}
// 画像を描画
private void MyHandler(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
App.View(g,50,50);
App.View(g);
}
// タイマー割り込み
private void timer1_Tick(object sender, EventArgs e)
{
short kw;
if (GetAsyncKeyState(0x1B)!=0) Application.Exit();
App.Move(rect);
kw = GetAsyncKeyState(0x20); //空白
if (kw<0 && (kw&1)!=0) App.Add(0,300,400,0,-1);
kw = GetAsyncKeyState(0x0D); //Enter
if (kw<0 && (kw&1)!=0) App.Circle(1,300,200);
kw = GetAsyncKeyState(0x26); //上
if (kw<0 && (kw&1)!=0) App.Line(2,80,400,0,-1,8,60,0);
kw = GetAsyncKeyState(0x25); //左
if (kw<0 && (kw&1)!=0) App.Line(3,80,300,0.2f,-1,8,60,10);
kw = GetAsyncKeyState(0x27); //右
if (kw<0 && (kw&1)!=0) App.Line(3,80,400,-0.6f,-1,8,60,-30);
Invalidate();
}
}
class form01
{
public static void Main()
{
MyForm mf = new MyForm();
Application.Run(mf);
}
}
|