javafx做游戏之连连看(1)

连连看是一款非常经典的游戏。

在接下来的blog中将详细讲解javafx如何做连连看游戏。

连连看规则:任意两个Tile可以用小于等于3条线连起来,则满足消除规则。

一、功能概述:

1、支持背景音乐。

2、支持刷新、提示等高级功能。

3、支持Tiles消除动画。

二、效果图

三、在线运行地址

连连看

四、设计思路

本篇中将重点讲解Tile对象的设计:

从图中或运行效果中我们可以看出Tile包含以下属性:

1、位置(每个Tile在canvas上初始化位置不一样)

2、类型(相同类型才能连接)

3、显示图片(不同类型用不同图片显示)

4、选中特效

另外,Tile还包含以下功能:

1、选择第一个Tile时,显示选中标识,并在canvas中记录。

2、选择第二个Tile时,如果第二个Tile就是第一个Tile,则反选第一个Tile,并清空canvas中记录。

           如果两个Tile不能消除,则先清除第一个Tile的相关记录,然后把第二个Tile当第一个Tile处理。

           如果可以消除,则消除这两个Tile。

下面看javafx中代码实现:

public class Tile extends Parent {
    // 记录单元格位置
    public ObjectProperty<Point> index = new SimpleObjectProperty<Point>();
    // 单元格类型
    public StringProperty type = new SimpleStringProperty();
    // 所在画布对象
    public War3Canvas canvas;
    // 是否可点击
    public boolean clickable = true;
    // 用于点击后实现单元格特效
    private DoubleProperty strokeAlpha = new SimpleDoubleProperty(0.0);
    public Timeline fade = new Timeline();
    // 单元格图片
    private ObjectProperty<Image> imageProperty = new SimpleObjectProperty<Image>();
    // 单元格边框颜色
    private ObjectProperty<Color> colorProperty = new SimpleObjectProperty<Color>();

    // 用于变化两个单元格位置时临时存储Point
    public Point tempPoint;

    public Tile(final War3Canvas canvas, Point index, String type) {
        initArgs();
        this.index.set(index);
        this.canvas = canvas;
        this.type.set(type);
        this.strokeAlpha.set(0);
        getChildren().add(create());
        setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                handleAction();
            }
        });
    }

    // 点击事件处理
    private void handleAction() {
        // 不可点击,说明已经不存在了,直接返回
        if (!clickable) {
            return;
        }
        // 第一次点击,用于选择开始连接点
        if (canvas.tempStart == null) {
            canvas.tempStart = this;
            fade.setRate(10);
            fade.play();
            return;
        }// 开始连接点已经选好
        else {
            if (canvas.tempStart == this) {
                canvas.tempStart = null;
                fade.setRate(-10);
                fade.play();
                return;
            } else {
                canvas.tempEnd = this;
                canvas.tempStart.fade.setRate(-10);
                canvas.tempStart.fade.play();
                canvas.tempEnd.fade.setRate(10);
                canvas.tempEnd.fade.play();
                // 如果类型相同,则查找连接路径
                if (canvas.tempStart.getType().equals(canvas.tempEnd.getType())) {
                    List<Point> path = canvas.findPath(
                            canvas.tempStart.getPoint(),
                            canvas.tempEnd.getPoint());
                    if (path != null) {
                        canvas.tempStart.clickable = false;
                        canvas.tempEnd.clickable = false;
                        canvas.tempStart = null;
                        canvas.tempEnd = null;
                        canvas.drawLine(path);
                    } else {
                        canvas.tempStart = canvas.tempEnd;
                        canvas.tempEnd = null;
                    }
                } else {
                    canvas.tempStart = canvas.tempEnd;
                    canvas.tempEnd = null;
                }
            }

        }
    }

    private void initArgs() {
        index.addListener(new ChangeListener<Point>() {
            @Override
            public void changed(ObservableValue<? extends Point> observable,
                    Point oldValue, Point newValue) {
                tempPoint = newValue;
                setTranslateX(newValue.col * (Utils.ELEMENTSIZE + 5) + 60);
                setTranslateY(newValue.row * (Utils.ELEMENTSIZE + 5) + 60);
            }
        });
        type.addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable,
                    String oldValue, String newValue) {
                Image image = new Image(Tile.class
                        .getResourceAsStream(newValue), Utils.ELEMENTSIZE - 5,
                        Utils.ELEMENTSIZE - 5, true, true);
                imageProperty.set(image);
            }
        });
        strokeAlpha.addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable,
                    Number oldValue, Number newValue) {
                Color color = Color.color(0, 0.8, 0, newValue.doubleValue());
                colorProperty.set(color);
            }
        });
        KeyFrame frame1 = new KeyFrame(Duration.ZERO, new KeyValue(strokeAlpha,
                0, Interpolator.LINEAR));
        KeyFrame frame2 = new KeyFrame(Duration.millis(500), new KeyValue(
                strokeAlpha, 1, Interpolator.LINEAR));
        fade.getKeyFrames().addAll(frame1, frame2);
    }

    // 生成单元格UI
    private Node create() {
        Group group = new Group();
        Rectangle rec = new Rectangle(Utils.ELEMENTSIZE, Utils.ELEMENTSIZE,
                Color.WHITE);
        rec.strokeProperty().bind(colorProperty);
        rec.setStrokeWidth(3);
        rec.setArcWidth(10);
        rec.setArcHeight(10);

        ImageView view = new ImageView();
        view.setTranslateX(3);
        view.setTranslateY(3);
        view.imageProperty().bind(imageProperty);
        group.getChildren().addAll(rec, view);
        return group;
    }

    public String getType() {
        return type.get();
    }

    public Point getPoint() {
        return index.get();
    }

    @Override
    public String toString() {
        return "[" + getPoint().row + "," + getPoint().col + "]";
    }
}

 

 连连看完整源码

 更多源码

posted on 2012-11-12 13:47  韩细  阅读(2587)  评论(1编辑  收藏  举报