我正在编写一个简单的小行星克隆游戏,使用Swing
显示图形。我有点喜欢德里克·巴纳斯的教程,但我决定自己扩展。
最初的想法是,游戏中的每一个图形元素(即小行星、飞船和子弹)都扩展了Polygon
类。他们的构造函数看起来如下所示:
public class SpaceShip extends Polygon {
//x and y coordinates
public static int[] polyXArray = {...};
public static int[] polyYArray = {...};
//other class variables
{...}
public SpaceShip() {
super(polyXArray, polyYArray, polyXArray.length);
}
}
其他图形元素也是一样的。
编辑:这里的关键元素是,这两个数组不存储对象的实际坐标,而是它们相对于中心的位置,其坐标是double
-type类变量。因此,数组只描述对象的形状,而子类move()
方法将影响中心的坐标。负责实际绘制的类将调用move()
方法,然后应用仿射变换来移动和旋转形状(根据正确定义的角度参数)。我这样做是为了避免与处理double
算法相关的精度问题。
现在,由于元素有许多“相等”变量(它们的中心坐标,为了用仿射变换将它们转换为中心坐标,它们的速度分量等等)和方法(getter和setter、move()
方法等)我想让它们成为一个抽象类的扩展,比方说,GameShape
,它包含了所有这些常见的方法和变量。现在,GameShape
将直接扩展Polygon
:
public abstract class GameShape extends Polygon {
//x and y coordinates, still unassigned
public static int[] polyXArray, polyYArray;
//other class variables
{...}
public GameShape() {
super(polyXArray, polyYArray, polyXArray.length);
}
}
然后,当我定义不同的子类以绘制我需要的不同形状时,我想要将所需的值分配给polyXArray
和polyYArray
,但是我还没有找到一种方法。
我确实希望这些变量是静态的,因为它们是单个类的特定属性,而且我不希望每次实例化新对象时都将它们作为参数传递。
我的情况与这个问题中描述的情况非常相似,但建议的解决方案似乎不起作用,因为我需要构造函数中的那些变量。有什么办法可以克服这个问题吗?不管过程如何,我的主要目标是拥有一个与所有图形元素共同的超类,以避免数十行复制粘贴的代码。
发布于 2015-10-07 13:02:36
编辑:
正如VGR在评论中指出的那样,这将不会编译。因此,我们将不得不稍微修改实现,即我们将使用have关系而不是IS关系:)
首先,不要使聚数组字段静态。如果您这样做了,那么对于所有的子类来说,它们都是相同的,那么有什么意义呢?
其次,在这里使用模板方法设计模式。你的课会是这样的:
public abstract class GameShape {
//x and y coordinates, still unassigned
public int[] polyXArray, polyYArray;
private Polygon polygon;
//other class variables
{...}
public GameShape() {
instantiatePolyArrays();
this.polygon = new Polygon(polyXArray, polyYArray, polyXArray.length);
}
protected abstract void instantiatePolyArrays();
public final Polygon getPolygon(){
return this.polygon;
}
}
每个扩展类都必须重写此方法,并且可以为每个方法重写中的每个类实例化数组。
另外,还有一个关于is - with问题的词--在您的示例中,您展示的是一个IS关系,其中GameShape
对象是一个Polygon
,因此需要调用超级构造函数,并由此产生问题。在我的解决方案中,这被替换为一个HAS关系,其中GameShape
对象内部有一个Polygon
对象,并使用getPolygon()方法进行访问。这允许您有更多的灵活性:-)
发布于 2015-10-07 13:05:53
您有一对数组,用于描述特定种类的游戏对象的形状。如果不同的游戏对象可以有不同的形状,那么它们都不能共享一个单独的数组,就像它们是所有游戏对象类的公共超类的静态属性一样。同一类型的不同对象可以共享相同的数组(假设这些数组不需要在每个对象的基础上进行修改),这可能对应于这些数组是具体游戏对象类的静态字段。但是,在这种情况下,如果您希望这些类的超类能够访问给定游戏对象的正确形状数据,那么必须告诉它这些形状数据是什么。
有两种主要的方法可以做到这一点:
发布于 2015-10-07 13:08:26
数组字段不能是static
,因为不同形状的坐标不同。另外,在特定的子类中不需要这些数组,因为它们已经在Polygon
或GameShape
中了。
下面是我编写GameShape
的方式(虽然我同意@Michael,您不需要同时将polyXArray
和polyXArray.length
传递给构造函数)。
public abstract class GameShape extends Polygon {
// I got rid of the array fields as I think they are in Polygon anyway.
//other class variables
{...}
// I added arguments to your constructor.
public GameShape(int[] polyXArray, int[] polyYArray) {
super(polyXArray, polyYArray, polyXArray.length);
}
}
问题是super
必须是构造函数的第一行,但是可以使用私有方法来构建数组:
public final class BoringRectangle extends GameShape {
public BoringRectangle(int left, int right, int top, int bottom) {
super(xArray(left, right), yArray(top, bottom));
}
private static int[] xArray(int left, int right) {
return new int[] {left, right, right, left};
}
private static int[] yArray(int top, int bottom) {
return new int[] {bottom, bottom, top, top};
}
}
https://stackoverflow.com/questions/33002225
复制相似问题