父类写完之后,考虑子类应该怎么写。
最简单的子类:砖块类,砖块类基本上没有什么新的字段和方法,不过为了方便画图,我加了一部分常量字段。顺便说一句,C#里常量字段默认是静态的,可是操作常量字段的get和set访问器得自己显示的定义为静态。
上代码:
using System.Drawing;
namespace 弹球
{
///
/// 方块:弹球世界中的矩形物体,被撞击后消失
///
class Block : Actor
{
///
/// 方块的宽度
///
private const int width = 50;
///
/// 获取方块的宽度
///
public static int Width
{
get { return width; }
}
///
/// 方块的高度
///
private const int height = 10;
///
/// 获取方块的高度
///
public static int Height
{
get { return height; }
}
public Block()
{ }
///
/// 构造函数:设置方块的左上角顶点位置
///
///
///
///
///
public Block(int iX, int iY)
{
PositionBounds.SetBounds(iX, iY, Block.width, Block.height);
CollisionBounds.SetBounds(iX, iY, Block.width, Block.height);
MoveBounds.SetBounds(0, 0, 0, 0);
}
///
/// 绘制方块
///
///
public override void Draw(Graphics g)
{
g.FillRectangle(new SolidBrush(Color.Black), new Rectangle(PositionBounds.Left, PositionBounds.Top, Block.width, Block.height));
g.DrawRectangle(Pens.White, new Rectangle(PositionBounds.Left, PositionBounds.Top, Block.width, Block.height));
}
public override void Update()
{
//该物体不更新信息
}
}
}
然后写球拍类,这个类相当于在基类的基础上新增一个移动方向,并且定义了自己的update()方法用来更新信息,其实球拍的移动就是更新了位置信息(包括碰撞)。
相应的我也给这个类写了几个静态字段用来表示球拍的一些参数,以后如果要修改这些参数的话只需要改一个部分就行了。
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace 弹球
{
///
/// 拍子:玩家通过拍子使弹球反弹,击打砖块
///
class Paddle : Actor
{
///
/// 拍子的宽度
///
private const int width = 80;
///
/// 获取拍子的宽度
///
public static int Width
{
get { return width; }
}
///
/// 拍子的高度
///
private const int height = 10;
///
/// 获取拍子的高度
///
public static int Height
{
get { return height; }
}
///
/// 拍子的移动方向,有三种情况,大于0为向右,小于0为向左,等于0为不移动,初始情况不移动
///
private Direction direction;
///
/// 获取和设置拍子的移动方向:大于0为向右,小于0为向左,等于0为不移动,初始情况不移动
///
public Direction Direction
{
get { return direction; }
set { direction = value; }
}
///
/// 拍子的速度
///
private const int speed = 20;
///
/// 获取拍子的移动速度:为10像素点
///
public static int Speed
{
get { return speed; }
}
public Paddle()
{ }
///
/// 构造函数:根据左上方顶点信息和左右移动边界创建拍子
///
///
///
///
///
public Paddle(int iX, int iY, int iBoundsX, int iBoundsY, int iBoundsWidth, int iBoundsHeight)
{
PositionBounds.SetBounds(iX, iY, Paddle.width, Paddle.height);
CollisionBounds.SetBounds(iX, iY, Paddle.width, Paddle.height);
MoveBounds.SetBounds(iBoundsX, iBoundsY, iBoundsWidth, iBoundsHeight);
direction = Direction.None;
}
public override void Draw(System.Drawing.Graphics g)
{
g.FillRectangle(new SolidBrush(Color.Yellow), new Rectangle(PositionBounds.Left, PositionBounds.Top, width, height));
g.DrawRectangle(Pens.White, new Rectangle(PositionBounds.Left, PositionBounds.Top, width, height));
//调试语句,绘制碰撞边界
//g.DrawRectangle(Pens.Red, new Rectangle(CollisionBounds.Left, CollisionBounds.Top, width, height));
}
public override void Update()
{
//更新位置信息
if (this.Direction == Direction.Left &&
((this.CollisionBounds.Left - Paddle.Speed) >= (MainWin.PlayerBounds.Left)))
{
this.MoveRight(-Paddle.Speed);
}
if (this.Direction == Direction.Right &&
((this.CollisionBounds.Right + Paddle.Speed) <= (MainWin.PlayerBounds.Right)))
{
this.MoveRight(Paddle.Speed);
}
this.Direction = Direction.None;
}
}
}
接下来就是最复杂的一个类了,其实也谈不上多么复杂,球这个东西除了子类具有的陈员外,还有一个矢量速度,和速度的绝对值这两个静态方法,同样是为了以后好修改,所以矢量速度的长度总是等于1,需要修改速度的话改绝对值大小就行。另外,为了给游戏增加一点变数,让它更好玩,所以球的初始速度包含一个随机值确定。代码如下:
private void CreateRandomVector(vector2D Vector)
{
Random rand = new Random();
Vector.setValue(rand.NextDouble() + 1, rand.NextDouble() + 1);
}
这样的话能够保证球大致的方向是右下角,而且是在一个范围内随机的。
全部代码如下:
using System;
using System.Drawing;
namespace 弹球
{
class Ball : Actor
{
///
/// 球的大小
///
private const int size = 10;
///
/// 静态属性:获取球的大小
///
public static int Size
{
get { return size; }
}
///
/// 球运动的方向
///
public vector2D Vector;
///
/// 球运动的速度
///
public const int Speed = 5;
public Ball()
{ }
///
/// 根据顶点位置,移动边界信息创建一个球
///
///
///
///
///
///
///
public Ball(int iX, int iY, int iBoundsX, int iBoundsY, int iBoundsWidth, int iBoundsHeight)
{
PositionBounds.SetBounds(iX, iY, size, size);
CollisionBounds.SetBounds(iX, iY, size, size);
MoveBounds.SetBounds(iBoundsX, iBoundsY, iBoundsWidth, iBoundsHeight);
//随机设置方向
CreateRandomVector(Vector);
}
public Ball(int iX, int iY, Bounds OtherBounds)
{
PositionBounds.SetBounds(iX, iY, size, size);
CollisionBounds.SetBounds(iX, iY, size, size);
MoveBounds.SetBounds(OtherBounds);
//随机设置方向
CreateRandomVector(Vector);
}
private void CreateRandomVector(vector2D Vector)
{
Random rand = new Random();
Vector.setValue(rand.NextDouble() + 1, rand.NextDouble() + 1);
}
public void Move()
{
CollisionBounds.Move(Vector, Speed);
PositionBounds.Move(Vector, Speed);
}
///
/// 绘制球
///
///
public override void Draw(System.Drawing.Graphics g)
{
g.FillEllipse(Brushes.Red, new Rectangle(PositionBounds.Left, PositionBounds.Top, Size, Size));
}
public override void Update()
{
//更新位置
Bounds newPosition = new Bounds(this.PositionBounds);
newPosition.Move(Vector, Speed);
//检测是否碰撞到了边界
if ((newPosition.Left < this.MoveBounds.Left))
{
newPosition.Left = this.MoveBounds.Left;
newPosition.Right = this.MoveBounds.Left + Ball.Size;
this.Vector.NegateX();
}
else if (newPosition.Right > this.MoveBounds.Right)
{
newPosition.Right = this.MoveBounds.Right;
newPosition.Left = this.MoveBounds.Right - Ball.Size;
this.Vector.NegateX();
}
if (newPosition.Top < this.MoveBounds.Top)
{
newPosition.Top = this.MoveBounds.Top;
newPosition.Bottom = this.MoveBounds.Top + Ball.Size;
this.Vector.NegateY();
}
else if (newPosition.Bottom > this.MoveBounds.Bottom)
{
newPosition.Bottom = this.MoveBounds.Bottom;
newPosition.Top = this.MoveBounds.Bottom - Ball.Size;
this.Vector.NegateY();
}
this.PositionBounds.SetBounds(newPosition);
this.CollisionBounds.SetBounds(newPosition);
}
}
///
/// 二维向量,用来表示平面上的方向,只有方向,没有大小
///
public struct vector2D
{
///
/// 横向的值
///
private double x;
///
/// 获得横向的值
///
public double X
{
get { return x; }
}
///
/// 将横向值取反
///
public void NegateX()
{
x = -x;
}
///
/// 纵向的值
///
private double y;
///
/// 将纵向值取反
///
public void NegateY()
{
y = -y;
}
///
/// 获得纵向的值
///
public double Y
{
get { return y; }
}
///
/// 构造函数:向量为单位长度,参数只代表方向
///
///
///
public vector2D(double iX, double iY)
{
double length = Math.Sqrt(iX*iX + iY*iY);
x = iX/length;
y = iY/length;
}
///
/// 注意:向量为单位长度
///
///
///
public void setValue(double iX, double iY)
{
double length = Math.Sqrt(iX * iX + iY * iY);
x = iX / length;
y = iY / length;
}
}
}
现在这个游戏的class彻底完成了,然而如何组织各种不同的类才是最重要的。