`
kinglong
  • 浏览: 32690 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

Flash游戏-SlidingPuzzle滑块拼图游戏

阅读更多
最近在研究Flash游戏的算法,发现同一种游戏能有很多种算法,而我比较喜欢面向对象和事件通知方式的算法,清清爽爽的程序结构。。。

[运行效果]

[FLASH=550,400,True]upload/SlidingPuzzle.swf[/FLASH]

[主程序类]
package {
	import com.klstudio.puzzles.slider.PuzzleBoard;

	import flash.display.Sprite;

	/**
	 * SlidingPuzzle
	 * @author Kinglong(kinglong@gmail.com)
	 * @since:2010-9-13
	 */
	public class SlidingPuzzle extends Sprite {
		[Embed(source="image.jpg")]
		private var embeddedImage : Class;
		
		private var _board:PuzzleBoard;
		public function SlidingPuzzle() {
			_board = new PuzzleBoard(300,300,4);
			addChild(_board);
			
			_board.createPuzzle(new embeddedImage());
			
			_board.startGame();
		}
	}
}

[PuzzleBoard类]
package com.klstudio.puzzles.slider {
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.display.Bitmap;
	import flash.geom.Matrix;
	import flash.display.BitmapData;
	import flash.display.Sprite;

	/**
	 * PuzzleBoard
	 * @author Kinglong(kinglong@gmail.com)
	 * @since:2010-9-13
	 */	

	public class PuzzleBoard extends Sprite {
		private var _pieces : Array;
		private var _moving : Boolean;
		private var _boardWidth : int;
		private var _boardHeight : int;
		private var _pieceWidth : Number;
		private var _pieceHeight : Number;
		private var _subdivisions : uint;
		private var _space : uint;
		private var _padding : uint;

		public function PuzzleBoard(width : uint,height : uint,subdivisions : uint = 3,padding : uint = 1,space : int = -1) {
			_pieces = [];
			_moving = true;
			
			_boardWidth = width;
			_boardHeight = height;
			_subdivisions = subdivisions = (subdivisions < 3) ? 3 : subdivisions;
			_space = (space < subdivisions * subdivisions && space > -1) ? space : subdivisions - 1; 
			_padding = padding;
			
			_pieceWidth = _boardWidth / subdivisions;
			_pieceHeight = _boardHeight / subdivisions;
		}

		public function get subdivisions() : uint {
			return _subdivisions;
		}

		public function get padding() : uint {
			return _padding;
		}

		private function scaleImage(bitmap : Bitmap) : BitmapData {
			var bd : BitmapData = new BitmapData(_boardWidth, _boardHeight);
			var bRate : Number = _boardWidth / _boardHeight;
			var iRate : Number = bitmap.width / bitmap.height;
			var matrix : Matrix = new Matrix();
			if(bRate < iRate) {
				matrix.scale(_boardHeight * iRate / bitmap.width, _boardHeight / bitmap.height);
			} else {
				matrix.scale(_boardWidth / bitmap.width, _boardWidth / iRate / bitmap.height);
			}
			bd.draw(bitmap, matrix, null, null, null, true);			
			return bd;
		}

		public function createPuzzle(bitmap : Bitmap) : void {
			clearBoard();
			var bd : BitmapData = scaleImage(bitmap);
			var pbd : BitmapData;
			var len : uint = subdivisions * subdivisions;
			var rect : Rectangle = new Rectangle(0, 0, _pieceWidth, _pieceHeight);
			var point : Point = new Point();
			for(var i : uint = 0;i < len;i++) {
				if(i == _space) {
					continue;
				}
				rect.x = (i % subdivisions) * _pieceWidth;
				rect.y = Math.floor(i / subdivisions) * _pieceHeight;
				pbd = new BitmapData(_pieceWidth, _pieceHeight);				
				pbd.copyPixels(bd, rect, point);				
				var piece : PuzzlePiece = new PuzzlePiece(pbd, new Point(i % subdivisions, Math.floor(i / subdivisions)), padding);
				piece.addEventListener(PuzzleEvent.CLICK, clickHandler);
				piece.addEventListener(PuzzleEvent.MOVE, moveHandler);
				piece.addEventListener(PuzzleEvent.READY, moveHandler);
				addChild(piece);
				_pieces.push(piece);
			}
		}

		public function startGame() : void {
			var count : uint = 0;
			var piece : PuzzlePiece;
			var position : int;
			while (count < 100) {                
				do {                    
					piece = _pieces[int(Math.random() * _pieces.length - 1)];
					position = checkNeighbours(piece);
				}while (position == -1);
				piece.move(position, false);
				count++;
			}
			_moving = false;
		}

		private function clickHandler(event : PuzzleEvent) : void {
			if(_moving) {
				return;
			}
			var position : int = checkNeighbours(event.piece);
			if(position > -1) {
				event.piece.move(position);
			}
		}

		private function moveHandler(event : PuzzleEvent) : void {
			switch(event.type) {
				case PuzzleEvent.READY:
					_moving = false;
					break;
				case PuzzleEvent.MOVE:
					_moving = true;
					break;
			}
		}

		private function clearBoard() : void {
			if(_pieces.length == 0) {
				return;
			}
			for each(var piece:PuzzlePiece in _pieces) {
				piece.removeEventListener(PuzzleEvent.CLICK, clickHandler);
				piece.removeEventListener(PuzzleEvent.READY, moveHandler);
				piece.removeEventListener(PuzzleEvent.MOVE, moveHandler);
				removeChild(piece);
			}
			_pieces = [];
		}

		private function isEmptySpace(x : int,y : int) : Boolean {            
			for each (var piece:PuzzlePiece in _pieces) {
				if(piece.point.x == x && piece.point.y == y) {
					return false;
				}
			}
			return true;
		}

		private function checkNeighbours(piece : PuzzlePiece) : int {
			if (piece.point.x > 0 && isEmptySpace(piece.point.x - 1, piece.point.y)) {				
				return PuzzlePiece.LEFT;
			}
			if (piece.point.x < subdivisions - 1 && isEmptySpace(piece.point.x + 1, piece.point.y)) {				
				return PuzzlePiece.RIGHT;
			}
			if (piece.point.y > 0 && isEmptySpace(piece.point.x, piece.point.y - 1)) {				
				return PuzzlePiece.UP;
			}
			if (piece.point.y < subdivisions - 1 && isEmptySpace(piece.point.x, piece.point.y + 1)) {				
				return PuzzlePiece.DOWN;
			}			
			return -1;
		}
	}
}

[PuzzleEvent类]
package com.klstudio.puzzles.slider {
	import flash.events.Event;

	/**
	 * PuzzleEvent
	 * @author Kinglong(kinglong@gmail.com)
	 * @since:2010-9-13
	 */	

	public class PuzzleEvent extends Event {
		private var _piece : PuzzlePiece;
		public static const MOVE : String = "MOVE";
		public static const READY : String = "READY";
		public static const CLICK : String = "CLICK";

		public function PuzzleEvent(type : String, piece : PuzzlePiece = null) {
			super(type);
			_piece = piece;
		}

		public function get piece() : PuzzlePiece {
			return _piece;
		}

		override public function clone() : Event {
			return new PuzzleEvent(type, piece);
		}
	}
}


[PuzzlePiece类]
package com.klstudio.puzzles.slider {
	import flash.filters.GradientBevelFilter;
	import flash.filters.BitmapFilter;
	import flash.filters.BitmapFilterType;
	import flash.filters.BitmapFilterQuality;
	import flash.events.MouseEvent;

	import gs.TweenLite;
	import gs.easing.Circ;

	import flash.display.Bitmap;
	import flash.display.Shape;
	import flash.geom.Point;
	import flash.display.BitmapData;
	import flash.display.Sprite;

	/**
	 * PuzzlePiece
	 * @author Kinglong(kinglong@gmail.com)
	 * @since:2010-9-13
	 */	

	public class PuzzlePiece extends Sprite {
		public static const DOWN : int = 3;
		public static const LEFT : int = 1;
		public static const UP : int = 4;
		public static const RIGHT : int = 2;

		private var _padding : uint;
		private var _ease : Function;
		private var _point : Point;
		private var _oPoint : Point;
		private var _bmp : Bitmap;
		private var _mask : Shape;

		public function PuzzlePiece(bitmapData : BitmapData,point : Point,padding : uint = 1) {
			mouseChildren = false;			
			_ease = Circ.easeInOut;
			_padding = padding;
			_oPoint = point.clone();
			_point = point.clone();
			
			_bmp = new Bitmap(bitmapData);
			addChild(_bmp);			
			
			_mask = new Shape();
			_mask.graphics.beginFill(0xFF0000);
			_mask.graphics.drawRoundRect(_padding, _padding, _bmp.width - _padding * 2, _bmp.height - _padding * 2, 8, 8);
			_mask.graphics.endFill();
			addChild(_mask);
			_bmp.mask = _mask;	
			
			x = point.x * _bmp.width;
			y = point.y * _bmp.height;
			
			addEventListener(MouseEvent.CLICK, clickHandler);		
			
			_bmp.filters = [getBitmapFilter()];
		}

		public function move(position : int,tweened : Boolean = true) : void {
			var params : Object = {ease:_ease, onComplete:tweenCompleteHandler};
			var duration : Number = 0.4;
			switch(position) {
				case LEFT:
					updatePoint(point.x - 1, point.y);
					if(tweened) {
						params["x"] = point.x * _bmp.width;
						TweenLite.to(this, duration, params);
						dispatchEvent(new PuzzleEvent(PuzzleEvent.MOVE));
					} else {
						x = point.x * _bmp.width;
					}
					break;
				case RIGHT:	
					updatePoint(point.x + 1, point.y);	
					if(tweened) {
						params["x"] = point.x * _bmp.width;
						TweenLite.to(this, duration, params);
						dispatchEvent(new PuzzleEvent(PuzzleEvent.MOVE));
					} else {
						x = point.x * _bmp.width;
					}			
					break;
				case UP:	
					updatePoint(point.x, point.y - 1);
					if(tweened) {
						params["y"] = point.y * _bmp.height;
						TweenLite.to(this, duration, params);
						dispatchEvent(new PuzzleEvent(PuzzleEvent.MOVE));
					} else {
						y = point.y * _bmp.height;
					}				
					break;
				case DOWN:	
					updatePoint(point.x, point.y + 1);
					if(tweened) {
						params["y"] = point.y * _bmp.height;
						TweenLite.to(this, duration, params);
						dispatchEvent(new PuzzleEvent(PuzzleEvent.MOVE));
					} else {
						y = point.y * _bmp.height;
					}				
					break;				
			}		
		}

		public function get point() : Point {
			return _point;
		}

		public function reset() : void {
			updatePoint(_oPoint.x, _oPoint.y);
			x = point.x * _bmp.width;
			y = point.y * _bmp.height;						
		}

		private function updatePoint(x : int,y : int) : void {
			_point.x = x;
			_point.y = y;
			if(hasCompleted()) {
				_bmp.filters = null;
			}else{
				_bmp.filters = [getBitmapFilter()];
			}
		}

		private function getBitmapFilter() : BitmapFilter {
			return new GradientBevelFilter(5, 225, [16777215, 13421772, 0], [0.4, 0, 0.4], [0, 128, 255], 8, 8, 2, BitmapFilterQuality.HIGH, BitmapFilterType.INNER, false);
		}

		public function hasCompleted() : Boolean {
			return _point.equals(_oPoint);
		}

		private function clickHandler(event : MouseEvent) : void {
			dispatchEvent(new PuzzleEvent(PuzzleEvent.CLICK, this));
		}

		private function tweenCompleteHandler() : void {
			dispatchEvent(new PuzzleEvent(PuzzleEvent.READY));
		}
	}
}
分享到:
评论

相关推荐

    SliderCheck-手搓滑块验证vue版本-兼容移动端和pc端

    SliderCheck-手搓滑块验证vue版本-兼容移动端和pc端SliderCheck-手搓滑块验证vue版本-兼容移动端和pc端SliderCheck-手搓滑块验证vue版本-兼容移动端和pc端SliderCheck-手搓滑块验证vue版本-兼容移动端和pc端...

    解决rc-slider-captcha滑块拼图验证码mode=float鼠标按下移出按钮范围时拼图面板消失问题

    滑块拼图验证码(rc-slider-captcha)是一种常见的防止机器人和自动脚本的验证机制,它在确保网站安全性的同时,尽可能地减少对用户操作的干扰。然而,当遇到"mode=float"模式下鼠标按下后移出按钮范围时拼图面板...

    实现滑块拼图游戏

    滑块拼图游戏的设计,比较符合玩家的意愿,同时采用了交互式,帮助玩家完成游戏。

    【uni-app】自定义-图形滑块验证码,后端php 的演示视频

    它的核心原理是生成一张包含随机图形的图片,并在图片上设置一个可移动的滑块,用户需要正确拖动滑块完成拼图才能通过验证。这种验证码方式既提高了用户体验,又具有一定的安全性。 在uni-app中实现自定义图形滑块...

    小程序游戏源码 滑块拼图.zip

    本源码提供了一套完整的滑块拼图游戏解决方案,适合开发者进行二次开发或学习游戏编程。下面将详细介绍这个源码中的关键知识点。 1. **微信小程序框架**:此游戏源码基于微信小程序开发,微信小程序是一种轻量级的...

    微信小程序-滑块拼图游戏.zip

    【微信小程序滑块拼图游戏】是一个基于微信小程序平台开发的小型娱乐应用,它利用了微信小程序提供的API和框架,为用户提供了简单的拼图游戏体验。这个项目涉及到的知识点广泛,包括前端开发、微信小程序开发规范、...

    emWin模拟器 - SLIDER滑块控件

    emWin模拟器 - SLIDER滑块控件

    腾讯、网易、极验滑块识别-通用滑块识别

    滑块识别技术是网络安全与爬虫技术领域中的一个重要话题,主要应用于验证码系统,旨在防止恶意爬虫自动操作。本文将详细解析"腾讯、网易、极验滑块识别-通用滑块识别"这一主题,以及如何利用提供的OCR.dll库来解决...

    e语言-网易滑块坐标识别算法

    "e语言-网易滑块坐标识别算法" 指的是一个使用E语言(Easy Language)编写的程序,目标是实现对网易游戏中滑块验证的坐标识别算法。这种验证通常用于防止机器人自动操作,增加用户的人工交互验证。通过计算滑块移动...

    滑块拼图游戏(PuzzleX)

    这是一款Android下的滑块拼图游戏。有多种图片可供选择。可以设置游戏难度,把原始图片分成3x3,4x4,5x5的小块,打乱之后,通过移动小块来还原图片。 This is a puzzle game app under Android system. There are ...

    JavaScript应用实例-微信滑块.js

    JavaScript应用实例-微信滑块.js

    VC编的小游戏------九宫格拼图

    9. **多线程编程**:尽管九宫格拼图游戏可能不需要多线程,但了解如何在VC中使用多线程是提升游戏性能的一个方向,例如,可以将用户界面更新和游戏逻辑计算分开到不同的线程中。 10. **调试与测试**:VC集成的调试...

    易语言-TX滑块轨迹算法纯源码,100%可过滑块

    易语言-TX滑块轨迹算法纯源码是一种用于网络验证的解决方案,主要目的是为了通过滑块验证机制。滑块验证通常被用在网络登录、注册或防止自动化脚本等场景,以确保操作是由真实人类执行的。这个算法的独特之处在于它...

    Android-Android滑块验证码控件

    它通过提供一种交互式的验证方式,要求用户手动拖动一个滑块来完成一段图像或拼图,从而防止自动化的恶意操作。这篇文档将深入探讨如何在Android项目中实现这种控件。 首先,滑块验证码的核心原理是生成一个不完整...

    AutoJs源码-微信滑块

    AutoJs源码-微信滑块。本资源购买前提醒:本源码都是实际autojs项目模板,安装好autojs直接运行即可打开。1、支持低版本autojs。2、资源仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您自己承担!。3、...

    行业分类-设备装置-摆杆滑块往复式太阳翼辅助翻转机构.zip

    标题中的“摆杆滑块往复式太阳翼辅助翻转机构”是一种在航天或机械工程领域常见的装置,主要用于控制和调整太阳能电池板(通常被称为太阳翼)的角度,以确保最佳的能源采集效率。这种机构利用摆杆和滑块的机械原理来...

    电子政务-并行滑块式电磁压力机.zip

    在"电子政务-并行滑块式电磁压力机.zip"这个压缩包中,主要包含了一个名为"行业分类-电子政务-并行滑块式电磁压力机.pdf"的文件,这似乎是一个关于电子政务在特定机械设备领域的应用案例,具体来说,是涉及并行滑块...

    集成aj-captcha实现滑块验证码.zip

    滑块验证码是一种常见且有效的防止机器人和自动脚本的手段,它增加了用户交互性,同时降低了恶意攻击的可能性。本集成教程将详细介绍如何在项目中使用aj-captcha库来实现滑块验证码功能,特别适用于基于若依前后端...

    滑块拼图.zip小程序小游戏源码微信小程序源码下载

    滑块拼图.zip小程序小游戏源码微信小程序源码下载滑块拼图.zip小程序小游戏源码微信小程序源码下载滑块拼图.zip小程序小游戏源码微信小程序源码下载滑块拼图.zip小程序小游戏源码微信小程序源码下载 1.合个人学习...

Global site tag (gtag.js) - Google Analytics