用Racket做一个拼图游戏-01
1 前言
Racket作为Lisp语言的一个分支,拥有强大的编程逻辑构建能力,其强大的宏构建能力更是让他成为了创建语言的语言。Racket在原Scheme简洁的基础上得到更广泛的发展,在系统编程、图形界面编程、网络编程等均有不俗的表现。
经常遇到一些朋友提问说能用Racket做什么?如何用Racket做桌面GUI应用程序?本文通过一个拼图游戏的构建,展示如何从0开始用Racket完成一个桌面GUI游戏程序,其间涵盖了Racket做桌面应用的主要功能,同时也可以作为Racket入门的读物。
文内会在每一部分析完成步骤和思路,也会详细解析各使用的函数的功能,力图使读者清晰地理解用Racket是如何完成每一步编程的,以从中感受Racket的魅力。
2 设计目标
本文实现一个基本的拼图游戏。游戏者能够通过调换小块图片位置来重新把打乱的图块恢复成一张完整的图片。用户可以自己更换图片,设定图块分隔复杂度等。
3 设计思路
拼图本质上就是将一张完整的图片通过行列分割成相同大小的小块,然后打乱重排,并将重排后的图像展示给用户,有用户重新恢复拼合的过程。
由此,我们把游戏分为两大部分,一部分是将图片分割打乱的过程,这部分工作在后台完成;另一部分是将打乱重排的图片展示给用户,由用户重新拼合的交互过程,这部分通过图形界面和用户交互完成。
在Racket中是可以直接通过在交互栏内显示结果的,这个结果可以使文本内容,也可以是图形内容,这就给调试有图形输出的程序提供了极大的便利。
有了这个便利,我们可以先把有关图片操作的相关函数全部先写出来,然后把这些函数进行按需组合,就能实现了我们需要的程序——这就是自底向上的程序设计。然后我们设计好GUI中的相应功能界面,把相应的功能一个个和GUI功能界面连接,就完成了整个游戏了——这就是自顶向下的程序设计。
好了,我们先来看看底层需求有哪些?
3.1 图片操作功能
具体每个功能对应哪个函数,后续程序设计部分可以看到,也可以对应源代码说明。
取得源图片——从存储介质中读取图片;
设置拼图图片尺寸——给定一个拼图图片大小的尺寸;
调整图片大小——读取的图片不一定是需要的尺寸,需要根据需要进行调整;
设置单元格行数列数——这个用来分割拼图图片,行列数越多拼起来越复杂;
调换单元格——将分割的图片中的指定两个单元格调换,这是打乱拼图的基础,对所有单元格进行调换就实现了打乱单元格的功能;
设置混合图片——将打乱混合的各个单元格图块组合成一张待拼图,这个用来展示给用户;
重置混合图片——考虑到用户可能觉得显示出来的拼图不够乱,可以再来打乱一次;
恢复混合图——考虑到用户拼到半途觉得没过瘾,需要再拼一次拼过的拼图,再给他一次机会;
绘制混合图片——把混合拼图绘制出来;
绘制目标图片——这个用来给用户一个完成的目标图片小样作为参照,可以提示或引导用户完成拼图操作;
根据坐标位置转id——因为我们使用鼠标操作,这里把鼠标光标位置转换成单元格图片的标志号(ID号。具体为什么要用ID号,下边专门做解释);
绘制空白单元格——把单元格图块移走了,还没有填充图片的状态,就留下空白单元格,这是为了交互动画而需要的,具体原因下边解释;
在指定单元格位置绘制指定单元格内容——这个比较直白,就是在指定的单元格把指定的图块画上;
在指定坐标位置绘制指定单元格——把一个单元格的图块移到了其他单元格放上,就得在那个位置上把新的图块画出来;
绘制焦点单元格——如果鼠标移到某个单元格上,给出一个框做提示;
绘制失焦单元格——如果鼠标移出某个单元格,清除焦点提示;
取得当前单元格id——通过给定单元格行列号得到单元格ID号;
指定的id有效——判断给出的ID号是否属于拼图图块列表中的,防止误给出ID号;
根据拖动的坐标位置判断单元格id——当用鼠标按住一个单元格图块并拖动的时候,需要随时知道拖到哪个位置了,以便于后续的操作;
判断是否成功完成拼图——完成拼图了吗?这个需要随时检查判断一下,很多时候拼没拼对用户是无法判断的,因为图块之间太相似了;
初始化拼图数据——每个程序开始之前,难免要做些准备,这个就干这个的。
大致就是这些吧,如果有需要,后续还可以添加。
解释两个问题,当然对于熟系的朋友来说并不一定需要。
为什么要对每个图块标记ID号? 这涉及到数据结构问题。数据结构我们在下边做一个简略说明,这里不做叙述,单就ID号的作用做一个说明。
必须的是,每个单元格图块都要唯一进行标记才能操作,这是没有疑问的。本来单元格图块直接用行号及列号就可以表示,也能够唯一标识,但是在用户拼图的时候,总会调来调去,位置一定会打乱的,这样我们就无法重新定位图块在原图上的位置(原图位置的一个用处是判断拼图是否完成),也不能定位刚打乱的时候的位置(为了恢复混合图,需要记住打乱时的位置),而且采用标志ID号也比较简单。
交互动画是如何实现的? 大家应该都清楚我们看的影视动画都是在固定时间里通过显示静态图片实现的(比如每秒钟显示24帧)。
在我们程序的交互动画里边也可以是一帧一帧画面显示。比如鼠标每移动一次,画面刷新显示一次(根据鼠标移动情况随机发生)。可以这样来区分,于影视动画是固定时间变换帧动画,程序交互动画是随机变换帧动画。在交互动画中,很多时候我们实际只涉及图像里边的很小一块图像的变化,为了增加变换效率,减少每次变化计算机需要应对的数据量,可以把原交互图像作为背景,修改图像中变化的那一块图像,这样可提升交互操作的实时性。
3.2 界面功能设计
首先,肯定需要一个图片显示区域来显示拼图;
其次,需要一张缩略图给予用户提示完成的目标图像;
然后就是提供给用户的一些操作功能,暂时考虑功能(实现控件)有:选择图片(按钮)、混合拼图(按钮)、再来一次(按钮)、退出(按钮)、行数设置(文本框)、列数设置(文本框)、行列数选择等(下拉列表框)。
如上所述,我们可以将图形框架界面划分为以下4个区域:缩略图显示区、拼图显示区、操作功能区、信息显示区。如下:
待续~~~
用Racket做一个拼图游戏-01相关推荐
- python设计拼图游戏tkinter_tkinter做一个拼图游戏
今天我们利用canvas绘制.删除图片的的函数,以及鼠标事件的绑定来制作一个简单的九宫格拼图游戏. 首先从网上下九张图,它们是把一张图分割成了九宫图,打乱后显示在canvas画布上. 接下来我们只要实 ...
- 用python自己动手做一个小游戏01
今天我们来用python做一款属于自己的小游戏--贪吃蛇.众所周知哈,pygame入门级游戏应该是非贪吃蛇莫属了,只需要一点简单的算法就能够完美还原童年的感觉.当然了,目前网上的贪吃蛇数量众多,质量参 ...
- 用 JS 做一个数独游戏(二)
用 JS 做一个数独游戏(二) 在 上一篇博客 中,我们通过 Node 运行了我们的 JavaScript 代码,在控制台中打印出来生成好的数独终盘.为了让我们的数独游戏能有良好的体验,这篇博客将会为 ...
- python手机版做小游戏代码大全-Python大牛手把手教你做一个小游戏,萌新福利!...
原标题:Python大牛手把手教你做一个小游戏,萌新福利! 引言 最近python语言大火,除了在科学计算领域python有用武之地之外,在游戏.后台等方面,python也大放异彩,本篇博文将按照正规 ...
- scratch做简单跑酷游戏_腾讯游戏学院专家:做一个多线程游戏框架可以多简单?...
导语 如何做一个多线程游戏框架?腾讯游戏学院专家Tao将在本文通过一个demo来说说游戏逻辑的多线程化. 众所周知现在各种游戏终端的发展十分迅猛.其中一个共同的特征是"多核化",由 ...
- 做一个FLASH游戏你需要掌握的东西【实用】
做一个FLASH游戏你需要掌握的东西 作者:jianzhong 一直想着什么时间好好做一个像样点的游戏,于是刻意的开始去了解FLASHGAME的相关资料,在这里把自己在整个制作和收集过程中的一些感觉使 ...
- 单枪匹马:4年只做一个iOS游戏 收入破千万美元
2011 年,一款叫做<Tiny Wings>的手游被苹果推荐为最佳 iPhone 游戏,对手游市场有所了解的同学一定会赞同<Tiny Wings>是过去几年中全球知名度仅次于 ...
- 用 Python 做一个 H5 游戏机器人
原文地址:Creating An HTML5 Game Bot Using Python 原文作者:vesche 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- ...
- 使用PixiJS做一个小游戏
PixiJS PixiJS使用WebGL,是一个超快的HTML5 2D渲染引擎.作为一个Javascript的2D渲染器,Pixi.js的目标是提供一个快速的.轻量级而且是兼任所有设备的2D库. 官方 ...
- dx绘制2d图像_【教程】使用DX9做一个2D游戏(1)
本文最先发表在贴吧,现在整理到此处,之后所有更新将在这里进行. by Chu @ XDU 2012/11/25 版权所有,禁止用于商业用途. 转载请注明出处. 用DX9做一个2D游戏显然不是一件容易的 ...
最新文章
- CTO让我研究中台(一):阿里的“数据+业务”双中台架构
- php n维数组扁平化,js嵌套的数组扁平化:将多维数组变成一维数组以及push()与concat()区别的讲解...
- CLEARTEXT communication to xxx not permitted by network security policy
- userdel account is currently in use
- copy 扩展名 包含子文件夹 文件 到某个 文件夹
- [GAN学习系列2] GAN的起源
- jquery 的animate 的transform
- 2017-2018-1 20155338 《信息安全系统设计基础》第七周学习总结
- java发送接收组播(多播)数据包(UDP包)
- 【报错】Error inserting GREEM=30 YELLOW=4 RED=5 android.database.sqlite.SQLiteException: no such tab
- java web教室管理系统_“真香”教程,455集全套java视频教程,自己拿走去学习吧...
- 报表工具Style Report报表打印功能
- 第十一章:项目风险管理 - (11.4 实施定量风险分析)
- 2017前端开发手册三-前端职位描述
- EOFError: Ran out of input
- 国密gmssl命令行生成SM2证书
- matlab郭彦甫-听课笔记-02
- unityplayerpre存档_c# unity PlayerPrefs 游戏存档,直白点就是讲游戏数据本地保存下来...
- 2019 SUST暑期集训题解(计算几何(二))
- 2006年35大BT种子网站
热门文章
- Pearson相关系数公式的四种形式及Python代码实现
- 最新资料!工银亚洲开户见证业务受理网点(广东地区,除了深圳)
- xp桌面计算机隐藏设置密码,电脑设置开机密码详解 保护自己的隐私不受窥探-电脑设置开机密码...
- Trustzone的一些理解
- 密码库LibTomCrypt学习记录——(2.13)分组密码算法的工作模式——CCM加密认证模式
- 开关电源Buck电路CCM及DCM工作模式
- header html 高度,CSS经典基础布局,自适应高度。header,content,footer.
- 将<span>标签设为圆形
- 自动化测试方案设计和实现
- 自己制作深度学习数据集教程