游戏开发论坛

 找回密码
 立即注册
搜索
查看: 6944|回复: 3

史上最简JAVA拼图游戏实现。

[复制链接]

10

主题

18

帖子

28

积分

注册会员

Rank: 2

积分
28
发表于 2007-10-16 20:13:00 | 显示全部楼层 |阅读模式
package org.test;



/**
* <p>Title: LoonFramework</p>
* <p>Description:拼图图像处理[未优化](优化算法已内置于loonframework-game框架中。)</p>
* <p>Copyright: Copyright (c) 2007</p>
* <p>Company: LoonFramework</p>
* @author chenpeng  
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Event;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.image.BufferedImage;

import org.loon.framework.game.helper.ImageHelper;

public class BlockImage extends Canvas {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    private Image _img;

    private Image _img2;

    private Graphics bg;

    private Image backimage;

    private int blocks[];

    private boolean isEvent;

    private MediaTracker mt;

    private int _width;

    private int _height;

    private int _RS;

    private int _CS;

    private Image screen = null;

    private Graphics later = null;

    private int _objWidth;

    private int _objHeight;

    private int _COUNT;

    /**
     * 析构函数,内部调用init方法。
     *
     * @param bImage
     * @param overImage
     * @param cs
     * @param rs
     */
    public BlockImage(Image bImage, Image overImage, int cs, int rs) {
        init(bImage, overImage, cs, rs);
    }

    /**
     * 初始化拼图参数。
     *
     * @param bImage
     * @param overImage
     * @param cs
     * @param rs
     */
    public void init(Image bImage, Image overImage, int cs, int rs) {
        // 列数
        _CS = cs;
        // 行数
        _RS = rs;
        // 加载拼图用图像。
        _img = bImage;

        // 获得实际窗体宽。
        _width = _img.getWidth(null);
        // 获得实际窗体高。
        _height = _img.getHeight(null);
        // 获得单块图像宽。
        _objWidth = _width / _CS;
        // 获得单块图像高。
        _objHeight = _height / _RS;

        // 本程序直接使用backimage上一块图形区域缓冲选择项,所以实际背景图像高=图形高+额外图块高。
        backimage = new BufferedImage(_width, _height + _objHeight, 1);
        // 获得生成的图形
        later = backimage.getGraphics();
        // 再创建一块图像区域,作为图像缓存用。
        screen = new BufferedImage(_width, _height, 1);
        // 获得缓存的图形
        bg = screen.getGraphics();
        // 获得等同图片总数的数组。
        _COUNT = _CS * _RS;
        blocks = new int[_COUNT];
        // 初始化为非点击。
        isEvent = false;
        // 加载完成拼图的显示图。
        _img2 = overImage;
        // 初始化图块参数。
        for (int i = 0; i < _COUNT; i++) {
            blocks = i;
        }
        // 载入MediaTracker,用以跟踪图像状态。
        mt = new MediaTracker(this);
        // 加载被跟踪的图像。
        mt.addImage(_img, 0);
        mt.addImage(_img2, 0);
        // 同步载入。
        try {
            mt.waitForID(0);
        } catch (InterruptedException interruptedexception) {
            return;
        }
        // 随机生成图像面板内容。
        rndPannel();

    }

    /**
     * 描绘窗体图像。
     */
    public void paint(Graphics g) {
        // 检查图像载入。
        if (mt.checkID(0)) {
            // 描绘底层背景。
            bg.drawImage(backimage, 0, 0, null);
            // 判断是否触发完成事件。
            if (!isEvent) {
                // 设置背景色。
                bg.setColor(Color.black);
                // 循环绘制小图片于背景缓存中。
                for (int i = 0; i < _CS; i++) {
                    for (int j = 0; j < _RS; j++)
                        bg.drawRect(i * _objWidth, j * _objHeight, _objWidth,
                                _objHeight);

                }

            }
            // 仅当完成事件触发并且有胜利图片时,载入完成提示。
            if (isEvent && _img2 != null) {
                bg.drawImage(_img2, 0, 0, null);
            }
        }
        // 举凡绘制图像时,应遵循显示图像仅绘制一次的基本原则,一次性的将背景绘制到窗体。
        // 简单来说,也就是采取[双缓存]的方式,所有复杂操作皆在缓存区完成,也只有这样才能避免产生延迟闪烁。
        g.drawImage(screen, 0, 0, this);
        g.dispose();
    }

    /**
     * 变更图像。
     */
    public void update(Graphics g) {
        paint(g);
    }

    /**
     * 鼠标点击事件。
     */
    public boolean mouseDown(Event event, int i, int j) {

        if (isEvent)
            return true;
        // 换算点击位置与小图片。
        int k = i / _objWidth;
        int l = j / _objHeight;
        copy(0, 0, 0, _RS);
        copy(k, l, 0, 0);
        copy(0, _RS, k, l);
        int i1 = blocks[0];
        // 换算选中图片存储区。
        blocks[0] = blocks[l * _CS + k];
        blocks[l * _CS + k] = i1;
        int j1;
        for (j1 = 0; j1 < _COUNT; j1++) {
            if (blocks[j1] != j1) {
                break;
            }
        }
        if (j1 == _COUNT)
            isEvent = true;
        repaint();
        return true;
    }

    public boolean mouseUp(Event event, int i, int j) {
        return true;
    }

    public boolean mouseDrag(Event event, int i, int j) {
        return true;
    }

    /**
     * copy换算后的图像区域。
     *
     * @param i
     * @param j
     * @param k
     * @param l
     */
    void copy(int i, int j, int k, int l) {
        later.copyArea(i * _objWidth, j * _objHeight, _objWidth, _objHeight,
                (k - i) * _objWidth, (l - j) * _objHeight);
    }

    /**
     * 事件触发状态。
     * @return
     */
    public boolean isEvent() {
        return isEvent;
    }

    public void setEvent(boolean isEvent) {
        this.isEvent = isEvent;
    }

    /**
     * 随机生成面板图片。
     *
     */
    void rndPannel() {
        later.drawImage(_img, 0, 0, this);
        for (int i = 0; i < (_COUNT * _CS); i++) {
            int j = (int) ((double) _CS * Math.random());
            int k = (int) ((double) _RS * Math.random());
            int l = (int) ((double) _CS * Math.random());
            int i1 = (int) ((double) _RS * Math.random());
            copy(j, k, 0, _RS);
            copy(l, i1, j, k);
            copy(0, _RS, l, i1);
            int j1 = blocks[k * _CS + j];
            blocks[k * _CS + j] = blocks[i1 * _CS + l];
            blocks[i1 * _CS + l] = j1;
        }

    }

    public static void main(String[] args) {

        Frame frm = new Frame("简单的JAVA拼图效果实现[由Loonframework框架提供]");
        frm.setSize(480, 500);
        frm.setResizable(false);
        /**
         * PS:ImageHelper.loadImage为Loonframework框架中helper下方法,为不依赖于javax扩展包而开发。
         * 可使用ImageIO相关方法代替。
         */
        // 加载图像。
        Image backImage = ImageHelper.loadImage("C:/backimage.jpg", true);
        Image overImage = ImageHelper.loadImage("C:/over.gif", true);
        // BlockImage中参数分别为 用于分解的拼图,完成后显示文字,拆分图片为分几列,分拆分图片为几行。
        //建议使用正方形图片作为背景图。
        frm.add(new BlockImage(backImage, overImage, 4, 4));
        backImage = null;
        overImage = null;
        // 显示窗体。
        frm.setVisible(true);

    }

}


详细操作参见源码注释,所用图片如下(也可自由选取图形),本代码算法支持自由成比例分隔图像行列,效果如下:
















0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2011-8-15 10:53:00 | 显示全部楼层

Re: 史上最简JAVA拼图游戏实现。

org.loon.framework.game.helper.ImageHelper;
你能不能发给我。我的邮箱1274311905@qq.com

谢谢!!!

0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2012-11-21 13:47:00 | 显示全部楼层

Re: 史上最简JAVA拼图游戏实现。

能不能请教一下这个具体是怎么实现的?(在下初学)
邮箱735841074@qq.com

0

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2013-7-2 11:35:43 | 显示全部楼层
好想知道这个具体要怎么实现?java初学者留。我的邮箱是:840811411@qq.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-2-26 14:17

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表