nodezscene.java
来自「java learn PPT java learn PPT java learn」· Java 代码 · 共 356 行
JAVA
356 行
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import magic.gamelet.*;
import magic.actor2d.*;
import magic.debug.*;
import magic.scene.*;
import magic.graphics.*;
public class NodezScene extends Scene
{
// 装载节点相关信息的ActorGroup2D对象
private NodeGroup nodeGroup;
// 容纳实际节点的Vector
private Vector nodes;
// 连接节点的线条的颜色和笔划
private final Color CIRCUIT_COLOR = new Color(255, 50, 50);
private final Stroke CIRCUIT_STROKE = new BasicStroke(4.0f);
// 绘制线圈的线条的2-D数组
// 比如, { 2, 3 }将在索引为2和3的节点间连接一条线
private int[][] circuits;
// 上述数组中的线条相互连接的索引对
private Line2D[] circuitLines;
// 用户的选择
private Node selection1;
private Node selection2;
// 根据传入的边界和Applet引用创建一个 NodezScene 对象
public NodezScene(Rectangle2D r, java.applet.Applet a)
{
super(r, r);
// 为Nodez创建并初始化一个新的 NodezGroup 对象
nodeGroup = new NodeGroup();
nodeGroup.init(a);
// 创建vector并初始化选择
nodes = new Vector();
selection1 = null;
selection2 = null;
}
// 通过把它添加到nodez vector去的方法在画面中添加一个节点
public void add(Actor2D a)
{
nodes.add(a);
}
// 把传入的级别加载到画面中
public void loadLevel(int level)
{
// 用给定的级别数得到一个静态的NodezLevel结构.
NodezLevel nodezLevel = NodezLevel.getLevel(level);
// 返回值为null表明没有级别数据匹配这个级别数
if(nodezLevel == null)
{
Debugger.reportError(Debugger.FATAL_ERROR, "Invalid level specification",0);
return;
}
// 从level结构中获得 1)节点的位置和 2) 线圈的索引数组
Vector2D[] nodePos = nodezLevel.getNodePos();
circuits = nodezLevel.getCircuits();
// 清除Vector和选择
nodes.clear();
selection1 = null;
selection2 = null;
// 节点将相对窗体的中心放置所以它们会适应不同大小的窗体
double anchorX = getBounds().getWidth() * 0.5f;
double anchorY = getBounds().getHeight() * 0.5f;
// 给level结构中的每一个位置创建一个 Node
for(int i = 0; i < nodePos.length; i++)
{
// 用给定的 NodeGroup, 索引和位置创建一个节点
Node n = new Node(nodeGroup, i, new Vector2D.Double(anchorX + nodePos[i].getX(),
anchorY + nodePos[i].getY()));
add(n);
}
// 创建索引为[0, nodes.length-1]的数组,并对这个数组进行随机化
// 这个随机数组将作为节点的目标索引
int[] indexDest = new int[nodes.size()];
for(int i = 0; i < indexDest.length; i++)
{
indexDest[i] = i;
}
// 不断随机产生并填充目标索引直到有一些节点开始就正确
do
{
Random r = new Random();
for(int i = 0; i < indexDest.length; i++)
{
int temp = indexDest[i];
int rand = r.nextInt(indexDest.length);
indexDest[i] = indexDest[rand];
indexDest[rand] = temp;
}
int j = 0;
for(Enumeration e = nodes.elements(); e.hasMoreElements(); )
{
((Node) e.nextElement()).setCircuitIndexDest(indexDest[j++]);
}
} while(getNumCorrect() > 0);
// 填充x,y线条值
Node node1;
Node node2;
circuitLines = new Line2D.Double[circuits.length];
for(int i = 0; i < circuits.length; i++)
{
// 得到节点0和1等等...
node1 = (Node)nodes.get(circuits[i][0]);
node2 = (Node)nodes.get(circuits[i][1]);
// ...把它们的 x, y 值填充到线条数组中
circuitLines[i] = new Line2D.Double(node1.getX(), node1.getY(),
node2.getX(), node2.getY());
}
}
// 从画面中得到NodeGroup
public NodeGroup getNodeGroup()
{
return nodeGroup;
}
// 返回当前局中节点的数目
public int getNumNodes()
{
return nodes.size();
}
// 返回正确的节点的数目
public int getNumCorrect()
{
int numCorrect = 0;
for(Enumeration e = nodes.elements(); e.hasMoreElements(); )
{
if(((Node) e.nextElement()).isCorrect())
{
++ numCorrect;
}
}
return numCorrect;
}
// 处理在传入的Node对象上进行的鼠标左击事件
private void processLeftClick(Node n)
{
// 如果第一个选择没有设置,那么现在设置它
if(selection1 == null)
{
selection1 = n;
// 确保节点是按照1,2的顺序选择的
if(selection2 != null)
{
selection2.setSelected(false);
}
n.setSelected(true);
// 播放做出选择的声音
Gamelet.playSound(Nodez.NODE_SELECTED1, false);
return;
}
// 否则,选择第二个节点并测试交换
else
{
selection2 = n;
selection2.setSelected(true);
// 播放做出选择的声音
Gamelet.playSound(Nodez.NODE_SELECTED2, false);
// 如果同一个节点被选中两次,则取消它的选中状态
if(selection1 == selection2)
{
selection1.setSelected(false);
selection1 = null;
selection2 = null;
}
// 否则,测试节点的交换
else if(canSwap(selection1.getCircuitIndex(), selection2.getCircuitIndex()))
{
// 交换节点
Node.swap(selection1, selection2);
// 重置选择
selection1 = null;
// 检测这样做是不是已经解开了难题
if(getNumCorrect() == getNumNodes())
{
Gamelet.playSound(Nodez.GAME_OVER, false);
}
}
// 不应该做交换; 交换选项1的设置到选项2
// 这样可以按照这个顺序做匹配
else
{
selection1.setSelected(false);
selection1 = selection2;
}
}
} // processLeftClick
// 处理给定节点上的右击事件-- this will toggle the flagged
// state of the node
private void processRightClick(Node n)
{
n.toggleFlagged();
// 根据标记的状态播放声音
if(n.isFlagged())
{
Gamelet.playSound(Nodez.TOGGLE_FLAG_ON, false);
}
else
{
Gamelet.playSound(Nodez.TOGGLE_FLAG_OFF, false);
}
}
// 处理给定的点上的鼠标点击事件 (左击或者右击)
public void processMouseClick(Point p, int button)
{
// 看看哪一个节点包含了所传入的点
Node n;
for(Enumeration e = nodes.elements(); e.hasMoreElements(); )
{
n = (Node) e.nextElement();
// 只有 "静止"的节点才能被选中
if(! n.isMoving())
{
// 如果节点包含这个点,则在它上面执行动作
if(n.contains(p))
{
if(button == MouseEvent.BUTTON1)
{
processLeftClick(n);
}
else if(button == MouseEvent.BUTTON3)
{
processRightClick(n);
}
return;
}
}
}
}
// 检测是否游戏终止--如果画面上所有的节点都被正确放置则游戏终止
public boolean gameOver()
{
return (getNumCorrect() == getNumNodes());
}
// 判断画面是否已经 "安置好了";也就是说,是否有节点还在移动
public boolean isSettled()
{
for(Enumeration e = nodes.elements(); e.hasMoreElements(); )
{
if(((Node) e.nextElement()).isMoving())
{
return false;
}
}
return true;
}
// 判断两个节点是否可以互换; 也就是说,它们是否通过一般的线圈线条连接
private boolean canSwap(
int x, // 第一个节点的索引
int y // 第二个节点的索引
)
{
// 不要让一个节点和它自己交换
if(x == y)
{
return false;
}
// 这个测试理解起来比较麻烦.
// 如果 x = 2 并且 y = 3, 那么我们将需要找到一个回路
// 这个回路的第一个值是2或者3并且它的第二个值也是2或者3
int len = circuits.length;
for(int i = 0; i < len; i++)
{
if( (circuits[i][0] == x || circuits[i][0] == y) &&
(circuits[i][1] == x || circuits[i][1] == y))
{
return true;
}
}
return false;
}
// 更新节点元素Vector
public void update()
{
for(Enumeration e = nodes.elements(); e.hasMoreElements(); )
{
((Node) e.nextElement()).update();
}
}
// 绘制画面
public void paint(Graphics2D g2d)
{
// 首先绘制节点回路
g2d.setPaint(CIRCUIT_COLOR);
g2d.setStroke(CIRCUIT_STROKE);
for(int i = 0; i < circuitLines.length; i++)
{
g2d.draw(circuitLines[i]);
}
// 创建一个透明度为25%的合成
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));
// 绘制节点
for(Enumeration e = nodes.elements(); e.hasMoreElements(); )
{
((Node) e.nextElement()).paint(g2d);
}
}
} // NodezScene
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?