using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsForms_Game1
{
public partial class Form1 : Form
{
private Point player; //存放玩家x,y
private Point[] vMonster; //存放怪物x,y
private Bullet[] vBullet; //存放子彈x,y
private Random random;
private Graphics wndGraphic; //視窗畫布
private Graphics backGraphic; //背景頁畫布
private Bitmap backBmp; //背景點陣圖
private const int VIEW_W = 1024;
private const int VIEW_H = 768;
private const float MAKE_MONSTER_TIME = 3;
private float makeMonsterTime; //生怪的時間
private const float MAKE_BULLET_TIME = 0.1f;
private float makeBulletTime; //再過多久生子彈的時間
private const float REQUIRE_FPS = 60; //預期的畫面更新率(每秒呼叫幾次onTimer)
private const int BALL_SIZE = 50; //球的直徑
private const int MAX_ENEMY = 30;
private const int MAX_BULLET = 10;
private Point mousePos;
private KeyState keySpace;//空白鍵
private KeyState keyUp;//上
private KeyState keyDown;//下
private KeyState keyLeft;//左
private KeyState keyRight;//右
public Form1()
{
InitializeComponent();
keySpace = new KeyState(Keys.Space);
keyUp = new KeyState(Keys.Up);
keyDown = new KeyState(Keys.Down);
keyLeft = new KeyState(Keys.Left);
keyRight = new KeyState(Keys.Right);
makeBulletTime = 0;
makeMonsterTime =
MAKE_MONSTER_TIME;
wndGraphic = CreateGraphics(); //建立視窗畫布
backBmp = new Bitmap(VIEW_W, VIEW_H);
backGraphic = Graphics.FromImage(backBmp);
mousePos = new Point();
random = new Random();
random = new Random();
player = new Point();
player.x = 100;
player.y = 100;
vMonster = new Point[MAX_ENEMY];
vBullet = new Bullet[MAX_BULLET];
for (int i = 0; i <
MAX_ENEMY; i++)
{
vMonster[i] = new Point();
vMonster[i].x = random.Next(0, VIEW_W);
vMonster[i].y = random.Next(0,
VIEW_H);
}
timer1.Interval = 1000 / (int)REQUIRE_FPS; // 1/30秒
timer1.Start();
}
private void onPaint(object sender, PaintEventArgs e)
{
drawGame();
}
private void moveMonster()
{
for (int i = 0; i <
MAX_ENEMY; i++)
{
if (vMonster[i] != null)
{
vMonster[i].move(player);
/*碰到玩家球就消失
if
(vMonster[i].getDistance(player) < BALL_SIZE)
{
vMonster[i] = null;
}
*/
}
}
}
private void moveBullet_KillMonster()
{
for (int i = 0; i <
MAX_BULLET; i++)
{
if (vBullet[i] != null)
{
vBullet[i].move();
//有沒有打到怪
for (int m = 0; m <
MAX_ENEMY; m++)
{
//子彈跟怪都是存在的
if (vMonster[m] != null)
{
if
(vMonster[m].getDistance(vBullet[i]) < BALL_SIZE)
{
vBullet[i] = null;
vMonster[m] = null;
break;
}
}
}
if (vBullet[i] != null)
{
if (vBullet[i].x > VIEW_W) //檢查出界
vBullet[i] = null;
else if (vBullet[i].y > VIEW_H) //檢查出界
vBullet[i] = null;
else if (vBullet[i].x < 0) //檢查出界
vBullet[i] = null;
else if(vBullet[i].y < 0) //檢查出界
vBullet[i] = null;
}
}
}
}
private void drawGame()
{
backGraphic.FillRectangle(Brushes.White, 0, 0,
VIEW_W, VIEW_H);
backGraphic.DrawEllipse(Pens.Red, player.x,
player.y, BALL_SIZE, BALL_SIZE); //畫出玩家
int total = 0;
//畫出怪物
for (int i = 0; i <
MAX_ENEMY; i++)
{
if (vMonster[i] != null)
{
total++;
backGraphic.DrawEllipse(Pens.Blue,
vMonster[i].x, vMonster[i].y, BALL_SIZE, BALL_SIZE);
}
}
String str = "怪物數量:" + total;
backGraphic.DrawString(str, SystemFonts.CaptionFont,
Brushes.Black, 0, 0);
total = 0;
//畫出子彈
for (int i = 0; i <
MAX_BULLET; i++)
{
if (vBullet[i] != null)
{
total++;
backGraphic.DrawEllipse(Pens.Black,
vBullet[i].x, vBullet[i].y, BALL_SIZE, BALL_SIZE);
}
}
//顯示子彈的數量
total = MAX_BULLET - total;
str = "剩餘子彈:" + total;
backGraphic.DrawString(str, SystemFonts.CaptionFont,
Brushes.Black, 0, 20);
if (keySpace.isDown())
{
backGraphic.DrawString("space down", SystemFonts.CaptionFont, Brushes.Black, 0, 40);
}
else
{
backGraphic.DrawString("space up", SystemFonts.CaptionFont, Brushes.Black, 0, 40);
}
//將背景頁畫到視窗上面
wndGraphic.DrawImageUnscaled(backBmp, 0, 0);
//Invalidate(); //通知重繪畫面
}
private void onTimer(object sender, EventArgs e)
{
//就是主迴圈:main
keySpace.onTimer();
keyUp.onTimer();
keyDown.onTimer();
keyLeft.onTimer();
keyRight.onTimer();
if (keySpace.isPress()) //剛剛壓下去
{
//也要做發射
fireBullet();
}
// 連發
if (keySpace.isDown()) //壓著空白鍵
{
makeBulletTime -= 1.0f /
REQUIRE_FPS; // 1/30秒
if(makeBulletTime <= 0)//發射子彈的時間到了
{
fireBullet();
}
}
if (keyUp.isDown()) player.y -= 5;
if (keyDown.isDown()) player.y +=
5;
if (keyLeft.isDown()) player.x -=
5;
if (keyRight.isDown()) player.x +=
5;
makeMonsterTime -= 1.0f / 30.0f;
if(makeMonsterTime <= 0)
{
//生怪時間到了
for (int i = 0; i <
MAX_ENEMY; i++)
{
if (vMonster[i] == null)
{
vMonster[i] = new Point();
vMonster[i].x =
random.Next(0, VIEW_W);
vMonster[i].y =
random.Next(0, VIEW_H);
break;
}
}
makeMonsterTime =
MAKE_MONSTER_TIME;
}
moveMonster();
moveBullet_KillMonster();
drawGame();
}
void fireBullet()
{
//原本放開,剛剛按下去
for (int i = 0; i <
MAX_BULLET; i++)
{
if (vBullet[i] == null)
{
vBullet[i] = new Bullet(player, mousePos);
vBullet[i].x = player.x;
vBullet[i].y = player.y;
break;
}
}
makeBulletTime = MAKE_BULLET_TIME;
}
//滑鼠移動的通知
private void onMouseMove(object sender, MouseEventArgs e)
{
mousePos.x = e.X;
mousePos.y = e.Y;
}
//按鍵放開的通知
private void onKeyUp(object sender, KeyEventArgs e)
{
keySpace.onKeyUp(e.KeyCode);
keyUp.onKeyUp(e.KeyCode);
keyDown.onKeyUp(e.KeyCode);
keyLeft.onKeyUp(e.KeyCode);
keyRight.onKeyUp(e.KeyCode);
}
//按下某個按鍵
private void onKeyDown(object sender, KeyEventArgs e)
{
keySpace.onKeyDown(e.KeyCode);
keyUp.onKeyDown(e.KeyCode);
keyDown.onKeyDown(e.KeyCode);
keyLeft.onKeyDown(e.KeyCode);
keyRight.onKeyDown(e.KeyCode);
}
}
class Point
{
// public static float staticData =
1.7f; //共享
public float x, y;
public float getDistance(Point pnt)
{
//x,y是指呼叫者的x,y
//pnt是指傳入的物件
float L = (float)Math.Sqrt((x - pnt.x) *
(x - pnt.x) + (y - pnt.y) * (y - pnt.y));
return L;
}
public void move(Point target) //target > 玩家
{
float L =
getDistance(target);
float tx, ty;
if (L > 1)
{
tx = x + (target.x - x) * 1 /
L;
ty = y + (target.y - y) * 1 /
L;
x = tx;
y = ty;
}
else //距離很近
{
x = target.x;
y = target.y;
}
}
}
class Bullet : Point //Bullet繼承Point:加強或修改父類別
{
private Point moveDir; //移動的向量
private const int BULLET_SPEED = 10;
//方法名稱與類別名稱相同:建構
//當new某個物件(實體)的時候會呼叫這個物件(實體)的建構
public Bullet(Point pos, Point mousePos)
{
x = pos.x;
y = pos.y;
float dist =
getDistance(mousePos);
moveDir = new Point();
moveDir.x = (mousePos.x - x) *
BULLET_SPEED / dist;
moveDir.y = (mousePos.y - y) *
BULLET_SPEED / dist;
}
public void move()
{
//使用父類別的
x += moveDir.x;
y += moveDir.y;
}
}
//按鍵狀態(指定特定按鍵來做偵測)
class KeyState
{
//Keys不是一個類別,是一個列舉(enum)
private Keys theKey; //存放一個對應的按鍵編號
//剛剛壓下去 / 目前這次是壓著的 / 上次onTimer是否壓著
bool bPress, bDown, bPreDown;
public KeyState(Keys k)
{
theKey = k;
bPress = false;
bDown = false;
bPreDown = false;
}
public void onKeyDown(Keys k)
{
if(theKey == k)
{
bDown = true; //剛剛按下去
}
}
public void onKeyUp(Keys k)
{
if (theKey == k)
{
bDown = false;
bPress = false;
}
}
public bool isPress() //是否剛剛按下去
{
return bPress;
}
public bool isDown() //是否壓著
{
return bDown;
}
public void onTimer() //timer通知時呼叫
{
if(bDown == true)//此時是壓著
{
if (bPreDown == false) bPress = true;
else bPress = false;
}
else
{
bPress = false;
}
bPreDown = bDown; //把這次的狀態記下來,下次就可以用這個狀態
}
}
}
沒有留言:
張貼留言