怎么开发Html网页文字游戏开发框架?

借助HTML5 Canvas API制作一个简单的猜字游戏_html5教程技巧-H5教程-PHP中文网QQ群微信公众号还没有收藏借助HTML5 Canvas API制作一个简单的猜字游戏_html5教程技巧二话不说,先上效果图以及源代码~HTML代码
XML/HTML Code复制内容到剪贴板
&!doctype html&
&html lang=&en&&
&meta charset=&utf-8& /&
&script type=&text/javascript& src=&chp1_guess_the_letter.js?1.1.5&&script&
&script type=&text/javascript& src=&modernizr.custom.99886.js?1.1.5&&script&
&canvas id=&canvas_guess_the_letter& width=&500& height=&300&&
你的浏览器不支持HTML5 Canvas
&input type=&button& id=&createImageData& value=&Export Canvas Image& /&;
html&JS代码
JavaScript Code复制内容到剪贴板
* @author Rafael
window.addEventListener(&load&, eventWindowLoaded, false);
var Debugger = function() {
Debugger.log = function(message) {
console.log(message);
} catch(exception) {
function eventWindowLoaded() {
canvasApp();
function canvasSupport() {
return Modernizr.
function canvasApp() {
var guesses = 0;
var message = &Guess The Letter From a(lower) to z(higher)&;
var letters = [&a&,&b&,&c&,&d&,&e&,&f&,&g&,&h&,&i&,&j&,&k&,&l&,
&m&,&n&,&o&,&p&,&q&,&r&,&s&,&t&,&u&,&v&,&w&,&x&,&y&,&z&];
var today = new Date();
var letterToGuess = &&;
var higherOrLower = &&;
var letterGuessed = [];
var gameOver =
if(!canvasSupport()) {
var theCanvas = document.getElementById(&canvas_guess_the_letter&);
var context = theCanvas.getContext(&2d&);
initGame();
function initGame() {
var letterIndex = Math.floor(Math.random() * letters.length);
letterToGuess = letters[letterIndex];
guesses = 0;
lettersGuessed = [];
gameOver =
window.addEventListener(&keyup&, eventKeyPressed, true);
var formElement = document.getElementById(&createImageData&);
formElement.addEventListener('click', createImageDataPressed, false);
drawScreen();
function eventKeyPressed(e) {
if(!gameOver) {
var letterPressed = String.fromCharCode(e.keyCode);
letterPressed = letterPressed.toLowerCase();
guesses++;
letterGuessed.push(letterPressed);
if(letterPressed == letterToGuess) {
gameOver =
letterIndex = letters.indexOf(letterToGuess);
guessIndex = letters.indexOf(letterPressed);
if(guessIndex & 0) {
higherOrLower = &请输入正确的字符&;
} else if(guessIndex & letterIndex) {
higherOrLower = &小了&;
higherOrLower = &大了&;
drawScreen();
function drawScreen() {
context.fillStyle = &#ffffaa&;
context.fillRect(0, 0, 500, 300);
context.strokeStyle = &#000000&;
context.strokeRect(5, 5, 490, 290);
context.textBaseLine = &top&;
context.fillStyle = &#000000&;
context.font = &10px _sans&;
context.fillText(today, 150, 20);
context.fillStyle = &#FF0000&;
context.font = &14px _sans&;
context.fillText(message, 125, 40);
//猜测次数
context.fillStyle = &#109900&;
context.font = &16px _sans&;
context.fillText(&猜测次数: &+guesses, 215, 60);
//大还是小
context.fillStyle = &#000000&;
context.font = &16px _sans&;
context.fillText(&大还是小: &+higherOrLower, 150, 135);
//已经猜测的字符
context.fillStyle = &#FF0000&;
context.font = &16px _sans&;
context.fillText(&已经猜测的字符: &+letterGuessed.toString(), 10, 260);
if(gameOver) {
context.fillStyle = &#FF0000&;
context.font = &40px _sans&;
context.fillText(&你猜中了&, 150, 180);
function createImageDataPressed(e) {
window.open(theCanvas.toDataURL(), &canvasImage&,&left=0, top=0, width=&+theCanvas.width+&, height=&+theCanvas.height+&, toolbar=0, resizable=0&);
}从游戏名称可以看出,该游戏是猜字游戏。每局系统都会自动生成一个字母,玩家会按键盘来猜测该字母是哪一个。例如生成的是s,玩家按了h,则游戏就会提示《小了》,因为英文字母当中h的索引比s的索引更靠前。案例当中涉及的变量。guesses:猜测次数message:文字提示,指导用户如何玩该游戏letters:文字数组,存放我们要猜测的文字的集合。这个例子用的是a到ztoday:今天的日期letterToGuess:要猜测的文字higherOrLower:是《大了》还是《小了》letterGuessed:已经猜测过得文字gameOver:游戏是否结束,是布尔变量,开始的时候是false,猜对后设为true变量的声明var guesses = 0;
var message = &Guess The Letter From a(lower) to z(higher)&;
var letters = [&a&,&b&,&c&,&d&,&e&,&f&,&g&,&h&,&i&,&j&,&k&,&l&,
&m&,&n&,&o&,&p&,&q&,&r&,&s&,&t&,&u&,&v&,&w&,&x&,&y&,&z&];
var today = new Date();
var letterToGuess = &&;
var higherOrLower = &&;
var letterGuessed = [];
var gameOver =初始化游戏function initGame() {
var letterIndex = Math.floor(Math.random() * letters.length);
letterToGuess = letters[letterIndex];
guesses = 0;
lettersGuessed = [];
gameOver =
window.addEventListener(&keyup&, eventKeyPressed, true);
var formElement = document.getElementById(&createImageData&);
formElement.addEventListener('click', createImageDataPressed, false);
drawScreen();
通过使用Math的random()函数和floor()函数,根据文字的数组生成要猜测的文字。并且当用户按键盘的时候监听《keyup》事件,根据传递过来的event,生成按下的键值。因猜测游戏对大小写不敏感,为防止用户按大写字母,我们需要把值转换成小写形式。猜测次数+1猜测出来的文字添加到已经猜测的文字数组当中var letterPressed = String.fromCharCode(e.keyCode);
letterPressed = letterPressed.toLowerCase();
guesses++;
letterGuessed.push(letterPressed);剩下的就只有判断 大和小了。通过indexOf函数 我们可以判断要猜测的文字和我们输入的文字在字符集上面的索引值。如果我们输入的更靠前则提示《小了》反之《大了》最终用户猜对了要猜测的文字 我们会在中央用大号字体显示《你猜对了》letterIndex = letters.indexOf(letterToGuess);
guessIndex = letters.indexOf(letterPressed);
if(guessIndex & 0) {
higherOrLower = &请输入正确的字符&;
} else if(guessIndex & letterIndex) {
higherOrLower = &小了&;
higherOrLower = &大了&;
} 至此这个功能差不多完成了吧,我们还有一个小功能,那就是通过按下按钮的方式可以把屏幕结果抓去出来。用的函数为toDataUrl(),有兴趣的朋友研究一下。 以上就是借助HTML5 Canvas API制作一个简单的猜字游戏_html5教程技巧的内容,更多相关内容请关注PHP中文网(www.php.cn)!共3篇0点赞收藏分享:.php.cn&猜你喜欢PHP中文网:独家原创,永久免费的在线,php技术学习阵地!
All Rights Reserved | 皖B2-QQ群:关注微信公众号用HTML5+WebGL打造网页版3D游戏《刺客信条》
[问题点数:50分]
用HTML5+WebGL打造网页版3D游戏《刺客信条》
[问题点数:50分]
只显示楼主
取消只显示楼主
匿名用户不能发表回复!|HTML5游戏如何挣钱?2条经验让你每款赚3万刀
[摘要]当前,开放网络正在从Flash独占桌面环境朝跨平台HTML5技术所转变。与众多的原生应用开发商以及应用程序相比,当前只有几百个游戏工作室和小规模社区独立组织在分享HTML5游戏开发的美味蛋糕。腾讯游戏 9月5日 作者:杨亮 编辑:白豆原文作者:Alexander Krug,是世界上最大的HTML5游戏平台的运营商SOFTGAMES的CEO。现今苹果App Store当中的应用数量可以以海量来形容,最新发布的应用对排行榜的冲击力也越来越小,很明显,其已成为一个饱和市场。一款游戏要想在App Store中冲到美国“免费游戏榜”首位需要日下载超过五万次。不奇怪,有超过99%的应用的日下载都达不到这个要求。如果能达到这个下载量,一般都是病毒传播和运气的产物。不幸的是,这种事情可遇而不可求。开发商可以通过一些方法来增加日常安装量:用市场手段为每个安装量而付费。然而,现实是当你为每个安装增加成本时,其ARPU(每用户平均收入)会下降或者不变,而且收购成本与ARPU之间的差距还会逐月增大。要想管控这种风险,开发商需要有一支非常有经验的营销团队以及大量的资金。但当前的独立开发者在大多数情况下,每个应用程序的月收入连500美元(约3000元人民币)都不到。当前,开放网络正在从Flash独占桌面环境朝着一个开放、处于上升空间的跨平台HTML5技术所转变。与几十万的原生应用开发商以及数以百万计的应用程序相比,当前只有几百个游戏工作室和小规模社区独立组织在分享HTML5游戏开发的美味蛋糕。以下为原文翻译:详细来说,HTML5游戏市场与原生App Store商业模式相比有着若干差异:与App Store发行商正在为满足玩家对高质量HTML5游戏的需求,而积极找寻和接洽开发商不同的是,像Softgames这个世界上最大的HTML5平台,对休闲游戏有强烈的需求。Softgames平均每个工作日都会发布一款新的跨平台游戏,相比于App Store这种拥有几十万应用的平台,Softgames对开发商开展业务而言实在是一块“风水宝地”。(利益相关:原文作者Alexander Krug是Softgames的创始人,Softgames是一家总部位于德国的HTML5游戏平台。)以休闲游戏为主导的平台能够给开发商带来巨大的收益,开发商只需马上行动,提交简单和精心打造的项目,并不断扩充即可。无需投入大量资源,无需长期投入,HTML5技术可以在一两个月内就设计出一款优秀的游戏。游戏可出售给像Softgames这样的发行商,独家/非独家授权皆可。独家授权的话,开发商最高可获得多达三万美元的收益。这份收益比大多数独立发行的应用在整个应用生命周期内所产生的收益都要大。与存在着大量山寨应用,大量原生应用开发商的App Store相比,HTML5游戏市场提供了巨大的市场机遇。Softgames上有超过250款流行大作,并对例如麻将、纸牌或者祖玛类型的游戏有强烈的需求。开发者可快速行动以填补这方面的空白并从中受益,而这些机遇在App Store当中根本不存在。当前HTML5游戏的主要收入来自应用内广告。而由于低支付聚合支出和一个全球性的支付构架的缺失,“免费加增值”的模式是不存在的。然而,其对于能一次快速开发一款游戏的开发者来说,这一点并不是劣势。开发者可以将游戏出售给开发者,并将精力转移到更佳的作品上面去。这种做法可以让开发者在游戏发布之后,无需冒风险再分配大量资源去做优化,维护和升级游戏。在开发者投身于HTML5跨平台游戏开发之前,有几件事情需要注意:1、对初学者而言,要想开发一款能在所有平台都正常运行的HTML5游戏无疑是一项挑战。因此,测试、优化和学习是实现“一套代码,多个设备”的关键。下一步对初学者而言可能更加的困难,那就是要在海量的HTML5支持设备上测试你的游戏。例如,不同操作系统,甚至不同的版本运行情况各不相同,你还得进行新功能的性能调试。聚焦于一点,一个一个项目的推进是避免遇到太大困难的正确方法。2、游戏需要兼容各种不同的控制方式,你的用户可能通过鼠标、键盘、智能电视遥控器或者他们的iPhone来玩游戏。此外,你的游戏在不同屏幕分辨率下可能会有巨大的差异。在一些分辨率下,有些游戏的显示可能会出问题。你需要进行智能的规划,以避免这些潜在的问题,因为其会使你的游戏遭受失败。3、通常情况下,HTML5游戏的音频的滞后是导致浏览器(尤其是移动浏览器)载入时间过长、游戏卡顿,浏览器崩溃的最直接原因。幸运的是,当前已有一些重大的改进,将基本音频支持内置到HTML5游戏内。然而对于原生游戏而言,这个功能还不完善。因此开发者应该使用基本声音库而不是扩展音频,以避开陷阱。开发者如何从HTML5中受益今天对开发者而言有两种商业模式:1、开发者将游戏通过独家或者非独家的方式卖给诸如Softgames这样的发行商;2、从应用内置广告产生的收益中与发行商进行分成。非独家授权方式的话,开发者可以将游戏多次出售给不同发行商,Softgames购买非独家授权游戏的价格通常在500-5000美元(约万元人民币)之间。可以预见的是,开发者通过一款高质量HTML5游戏在几周内可以产生上万美元(六万人民币)的收益。HTML5应该被视为原生开发的一种巨大的替代品。与其把冀期望成功给运气,开发者可以有效安排时间和精力给下一款游戏,并通过发行商网站对高质量HTML5休闲游戏的巨大需求而获得收入。Softgames作为HTML5游戏的先锋,已经有超过十年的移动发行方面的经验,并完全专注HTML5游戏平台已有三年之久。开发者应该早日加入HTML5游戏开发的淘金热行列中来,以免为时已晚。
正文已结束,您可以按alt+4进行评论
相关阅读:
相关搜索:
[责任编辑:aniszhou]
热门搜索:
Copyright & 1998 - 2018 Tencent. All Rights Reserved在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
标签:至少1个,最多5个
先上效果图
开始之前的准备
js/ 里面创建game.js
images/ 里面放三张图片,一张背景图片(background.png),一张英雄图片(hero.png),一张怪物的图片(monster.png)
在game.html里面写上以下几行简单的HTML代码:
&!DOCTYPE html&
&html lang="en"&
&meta charset="utf-8"&
&title&Simple Canvas Game&/title&
&script src="js/game.js"&&/script&
我们在game.html引入了game.js文件,没错,剩下的所有工作都是在操作game.js,为其添加游戏的js代码。
在game.js 里面,我们首先需要为游戏的舞台创建一张画布(canvas):
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);
这里通过js来创建了一个元素并设置canvas的宽和高,最后将其添加到&body&标签后。var ctx = canvas.getContext("2d");中的ctx变量是我们后面会用到的,具体的canvas用法查看这里的链接:
游戏需要加载我们之前存放在images文件夹下面的三张图片:
// Background image
var bgReady =
var bgImage = new Image();
bgImage.onload = function () {
bgImage.src = "images/background.png";
// Hero image
var heroReady =
var heroImage = new Image();
heroImage.onload = function () {
heroReady =
heroImage.src = "images/hero.png";
// Monster image
var monsterReady =
var monsterImage = new Image();
monsterImage.onload = function () {
monsterReady =
monsterImage.src = "images/monster.png";
以上三张图片都是通过创建简单的图片对象来实现加载的,类似bgReady的三个变量用来标识图片是否已经加载完成,如果如果在图片加载未完成情况下进行绘制是会报错的。如果你不太确定new Image()到底是个什么东西,你可以在bgImage.src = "images/background.png";之后使用console.log(bgImage);来查看,你看到的将是类似:
&img src="images/background.png" &
我们需要定义一些对象,以便我们在后面会用到:
var hero = {
speed: 256 // movement in pixels per second
var monster = {};
var monstersCaught = 0;
既然是英雄抓获怪物,我们得要有一个英雄和怪物的对象。而英雄有一个speed属性用来控制他每秒移动多少像素。怪物游戏过程中不会移动,所以暂时不用设置属性。monstersCaught则用来存储怪物被捉住的次数,初始值当然为0了。
处理用户的输入
游戏是给人玩的,那么我们怎么知道用户到底在这个过程中干了什么?按了键盘?点了鼠标?这些都是用户在玩游戏的时候的输入,所以我们一旦捕获到这些输入,我们就可以根据游戏的逻辑对用户的输入进行处理了:
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function (e) {
keysDown[e.keyCode] =
}, false);
addEventListener("keyup", function (e) {
delete keysDown[e.keyCode];
}, false);
这里我们只是监听两个用户的输入:
然后我们将用户的输入先保存起来,并没有立即响应。为此,我们用keysDown这个对象来保存用户按下的键值(keyCode),如果按下的键值在这个对象里,那么我们就做相应处理。
在前端开发中,一般是用户触发了点击事件然后才去执行动画或发起异步请求之类的
开始一轮游戏
游戏在结束的时候,我们需要开始新的一轮游戏,所以在game.js添加reset函数
// Reset the game when the player catches a monster
var reset = function () {
hero.x = canvas.width / 2;
hero.y = canvas.height / 2;
// Throw the monster somewhere on the screen randomly
monster.x = 32 + (Math.random() * (canvas.width - 64));
monster.y = 32 + (Math.random() * (canvas.height - 64));
reset()函数用于开始新一轮和游戏,在这个方法里我们将英雄放回画布中心同时将怪物放到一个随机的地方。
在游戏的过程中,不管是用户在玩(有正确输入的状态)还是游戏结束,我们都是需要及时更新游戏的对象:
var update = function (modifier) {
if (38 in keysDown) { // Player holding up
hero.y -= hero.speed *
if (40 in keysDown) { // Player holding down
hero.y += hero.speed *
if (37 in keysDown) { // Player holding left
hero.x -= hero.speed *
if (39 in keysDown) { // Player holding right
hero.x += hero.speed *
// Are they touching?
hero.x &= (monster.x + 32)
&& monster.x &= (hero.x + 32)
&& hero.y &= (monster.y + 32)
&& monster.y &= (hero.y + 32)
++monstersC
update函数负责更新游戏的各个对象,会被规律地重复调用。首先它负责检查用户当前按住的是中方向键,然后将英雄往相应方向移动。
有点费脑力的或许是这个传入的modifier 变量。你可以后面将要实现的main 方法里看到它的来源,但这里还是有必要详细解释一下。它是基于1开始且随时间变化的一个因子。例如1秒过去了,它的值就是1,英雄的速度将会乘以1,也就是每秒移动256像素;如果半秒钟则它的值为0.5,英雄的速度就乘以0.5也就是说这半秒内英雄以正常速度一半的速度移动。理论上说因为这个update函数被调用的非常快且频繁,所以modifier的值会很小,但有了这一因子后,不管我们的代码跑得快慢,都能够保证英雄的移动速度是恒定的。
这里需要说明一下下面的判断怪物和英雄是什么根据:
hero.x &= (monster.x + 31)
&& monster.x &= (hero.x + 31)
&& hero.y &= (monster.y + 32)
&& monster.y &= (hero.y + 32)
上面的31,32是由hero和monster图片的大小决定的,我们的hero图片是32x32,monster图片是30x32,所以根据坐标的位于图片中心的法制,就可以得到上面的判断条件。
现在英雄的移动已经是基于用户的输入(按下上,下,左,右键)了,接下来该检查移动过程中所触发的事件了,也就是英雄与怪物相遇。这就是本游戏的胜利点,monstersCaught +1然后重新开始新一轮。
之前写的代码都是在准备前期工作和处理一些游戏的状态等,下面将进入正题:我们需要将所有的东西画出来
// Draw everything
var render = function () {
if (bgReady) {
ctx.drawImage(bgImage, 0, 0);
if (heroReady) {
ctx.drawImage(heroImage, hero.x, hero.y);
if (monsterReady) {
ctx.drawImage(monsterImage, monster.x, monster.y);
ctx.fillStyle = "rgb(250, 250, 250)";
ctx.font = "24px Helvetica";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText("Goblins caught: " + monstersCaught, 32, 32);
这里的ctx就是最前面我们创建的变量。然后利用canvas的drawImage()首先当然是把背景图画出来。然后如法炮制将英雄和怪物也画出来。这个过程中的顺序是有讲究的,因为后画的物体会覆盖之前的物体。
这之后我们改变了一下Canvas的绘图上下文的样式并调用fillText来绘制文字,也就是记分板那一部分。本游戏没有其他复杂的动画效果和打斗场面,绘制部分大功告成
主循环函数
我们实现了将画面画出来以后,我们紧接着需要实现的就是游戏的循环结构,于是将它放在main函数里:
// The main game loop
var main = function () {
var now = Date.now();
var delta = now -
//console.log(delta);
update(delta / 1000);
// Request to do this again ASAP
requestAnimationFrame(main);
上面的主函数控制了整个游戏的流程。先是拿到当前的时间用来计算时间差(距离上次主函数被调用时过了多少毫秒)。得到modifier后除以1000(也就是1秒中的毫秒数)再传入update函数。最后调用render 函数并且将本次的时间保存下来。
设置requestAnimationFrame()
在上面的main函数中,我们通过requestAnimationFrame()调用了main函数,所以我们需要声明:
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationF
这里这么多的||,不为别的,就是考虑到浏览器兼容问题而已。
最后启动游戏
万事具备,只欠东风。到此,所有的游戏代码基本就写完了,我们现在需要做的就是调用相应的函数来启动游戏:
// Let's play this game!
var then = Date.now();
到这里代码就写完了。先是设置一个初始的时间变量then用于首先运行main函数使用。然后调用 reset 函数来开始新一轮游戏(如果你还记得的话,这个函数的作用是将英雄放到画面中间同时将怪物放到随机的地方以方便英雄去捉它)
用浏览器打开game.html,开始玩游戏吧!
进一步思考
在玩游戏的过程中,你会发现每一次hero捕获到monster,hero就回到了canvas画布的正中间。那么现在需要做的就是,将hero在捕捉到monster的时候让hero就停留在捕获的位置,不再是回到canvas正中间。
这个现象的出现主要是因为在reset函数中将hero.x和hero.y写死了,所以一个最简单的方法就是在reset中传入参数:
var reset = function (x,y) {
然后在update调用reset的时候传入捕获时位置的参数:
var update = function (modifier) {
//...other codes
++monstersC
reset(heor.x,hero.y);
最后在开始游戏的时候将hero放在canvas最中间即可:
var then = Date.now();
reset(canvas.width / 2,canvas.height / 2);
大功告成!
Hapyy Hacking
16 收藏&&|&&81
你可能感兴趣的文章
175 收藏,5.2k
11 收藏,3.5k
174 收藏,2.2k
本作品 保留所有权利 。未获得许可人许可前,不允许他人复制、发行、展览和表演作品。不允许他人基于该作品创作演绎作品
哈哈哈,谢谢
哈哈哈,谢谢
楼主补一下图片吧,最好弄个gif的有个效果看看,这样才吸引人嘛
楼主补一下图片吧,最好弄个gif的有个效果看看,这样才吸引人嘛
最开头那张图不是么?
最开头那张图不是么?
图片显示不出来了好不好!我这里看不到
图片显示不出来了好不好!我这里看不到
额。第一张就是gif图。
额。第一张就是gif图。
分享到微博?
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。cocos2d-x之道~制作第一款文字游戏(一)
回想去年,也是在三、四月时开发出自己的第一款游戏,正是这款游戏,令我决定踏上独立开发者之路。一年过去了,第一款游戏达到它应有的盈利水平。然而这款游戏开发后的时间里,都没再取得另一款令自己满意的作品。直到今年的三、四月,我使用cocos2d-x开发出我的第一款文字游戏。
第一款游戏的传送门
第一款文字游戏的传送门
自从使用cocos2d-x后,发现自己爱上了这个引擎。它或许还不够强大和完善,但是使用它,可以体验编码的乐趣,还可以为我重拾C++这门技术(到底对C++有多么的执着啊),还能增进NDK和JNI的学习。恰恰满足我各种各样的追求。
这个第一款文字游戏,名字我取作Anagram Puzzle,其实这款游戏是参照RayWenderlich上的这篇教程来改写的,教程里使用的是iOS的UIKit编写,虽说原理相通,但是在改写过程中还是遇到不少折腾的地方。由于初次编写cocos2d-x游戏,所以错误难免百出,希望者们高抬贵手,点到即止……废话不多说,马上开始coco2d-x之道~如何制作第一款文字游戏!
Anagram简介
Anagram是一种把单词或短语的字母顺序打乱,重新排列后变成一个新单词或短语的游戏。例如,单词cinema可以重新排列成iceman。游戏中就要求玩家进行你所提供单词或短语的重新排列。完成游戏的画面会如图所示:
在开发这个游戏过程中,会接触到以下这些知识:vcD4KPHA+PC9wPgoKTVZD0M21xNPOz7e94bm5yOe6zrTTzsS8/sXk1sO809TYvLax8LzT1Ni12sj9t73X1szlvPK1pcq508PS9MDW0vTQp7fWwOtIVUSy49Pr087Pt7LjytbKxs3Ptq+8sLavu61QYXJ0aWNsZbXE0Ke5+wq7udPQxuTL+7XE0rvQqWNvY29zMmQteLXEu/m0odaqyrajrLa8u+HU2r+qt6K5/bPM1tC907Sltb2howo8YnI+Cgo8c3Ryb25nPrP1yry7r7mks8w8L3N0cm9uZz4KPHA+PC9wPgo8cD7K18/I1+7W2NKqtcS1sci7ysfKudPDw/zB7tDQwLS0tL2oY29jb3MyZC14uaSzzKOstbHIu9Ky09DG5Mv7t723qNKyv8nS1LS0vai5pLPMo6y1q8rHztLIz86q1cbO1cP8we7Q0MC0tLS9qMrHsdjQ67XEu/mxvrmmoaO0tL2ot723qL/J0tTU2tXiwO/V0rW9oaO0tL2ozeqzybrzuPe49sa9zKi1xLmks8zOxLz+vNC2vNPQwcuho87Sw8e1xNb30qq5pLPMzsS8/rzQysdwcm9qLmFuZHJvaWS6zXByb2ouaW9zwb249qGj1fu49r+qt6K5/bPMo6zO0sq508NNYWMgT1PAtL+qt6KjrMv50tSx4MLrysfU2lhDb2Rlyc+9+NDQo6y2+EFuZHJvaWS5pLPMtcSx4NLr1PLKudPDw/zB7tDQo6zP6s+4vcyzzL/J0tSyzr+81eLA76GjIDwvcD4KPHA+vajBorrDuaSzzLrzo6zPyLDRy/nQ6LXE18rUtM7EvP6/vbG0tb1SZXNvdXJjZc7EvP680NbQoaO08r+qWGNvZGW5pLPMo6zEv8ewUmVzb3VyY2XOxLz+vNDPwru5ysfUrcC0tcTXytS0zsS8/qOszai5/dPSu/dSZXNvdXJjZc7EvP680CAtPiBBZGQgRmlsZXMgdG8gLi4uo6yw0dfK1LTOxLz+try807W9uaSzzMDvoaOx4LytuvO5pLPMu+HI5828PC9wPgo8cD48aW1nIHNyYz0="/uploadfile/Collfiles/4.png" alt="\">
1)加载级别配置文件
打开level1.plist,可以看到里面内容
有三个最顶端的key,分别是:
pointsPerTile: 每个单词填对后获得的分数。
timeToSolve: 解决这一关的时间(秒)。
anagrams: 是题目的列表,包含两个item,分别是原始的短语以及最后要拼出的短语。
level文件的介绍就到此为止,下面开始编写Level类,在Level.h中添加以下内容
class Level:public CCObject{
static Level * levelWithNum(int levelNum);
int mPointPerT
int mTimeToS
CCArray * pA
其中,三个变量对应level文件里的三个最顶端的item。还有一个初始化函数,是给外部调用初始化level文件。
现在,打开Level.cpp,实现levelWithNum函数
Level * Level::levelWithNum(int levelNum){
char fileName[50];
char fullPath[150];
sprintf(fileName,"level%d.plist",levelNum);
CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile(fileName,fullPath);
CCDictionary * pListDict = CCDictionary::createWithContentsOfFile(fileName);
if(pListDict == NULL){
CCLog("level config not found");
Level * l = new Level();
CCString * tempS
tempStr = dynamic_cast(pListDict->objectForKey("pointsPerTile"));
l->mPointPerTile = tempStr->intValue();
tempStr = dynamic_cast(pListDict->objectForKey("timeToSolve"));
l->mTimeToSovle = tempStr->intValue();
l->pAnagrams = dynamic_cast(pListDict->objectForKey("anagrams"));
l->pAnagrams->retain();
这里首先用CCDictionary读出level文件中数值,然后就是读取出对应key里的值,并存储起来。
现在,打开主界面文件,默认是HelloWorldScene类,但是我改写成MainScene,其中MainScene.h是这样的
class MainScene : public cocos2d::CCLayer
~MainScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::CCScene* scene();
// implement the "static node()" method manually
CREATE_FUNC(MainScene);
Level * pL
可见,增加了Level变量。在MainScene.cpp中的init函数,编写
pLevel = Level::levelWithNum(1);
当然,这里可以通过CCLog来打印出pLevel里的内容来看看,会得到如图所示
在MainScene里添加个新的函数
void dealRandomAnagram();
具体实现要这样
void MainScene::dealRandomAnagram(){
Common::random(0, pLevel->pAnagrams->count() - 1);
int randomIndex =
Common::random(0, pLevel->pAnagrams->count() - 1);
CCAssert((randomIndex >= 0 && randomIndex pAnagrams->count()),"error random index!");
CCArray * anagram = (CCArray*)pLevel->pAnagrams->objectAtIndex(randomIndex);
CCString * ana1 = (CCString*)anagram->objectAtIndex(0);
CCString * ana2 = (CCString*)anagram->objectAtIndex(1);
int ana1len = ana1->length();
int ana2len = ana2->length();
Common::random是我自己编写的,生成两个数值之间的随机数
int Common::random(int s,int e){
float i = CCRANDOM_0_1()*(e-s+1)+s;
return (int)i;
}这样就把初始状态的短语和最终状态的短语获取到了,把dealRandomAnagram函数添加到MainScene的init函数里,
pLevel = Level::levelWithNum(1);
dealRandomAnagram();
2)创建单词的View
在工程中新增一个继承于CCNode的类,名字叫做TileView,在TileView.h中添加以下代码
static TileView * initWithLetter(const char * l,float sideLen);
CCSprite * pS
其中initWithLetter是初始化函数,pSprite是显示的精灵,mLetter是对应的字母,mIsMatch表示结果是否已经配对上(就是找到字母所应该在的位置)。
在TileView.cpp里,添加以下代码
#include "TileView.h"
TileView * TileView::initWithLetter(const char * l, float sideLen){
TileView * tile = new TileView();
CCSprite * bg = CCSprite::create("tile.png");
tile->addChild(bg);
tile->pSprite =
float scale = sideLen / bg->getContentSize().
bg->setScale(scale);
char chLetter[2];
sprintf(chLetter,"%c",l[0] - 32);
CCLabelTTF * letter = CCLabelTTF::create(chLetter,"Arial",75 * scale);
letter->setColor(ccWHITE);
tile->addChild(letter);
tile->mIsMatch =
tile->mLetter = chLetter[0];
函数中,首先的是创建一个以tile.png为图案的精灵,然后创建图案上的字母
接下来就要在界面中显示出来了,在MainScene中添加
Level * pL
CCArray * pT
CCArray * pT
pTiles是TileView的数组,pTargets是TargetView的数组,其中TileView是放在底部给出的短语的各个单词,TargetView是目标短语的各个单词。在MainScene.cpp的dealRandomAnagram函数中继续添加代码
int ana1len = ana1->length();
int ana2len = ana2->length();
float tileSide = ceilf( Common::getCameraWith()*0.9 / (float)std::max(ana1len, ana2len) ) - kTileM
float xOffset = (Common::getCameraWith() - std::max(ana1len,ana2len) * (tileSide + kTileMargin)) / 2;
xOffset += tileSide/2;
此时,开始计算各个TileView的位置。首先,比较得出原始短语和目标短语中长度最长的,然后算出各个View所需的宽度tileSide,以及各个View之间的间隔xOffset
对了,不要忘了定义全局的空隙
#define kTileMargin 20
接着,就要创建我们的TileView了
pTiles = CCArray::createWithCapacity(ana1len);
const char * ana1Letter = ana1->getCString();
for(int i = 0;i setPosition(ccp(xOffset + i * (tileSide + kTileMargin),Common::getCameraHeight() / 4));
this->addChild(tile);
pTiles->addObject(tile);
pTiles->retain();
创建方法比较简单,但是要注意的是,原始短语中可以会有空字符,空字符的地方需要留空。如图所示
3)单词View优化
方方正正的TileView看着有些拘谨,下面进行一些优化来让它们生动一些。在TileView中添加randomize函数
void TileView::randomize(){
float rotation = Common::random(0,50) /(float)100 - 0.2;
this->setRotation(rotation * 10);
int yOffset = Common::random(0,10);
this->setPositionY(this->getPositionY() + yOffset);
让TileView稍作旋转和偏移,然后在MainScene的dealRandomAnagram函数中的 this->addChild(tile); 语句后添加下面语句
tile->randomize();4)添加TargetView有了原始短语,下面就要开始创建目标短语的View了。对比TileView,TargetView要相对简单一些。因为它是固定位置及不需要显示字母。TargetView.h中添加以下代码:class TargetView : public CCNode
TargetView(void);
~TargetView(void);
static TargetView * initWithLetter(const char * l,float sideLen);
CCSprite * pS
与TileView相类似的,一个初始化函数,三个私有变量。与TileView的是一一对应。
TargetView * TargetView::initWithLetter(const char * l, float sideLen){
TargetView * tile = new TargetView();
CCSprite * bg = CCSprite::create("slot.png");
tile->addChild(bg);
tile->pSprite =
float scale = sideLen / bg->getContentSize().
bg->setScale(scale);
char chLetter[2];
sprintf(chLetter,"%c",l[0] - 32);
CCLabelTTF * letter = CCLabelTTF::create(chLetter,"Arial",78 * scale);
letter->setColor(ccWHITE);
tile->addChild(letter);*/
tile->mIsMatch =
tile->mLetter = chLetter[0];
TargetView的initWithLetter函数中,注释的语句是为显示一下结果,但是在实际游戏中是不显示TargetView上的字母。
接下来,就要把TargetView显示到场景上了,找到MainScene的dealRandomAnagram方法,在末尾处添加上以下代码
pTargets = CCArray::createWithCapacity(ana2len);
const char * ana2Letter = ana2->getCString();
for(int i = 0;i setPosition(ccp(xOffset + i * (tileSide + kTileMargin),Common::getCameraHeight() / 4 * 3));
this->addChild(target);
pTargets->addObject(target);
pTargets->retain();
是否可看到TargetView也出来,这里,我们就完成了AnagramPuzzle的第一部分开发工作,最后上个截图
感觉还不错吧,轻松的把所需要的游戏界面展示出来。这次接触到cocos2d-x知识还是比较少,主要是怎样往主场景中添加内容,怎样创建精灵。下一次,我们就要编写一些有点挑战性的东西了,比如怎么拖动精灵,怎么判断是否摆在正确的位置,怎么进行倒计时等等,真正的Code乐趣快要上场!请听下回分解。

我要回帖

更多关于 文字游戏快速开发 的文章

 

随机推荐