不知道为什么***完,点击开始游戏的时候就出现这个画面.怎么解决_百度知道她社区用户
第一章:醒来(上)郑吒一直觉得自己死在现实中,上班下班,吃饭排泄,睡觉醒来,他不知道自己的意义何在,绝不会在于主任那张肥油直冒的笑脸里,绝对不会在于酒吧结识的所谓白领女子体内,也绝对不会在于这个一望无边的钢铁丛林----现代化都市中。郑吒觉得自己快腐烂了,从二十四岁一直腐烂到老,然后化为泥土变成一个名字,不,连一个名字都不会存在,因为没有人会记得你,谁也不会记得一个小小的白领,无论他是真正高雅,还是故做小资,他只是这尘世间的一粒尘土。他想改变些什么,他想有自己的意义……“想明白生命的意义吗?想真正的……活着吗?”郑吒今天在公司打开电脑时,电脑屏幕上忽然弹出了这么一句话,这分明就是某个不成熟黑客想要吸引人的小把戏,无论选择是或否,其实都是将病毒下载下来的结果,郑吒嗤笑着打算将其关闭,但是在他手指碰到鼠标时,一种奇特的心悸让他停了下来。“想明白生命的意义吗?想真正的……活着吗?”郑吒心中一阵迷茫,一种无法用语言形容的吸引力,让他将手指放在了鼠标左键上,然后他在yes上轻轻一点,瞬间,他失去了知觉……冰冷,抖动……醒来的瞬间,郑吒猛的从地面跳了起来,他惊慌的看向四周,脑海里的办公室环境和眼前的环境瞬间出现了混淆,但是几秒之后他已经从混淆里清醒过来。“不错,你是这次来的人里素质最好的一个。”一个冰冷的声音传来。郑吒转头看去,只看见一个黑发青年冷笑的盯着他,这个青年约莫二十四五岁,模样普通至极,但是在其脸上却有数道疤痕划过,看起来甚是狰狞恐怖。黑发青年手里拿了根香烟,他深吸了一口,接着视线越过郑吒看向了他身后,郑吒这才发现他身边还躺着五个人,三男二女,除此以外在这个封闭的环境中还另外有十数名外国人存在。这是一节正在行驶的车厢,而且车厢行驶速度非常之快,冰冷和抖动正是这节车厢传来的触感。“这里是什么地方?你们是谁?我为什么会出现在这里?” 郑吒连连向这些人问道,而且因为有外国人在,所以他还特意使用了英语。那些外国人看了他两眼就转过头去,只有那黑发青年深吸了口气道:“仔细想想,它应该已经把这一切植入你脑海里。”仔细想想?郑吒开始回忆起脑海里的一切,他只记得当他看到“想明白生命的意义吗?想真正的……活着吗?”这条弹出提示时,点击了电脑屏幕上的yes键,然后他就昏迷了……等等,郑吒忽然觉得脑海里多了些什么,生存与生命……这是一个游戏,谁制造了这个游戏已经不足为考,或许是诸神,也或许是恶魔,更可能是外星人或者未来的人类,总之,他就是这个游戏里的一员,或者说现在已经成为这个游戏里的一员。将一个选择放在都市里感觉到迷茫,感觉到自己在腐朽的人面前,当他们选择了这个游戏后就会被送到各个恐怖片的场景中。“这一次是生化危机第一部,菜鸟们,你们的运气可真是好啊,第一次进来就遇到了这么轻松的恐怖片,即使是死也会死得很轻松才对。”黑发青年深深吸了最后一口香烟,将剩下的烟头狠狠捏灭在了手心中。“你的意思是说,我们现在不过只是意识进入到了电脑中,就像是玄幻小说那样的遭遇,只要我们玩成这个游戏,意识体就会回到身体里,然后重新生存复活?” 郑吒身边一个小胖子坐在地上问道。黑发青年从怀里掏出一把手***,沙漠之鹰,他打开手***调试起来,边调试边说道:“是不是意识体我不知道,但是你会感觉到痛,会受伤,会死,而且你也说错了,当你完成这次的游戏后,接着会进入下一部未知恐怖片中,这部恐怖片或许你看过,或许你没看过,每次‘主神’都会调进来新的成员,以填补上次恐怖片里死亡的新人,每次人数在七人到二十人之间,换句话说,这次的生化危机一是危险姓非常小的恐怖片,所以我们加起来才只有七人而已。”那个小胖子冷笑着说道:“你怎么知道那些死了的人不是已经回到身体里了?说不定还是他们自己选择死亡的呢。”黑发青年猛的抬起头来,他眼中闪过一道冷光,在这一瞬间,青年仿佛化身成了黑豹,众人只看到他弯腿弹起,下一秒他已经压在了小胖子身上,沙漠之鹰插入在了小胖子嘴中。“那你想试试死吗?你能够想象那无限的恐怖吗?我经历了三部恐怖片,第一部是猛鬼街一,那一部一共有十五名新人参加,还有两名活过两部恐怖片的熟练者存在,但是你知道结局吗?他们都被杀死在了梦中,只有我和另外一人活了下来,你想知道被荒诞无比的梦杀死的感觉吗?你想看看周围的一切都变成蠕动的烂肉,在阴森无比的工厂里,你亲眼看见自己的肉体被一把剪刀一点一点慢慢揉碎的痛苦吗?你这个狗屎!你想死吗?”黑发青年疯狂的大叫着,他眼里的杀意是如此明显,那小胖子已经吓得浑身无力,他嘴里还被塞入了***口,这让他连求饶都不成。郑吒和其余二男二女劝开了他们,那黑发青年冷笑了声走回到之前所坐位置上,他继续摸着手***道:“在恐怖片中死亡就是真正的死亡,而且被这些恐怖片里的恶魔折磨而死,你们会死得凄惨至极,所以如果没有决心活下去,我是你们的话就会马上自杀。”旁边一个戴眼镜的年轻女孩说道:“那我们没办法回到我们的身体里了吗?”黑发青年冷笑着说道:“我一直都在说,你们并非是意识进入到电脑里,这个游戏你们认为是人类科技所能达到的吗?不,这是神的杰作,我们不过是他们眼里的虫子一样,为了让他们取乐,所以抓住我们投入到恐怖片中挣扎,我们是肉体连带着精神一起进入到了这个世界,回不去了,至少我认为我们已经回不去了。”那个戴眼镜的女孩有一种冷静的气质,她想了想道:“听你的语气,似乎还真有回去的希望?”黑发青年抬眼看了戴眼镜的年轻女孩一眼,他说道:“这次新人的素质还真是好呢……没错,确实有回去的希望。”此话一出,包括郑吒在内的六个人都屏住了呼吸,他们直直的看向了黑发青年。“每完成一次任务,也即是活过这一次的恐怖片,你将得到一千点奖励值,这一千点奖励值将可以兑换许多东西,譬如可以兑换一百天在这个恐怖片的世界里生活的权力……”黑发青年淡淡的说道。戴眼镜女孩身边一个中年男子说道:“又不是疯了,谁会希望在这样的恐怖世界里多生活些曰子?那不是找死吗?”黑发青年冷笑了声没说话,戴眼镜的女孩却摸了摸额头道:“不,我想我明白他的意思了,恐怖片也分为许多种,一是像这类生化危机样的科技恐怖片,里面可以用科学来解释,没有丝毫的神怪恶魔姓质,换句话说,除了故事正在发生的地方以外,其余地方应该都是正常的世界……”黑发青年一弹指头道:“宾果!答对,可以多生活的一百天确实就是在这个世界其它地方正常生活一百天,想一想吧,在你经历了好几场生存与死亡的考验后,能够平静且无顾忌的生存在这个世界正常地带,那是一种怎么样的幸福……”郑吒浑身一震,他似乎有些明白这个世界存在的目的了,是的,正因为无聊的生存,才让他感觉到自己在腐朽,而一旦经历了这无数恐怖和死亡之后,那么平淡的生活确实是最幸福的期望。黑发青年继续说道:“除了可以兑换生活的天数以外,还可以兑换许多东西,譬如这把无限子弹的沙漠之鹰,只需要一百点,也即十天生活权利即可兑换,除此以外,一个人的平均素质,包括智力,精神力,细胞活力,神经反应速度,肌肉组织强度,免疫力强度这六点,也可以每一天生活权力兑换一点,一个普通人的六点强度均为一百,换句话说,只要你活过这一次恐怖片,你完全可以让你的力量比现在强大一倍,只要你活过一百场恐怖片,你就会成为一名超人!”戴眼镜的女孩却冷静的问道:“那么回归原点,让我们回到自己的世界里,这需要多少点奖励值?”“五万点!”黑发青年又从怀里掏出根香烟,点燃后他深吸一口道:“你一点奖励不用需要活过五十场恐怖片,这样你就能回去了。”顿时,数人都安静下来,按照这个黑发青年所言,五十场恐怖片的存活,如果不使用奖励点数来强化自己,那么根本就是不可能做到。“当然了,每场恐怖片一千点这是基本奖励,在恐怖片中也可以赚外快,比如刚才我给你们解释这一切,按照‘主神’的规定,给予新人解释规则,这将奖励给我一百点奖励点,同时你们应该注意到了自己正戴着一块奇怪的手表吧?”黑发青年扬了扬左手,上面有一块黑色纯金属的手表,样式古朴而纯粹。众人都看向了自己的左手,这块手表里显示了几个数据,一是正在倒计数的三个小时零七分,二是一些数据名字归纳,譬如丧尸个数,爬行者个数,新人个数……“每杀十个丧尸奖励一点奖励点,每杀一个爬行者奖励一百点奖励,每杀一个新人……奖励一千点奖励点……”黑发青年说完还不怀好意的看向了郑吒几人,这几人里只有郑吒和那名戴眼镜女孩安静的回看向他。“当然了,是负的奖励点……”黑发青年看着郑吒和戴眼镜女孩冷笑了声道:“好了,还有什么问题尽快问,这部恐怖片已经马上要正式开始了。”戴眼镜女孩看了看郑吒,郑吒略略一点头,她就继续问道:“还有两三个问题,生化危机一这部恐怖片我也看过,结尾是实验室的t病毒入侵浣熊市,那么在此之前,我们乘坐这节车厢逃离实验室,那不是可以很轻易的活下来吗?”黑发青年点点头道:“看看手表,左上方是不是有一个名字,念出它。”“马修?艾迪森!”几个人同时念了出来,接着他们惊奇的看到那些外[***]人里一名黑人浑身发出淡淡的光亮,这光亮只持续了片刻,接着那黑人又恢复到了正常。“这是电影里雇佣兵的队长,这部电影属于特定地区恐怖片,恐怖片剧情只发生在这实验室里,‘主神’为了限制难度,在这样的恐怖片中是无法逃离剧情区域太远的,离开这个马修?艾迪森一百米外,我们就会……轰的一声什么都没了,懂了吧?当剧情里的他死了后,这个限制又会加到其余剧情角色身上,环环相扣,我们只能拼命在这个恐怖片里活下去。”黑发青年解释道。郑吒忽然问道:“那个‘主神’是什么,你之前一直在说这个名字。”“‘主神’应该就是管理我们进入这个恐怖片循环的东西,它给予我们奖励点数,兑换也在它那里进行,‘主神’是一个光团,事实上我根本不知道它究竟是什么。”
戴眼镜的女孩点点头道:“最后一个问题……这数字代表了什么?”她指了指手表上正在倒数的数字。
“你必须在这个恐怖片里待的时间,时间一完结你就可以活着回到‘主神’处,领取奖励,接着面对下一部恐怖片。”黑发青年深吸口香烟道。
就在这时,这节车厢已经开始慢慢减速,黑发青年几口吸完香烟,他将沙漠之鹰从怀里掏出来后道:“好了,剧情从现在开始,他们从现在开始已经可以听到我们的对话,记住,被他们听到我们的话题会被扣十分,每一句话十分,负的部分从下次得到的奖励中扣除,菜鸟们……好好活下去吧!”
她社区用户
打开她社区 App 查看全部回复
【明星旧照大起底】古天乐说她是女神 香港影坛最具分量的影后 如今双耳近失聪。 她在香港电影历史上是一位里程碑式的人物,有名的才女,古天乐曾公开表示她是自己的女神,2010年CNN评选亚洲史上最伟大演员,香港有3人上榜,她赫然在列,另外两个分别是张国荣和梁朝伟。她的名字,叫萧芳芳。 曾多次获得金马奖和金像奖,在2009年还被第28届香港电影金像奖组委会授予终身成就奖,她也是25位亚洲影响力人物之一,女性只有3位,巩俐、周迅、萧芳芳。由此可见人们对萧芳芳的肯定。 对这个名字感到很陌生吧,那好接下来让我给你们介绍一下。李连杰版的《方世玉》剧中有一位武功高强,风趣搞笑,生性豪爽的人物----方世玉老妈,“方大玉”,她就是萧芳芳扮演的。 还有与周星驰合作的《漫画威龙》 这下大家总该熟悉了吧,再和大家说一个萧芳芳的经典作品,也是迄今为止她唯一的一首歌曲,相信大家也都有听过《世上只有妈妈好》,这是她11岁的时候在《苦海儿流浪记》里演唱的主题曲。其实萧芳芳是童星出道,最早与少年李小龙一同拍摄《孤星血泪》,有没有被震撼到。 萧芳芳算是港片界最会演戏的前辈代表人物之一。在港片的黄金年代演了不少电影,属于hold玉女,耍得了功夫,玩得了搞笑,演得了清纯,扮得了丑女,当得了红花,扮得了绿叶。以绿叶的角色,大家熟知的就是李连杰的方世玉系列吧,很是抢镜,演什么就是什么,演技浑然天成。 看《女人四十》的时候各种泪点啊,平凡朴实中又让人领悟看似浅显的深刻人生道理。 萧芳芳演绎生涯共参演影片高达几百部,获奖无数。在整个华语影坛中演技可媲美萧芳芳的女演员一手可以数完,角色塑造能力,戏路广度无出其右。她可以演戏,可以做编剧,还能导戏,她的表演生动有灵气。2009年,已接近失聪的萧芳芳获得第28届香港电影金像奖颁奖典礼终身成就奖,以表扬其在香港电影界作出的贡献。 息影后失聪的她创立护苗基金,一心扑在了公益事业中,宣传“保护儿童免受性侵犯”的讯息“,对于这样一位德艺双馨的演员,只有敬佩,别无其他。
【美食每刻】分享。 清理橱柜和冰箱的时候,发现存货不多,就几个鸡蛋,一点豆芽,半根胡萝卜,还有一把韭菜。可是家里有两个人特别不喜欢韭菜煎蛋,他们说韭菜味道太冲,吃完嘴巴一股味,难受。 想着用鸡蛋做个煎蛋好了,可是小朋友说吃煎蛋太频繁,没有新意。于是,我就煎蛋里加了点这些食材,煎至两面金黄,再抹上一些酱,味道还真不错,口感更丰富。这个蔬菜煎蛋做法太简单,一看就会。当然,你也可以根据自己家的喜好放其他蔬菜。 用料: 6个鸡蛋 3根葱,切碎 半根小胡萝卜,擦丝 半杯豆芽 1汤匙植物油 盐和白胡椒粉 辣酱或者蚝油 制作方法: 1, 取一个大碗,打入鸡蛋,放入葱、胡萝卜和豆芽,加盐和白胡椒粉调味 2. 平底锅刷上一层油,中火加热,倒入鸡蛋糊,煎至两面金黄 3. 最后装盘,抹上一点辣酱或者蚝油即可
如今社会,每个人都只会骂小三,我请问如果我作为妻子不会打扮也不会做饭每天找老公吵架,我老公在外面找人我一点也不奇怪,我还会理解,在骂别人之前请先自我反省!我既会打扮还做得一手好菜还不吵架,居然还单着[:女孩流泪:月老是看我太好了所以一直在给我寻觅配的上我得那个他,可您老老也让我都等了24年了
可能范冰冰自己都不知道, 她在“另一个世界”里能美成这样! 气质女人08-22 这八个字用来形容范冰冰再合适不过来! 作为中国红毯第一人,范冰冰历来的时尚造型不断被模仿,却无人能超越! 有人把范爷这些年来的经典造型和华美的礼服,用时装插画的形式表现了出来,仙鹤装、龙袍、青花瓷还有各种奢华唯美的高定礼服应有尽有,我们一起来感受一下这场视觉上的饕餮盛宴吧! - 红色LOOK - 范冰冰真的特别适合红色, 妩媚又不失优雅。 复古风格单肩礼服裙,纺纱材质, 穿在身上唯美仙气。 经典的戛纳红毯仙鹤装, 妥妥的女王气场! 透视纱裙搭配最原始的黑长直发型, 范爷竟然也有少女感。 无论是中国风还是简约的欧美风, 她都可以诠释得很完美! - 黑色LOOK - 这身黑裙穿出了那种华丽和高雅, 经典的宫廷荷叶边袖配上大气的长裙款式, 高级感爆棚!
哈喽,各位姐妹,我现在在卖车,有意向的朋友加我微信哦!CMY2983725,多多关照!!!
【谁穿着古装最美】 兰馨。 她是刘府上的千金,她的母亲生前喜爱兰花,她的父亲便为她的母亲建造了一座兰苑,她母亲在兰苑栽种了各色的兰花,还特地去边疆运回三色土,用来栽种特殊的白兰。直到三年前,母亲身患重病离世,把这座兰苑交到她的手中,并嘱咐她一定要好好管理,照顾好她的兰花,她不负所望,白兰在她的精心照料之下,一株株长得格外茂盛,盛开着洁白如雪的白兰花。她喜欢到夜幕降临时,再踏入南苑中,趁着朦胧的夜色,在夜色下欣赏迷人的兰花,嗅着它的阵阵芳香气息,她手中拿着一把浅蓝色的折扇,扇面上还描绘着兰苑的兰花,她画的兰花,犹如神来之笔,栩栩如生、楚楚动人。黑夜中,她独坐在兰苑的角落,她手中捧着如一轮圆月似的圆形灯笼,圆圆的灯笼散发着晶莹的月光,把兰苑的角落,照得如同白昼,她美得就像月宫中的仙子,令人沉醉着迷。----文原创,图片来自网络分享。
大家觉得我素颜好看,还是化妆好看,11岁。以上素颜以上化妆IBM Bluemix
点击按钮,开始云上的开发!
developerWorks 社区
在本系列文章中,HTML5 专家 David Geary 将向您展示如何逐步实现一个 HTML5 2D 视频游戏。在这由连续两部分组成的系列文章的第一篇文章中,将实现 runner sprite(跑步小人)的跳跃行为。
, 作者和演讲家, Clarity Training, Inc.
David Geary 是
的作者,也是
的合著者和其他 8 本 Java 图书的作者,其中包括畅销书 Swing 和 JavaServer Faces。David 经常在各大会议发表演讲,包括 JavaOne、Devoxx、Strange Loop、NDC 和 OSCON,他曾三次当选为 JavaOne 之星。他还为 developerWorks 撰写了
系列文章。您可以通过 @davidgeary 在 Twitter 上关注他。
在本系列的
中,我介绍了如何将 sprite 的活动(比如跑步、跳起、踱步或爆炸)封装在称之为行为 的可插入对象中。在运行时,您可以使用任何想要的行为轻松装饰 sprite。在诸多优点中,灵活性鼓励您探索可能被隐藏起来的游戏方面。
在本文中,我将继续讨论 sprite 行为。首先,本文是本系列文章中专门介绍单个 sprite 行为(跑步小人跳跃行为)的连续两部分文章的第一篇文章。在 “操纵时间,第 2 部分” 的结尾,Snail Bait 最终将会实现图 1 中描绘的自然跳跃序列。
图 1. 一个自然的跳跃序列其次,和
介绍的其他行为不一样,跳跃行为不能无限期地重复。由于这个简单的区别,Snail Bait 必须记录跳跃所用的时间。这一需求导致需要使用一个类似秒表的工具,因此我将实现一个 JavaScript 秒表,用它来记录跑步小人跳跃时的上升和下落时间。
跑步小人踪迹和平台顶部
Snail Bait 平台沿着三条轨道水平移动,如图 2 所示:
图 2. 平台轨道轨道间隔为 100 像素。这给高度为 60 像素的跑步小人提供了足够的跳跃空间。 清单 1 显示 Snail Bait 如何设置跑步小人的高度和平台垂直位置,还给出了一个返回某个轨道(1、2 或 3)相应基线的便捷方法: calculatePlatformTop()。
清单 1. 从轨道基线开始计算平台顶部位置var SnailBait = function () {
// Height of the runner's animation cells:
this.RUNNER_CELLS_HEIGHT = 60, // pixels
// Track baselines:
this.TRACK_1_BASELINE = 323, // pixels
this.TRACK_2_BASELINE = 223,
this.TRACK_3_BASELINE = 123,
SnailBait.prototype = {
calculatePlatformTop: function (track) {
(track === 1) { top = this.TRACK_1_BASELINE; }
else if (track === 2) { top = this.TRACK_2_BASELINE; }
else if (track === 3) { top = this.TRACK_3_BASELINE; }
Snail Bait 使用 calculatePlatformTop() 定位几乎所有游戏 sprite 的位置。
初始跳跃实现正如上篇文章结尾处所介绍的,Snail Bait 拥有最简单的跳跃算法,如清单 2 所示:
清单 2. 跳跃活动的键盘操作window.onkeydown = function (e) {
var key = e.keyC
if (key === 74) { // 'j'
if (snailBait.runner.track === 3) { // A nowhere to go
snailBait.runner.track++;
snailBait.runner.top = snailBait.calculatePlatformTop(snailBait.runner.track) -
snailBait.RUNNER_CELLS_HEIGHT;
...当玩家按下 j
键时,Snail Bait 会立即将跑步小人放在所在轨道上(假设跑步小人不在顶部轨道),如图 3 所示:
图 3. 不平稳的跳跃序列:容易实现但不自然 显示的跳跃实现有两个严重缺陷。首先,跑步小人从一个轨道移动到另一个轨道的方式(即时移动)远未达到预期效果。其次,跳跃实现发生在错误的抽象阶段。窗口事件处理程序没必要直接控制跑步者的属性;跑步小人本身要负责跳跃活动。将跳跃责任移交给跑步小人
清单 3 显示了一个重构的窗口 onkeydown 事件处理程序实现,该实现比
中的实现更简单,它将跳跃责任从事件处理程序移交给跑步小人。
清单 3. 窗口的关键处理程序委托给跑步小人window.onkeydown = function (e) {
var key = e.keyC
if (key === 74) { // 'j'
runner.jump();
启动游戏时,Snail Bait 调用了一个方法 equipRunner(),如清单 4 所示:
清单 4. 在游戏启动时装备跑步小人SnailBait.prototype = {
start: function () {
this.createSprites();
this.initializeImages();
this.equipRunner();
this.splashToast('Good Luck!');
如清单 5 所示,equipRunner() 方法为跑步小人添加了属性和 jump() 方法:
清单 5. 装备跑步小人:跑步小人的 jump() 方法SnailBait.prototype = {
equipRunner: function () {
// This function sets runner attributes:
this.runner.jumping = // 'this' is snailBait
this.runner.track = this.INITIAL_RUNNER_TRACK;
... // More runner attributes omitted for brevity
// This function also implements the runner's jump() method:
this.runner.jump = function () {
if ( ! this.jumping) {
// 'this' is the runner.
this.jumping = // Start the jump
},此外,跑步小人也有属性呈现其当前踪迹以及是否正在跳动。
如果跑步小人目前没有跳动,runner.jump() 将其 jumping 属性设置为 true。Snail Bait 在单独的行为对象中实现跳跃操作,就像实现跑步小人的其他行为一样,比如跑步和降落,事实上,所有 sprite 行为都是这样实现的。Snail Bait 在创建跑步小人时会将对象添加到其行为数组中,如清单 6 所示:
清单 6. 创建跑步小人及其行为var SnailBait = function () {
this.jumpBehavior = {
execute: function(sprite, time, fps) {
// Implement jumping here
this.runner = new Sprite('runner',
this.runnerArtist,
[ this.runBehavior, // behaviors
this.jumpBehavior,
this.fallBehavior
};现在基础架构已经为初始化跳跃活动做好准备,我可以将全部精力集中在跳跃行为上了。跳跃行为在清单 7 中,我们展示了一个跑步小人的初始实现,其功能与
中的代码相同。如果跑步小人的 jumping 属性(通过跑步小人的 jump() 方法设置,参见 )是 false,那么该行为将不执行任何操作。如果跑步小人在最上面的轨道上,那么该行为也不执行任何操作。
清单 7. 一个不切实际的跳跃行为实现var SnailBait =
function () {
this.jumpBehavior = {
execute: function(sprite, time, fps) {
if ( ! sprite.jumping || sprite.track === 3) {
sprite.track++;
sprite.top = snailBait.calculatePlatformTop(sprite.track) -
snailBait.RUNNER_CELLS_HEIGHT;
sprite.jumping =
};如果跑步小人正在跳动,而且不在顶部轨道上,那么
中实现的跳跃行为会将它移动到下一个轨道上,并将其 jumping 属性设置为 false 来完成跳跃。
中的跳跃实现一样, 中的实现立即将跑步小人从一个轨道移动到另一轨道。在实际的跳跃运动中,必须在特定时间内逐步将跑步小人从一个轨道移动到另一个轨道。
计时动画:秒表迄今为止,在 Snail Bait 中实现的所有运动都是不变的;例如,游戏中的所有 sprite(跑步小人除外)都是在水平方向来回移动,纽扣和蜗牛在其平台上不断来回踱步。(参阅本系列第 2 篇文章中的
小节,了解这一动作是如何实现的。)硬币、蓝宝石和红宝石也可以慢慢上下跳动,甚至不需要停下来休息。
但是,跳跃行为不是固定不变的,它有一个明确的开始时间和结束时间,因此,要实现跳跃行为,需要采用一种方法不断监控跳跃已经开始了多长时间,因此我需要一个秒表。
清单 8 显示了 Stopwatch JavaScript 对象的实现:
清单 8. 一个 Stopwatch 对象// Stopwatch..................................................................
// You can start and stop a stopwatch and you can find out the elapsed
// time the stopwatch has been running. After you stop a stopwatch,
// its getElapsedTime() method returns the elapsed time
// between the start and stop.
Stopwatch = function ()
this.startTime = 0;
this.running =
this.elapsed =
this.paused =
this.startPause = 0;
this.totalPausedTime = 0;
// You can get the elapsed time while the stopwatch is running, or after it's
// stopped.
Stopwatch.prototype = {
start: function () {
this.startTime = +new Date();
this.running =
this.totalPausedTime = 0;
this.startPause = 0;
stop: function () {
if (this.paused) {
this.unpause();
this.elapsed = (+new Date()) - this.startTime -
this.totalPausedT
this.running =
pause: function () {
this.startPause = +new Date();
this.paused =
unpause: function () {
if (!this.paused) {
this.totalPausedTime += (+new Date()) - this.startP
this.startPause = 0;
this.paused =
getElapsedTime: function () {
if (this.running) {
return (+new Date()) - this.startTime - this.totalPausedT
return this.
isPaused: function() {
return this.
isRunning: function() {
return this.
reset: function() {
this.elapsed = 0;
this.startTime = +new Date();
this.running =
this.totalPausedTime = 0;
this.startPause = 0;
};您可以启动、停止、暂停、取消暂停和重置
中的秒表对象。您还可以获取其运行时间,确定秒表是正在运行还是已经停了下来。
在本系列第 3 篇文章的
一节中,我介绍了
如何通过计算游戏暂停时间,从游戏停止位置精确恢复某个暂停的游戏。就像游戏一样,暂停秒表必须从游戏停止的地方精确恢复,因此它们也需要考虑暂停时间。
秒表实现尽管比较简单,但意义重大,因为它使您实现了持续一段时间的行为,在本例中,该行为是更为自然的跳跃。
细化跳跃行为现在已经有了秒表,让我们使用它来细化跳跃行为。首先,修改
中的 equipRunner() 方法,如清单 9 所示:
清单 9. 修改后的equipRunner() 方法SnailBait.prototype = {
this.RUNNER_JUMP_HEIGHT = 120,
this.RUNNER_JUMP_DURATION = 1000, // milliseconds
equipRunnerForJumping: function () {
this.runner.JUMP_HEIGHT = this.RUNNER_JUMP_HEIGHT;
this.runner.JUMP_DURATION = this.RUNNER_JUMP_DURATION;
this.runner.jumping =
this.runner.ascendStopwatch
= new Stopwatch(this.runner.JUMP_DURATION/2);
this.runner.descendStopwatch = new Stopwatch(this.runner.JUMP_DURATION/2);
this.runner.jump = function () {
if (this.jumping) // 'this' is the runner
this.jumping =
this.runAnimationRate = 0; // Freeze the runner while jumping
this.verticalLaunchPosition = this.
this.ascendStopwatch.start();
equipRunner: function () {
this.equipRunnerForJumping();
};修改后的 equipRunner() 实现调用了一个新方法:equipRunnerForJumping()。顾名思义,该方法为跑步小人装备了跳跃行为。该方法创建了两个秒表:runner.ascendStopwatch 用于上升,runner.descendStopwatch 用于下落。跳跃开始时,jump() 方法启动跑步小人的上升秒表,正如您在
中所看到的。该方法还将跑步小人的跑步动画速度(通过其跑动动画定义了跑步小人的速度有多快)设置为零,让跑步小人停止跑步,此时跑步小人在空中。run() 方法还记录了跑步小人的垂直位置,以便在跳跃完成时让其返回原地。
中设置的所有跑步者属性进行了总结:
表 1. 跑步小人与相关的属性属性描述JUMP_DURATION一个常量,表示跳跃持续的时间:1000 毫秒。JUMP_HEIGHT一个常量,代表跳跃高度:120 像素。跳跃的最高点距下一个轨道 20 像素。ascendStopwatch记录跑步小人在跳跃过程中所用的上升时间的秒表。descendStopwatch记录跑步小人在跳跃过程中所用的下落时间的秒表。jumpApex跑步小人跳跃的最高点;跳跃行为使用 apex 确定在下落过程中跑步小人在每个框架中所用的下落空间。jumping一个标记,跑步小人跳跃时其值为 true。verticalLaunchPosition跳跃开始时,跑步小人的位置(跑步小人 sprite 的左上角)。完成跳跃后返回该位置。
接着,我将在清单 10 中重构最初在
中实现的跳跃行为:
清单 10. 跳跃行为,重新修改var SnailBait =
function () {
this.jumpBehavior = {
execute: function(sprite, context, time, fps) {
if ( ! sprite.jumping) {
if (this.isJumpOver(sprite)) {
sprite.jumping =
if (this.isAscending(sprite)) {
if ( ! this.isDoneAscending(sprite)) this.ascend(sprite);
this.finishAscent(sprite);
else if (this.isDescending(sprite)) {
if ( ! this.isDoneDescending(sprite)) this.descend(sprite);
this.finishDescent(sprite);
... 中的跳跃行为是一个高级别抽象的实现,它将跳跃细节留给另一个方法,比如 ascend() 和 isDescending()。现在需要做的就是填充细节,通过使用跑步小人的上升和下降秒表来实现以下方法:
isJumpOver()ascend()isAscending()isDoneAscending()finishAscent()descend()isDescending()isDoneDescending()finishDescent()直线运动到目前为止,上面列出的方法都可以产生直线运动,这意味着跑步小人以恒定速率跳起或落下,如图 4 所示。图 4. 平稳的直线跳跃序列直线运动的结果是生成一个不自然的跳跃运动,当跑步者下落或跳起时,重力会使它们不断加速或减速。在下一期中,我将重新实现这些方法,使之产生非直线运动,如
所示。现在,继续介绍直线运动的简单案例。
首先,清单 11 展示了跳跃行为 isJumpOver() 方法的实现,无论运动是线性的还是非线性的,这个方法都是相同的:一旦结束跳跃,所有秒表都将不再运行:
清单 11. 确定跳跃是否结束SnailBait.prototype = {
this.jumpBehavior = {
isJumpOver: function (sprite) {
return !sprite.ascendStopwatch.isRunning() &&
!sprite.descendStopwatch.isRunning();
};处理上升运动的跳跃行为方法如清单 12 所示:
清单 12. 上升SnailBait.prototype = {
this.jumpBehavior = {
isAscending: function (sprite) {
return sprite.ascendStopwatch.isRunning();
ascend: function (sprite) {
var elapsed = sprite.ascendStopwatch.getElapsedTime(),
= elapsed / (sprite.JUMP_DURATION/2) * sprite.JUMP_HEIGHT;
sprite.top = sprite.verticalLaunchPosition - deltaY; // Moving up
isDoneAscending: function (sprite) {
return sprite.ascendStopwatch.getElapsedTime() & sprite.JUMP_DURATION/2;
finishAscent: function (sprite) {
sprite.jumpApex = sprite.
sprite.ascendStopwatch.stop();
sprite.descendStopwatch.start();
中的方法进行了总结:
表 2. jumpBehavior 的上升方法方法描述isAscending()如果跑步小人的上升秒表正在运行,则返回 true。ascend()根据上一个动画帧的运行时间、跳跃持续时间和跳跃高度,向上 移动跑步小人。isDoneAscending()返回 true,如果跑步小人上升秒表中的运行时间大于跳跃持续时间的一半。
finishAscent()
通过停止跑步小人的上升秒表来结束上升运动,并启动下降秒表。
当跑步小人处于跳跃最高点时,jumpBehavior 会调用该方法,finishAscent() 在跑步小人的 jumpApex 属性中存储其位置。descend() 方法将会使用该属性。
回忆一下跑步小人的
jump() 方法,如
所示,启动跑步小人的上升秒表。
随后,运行的秒表将导致跳跃行为的 isAscending() 方法临时返回 true。当跑步小人完成上升过程时(这意味着跳跃已完成了一半),跑步小人的跳跃行为会重复调用 ascend() 方法,正如您在
中所看到的。
上升和下降ascend() 方法使跑步小人逐渐向上移动。它可以计算像素来移动每个动画帧中的跑步小人:秒表的运行时间(毫秒)除以跳跃时间(毫秒)的一半,然后乘以跳跃高度(像素)。毫秒相互抵消,生成的像素值作为 deltaY 值的测量单元。因此,该值表示当前动画帧中跑步小人在垂直方向移动的像素。
在跑步小人完成上升过程后,跳跃行为的 finishAscent() 方法会记录跳跃到顶点时 sprite 的位置,然后停止上升秒表,并启动下降秒表。
与下降运动相关的跳跃行为方法如清单 13 所示:
清单 13. 下降运动SnailBait.prototype = {
this.jumpBehavior = {
isDescending: function (sprite) {
return sprite.descendStopwatch.isRunning();
descend: function (sprite, verticalVelocity, fps) {
var elapsed = sprite.descendStopwatch.getElapsedTime(),
= elapsed / (sprite.JUMP_DURATION/2) * sprite.JUMP_HEIGHT;
sprite.top = sprite.jumpApex + deltaY; // Moving down
isDoneDescending: function (sprite) {
return sprite.descendStopwatch.getElapsedTime() & sprite.JUMP_DURATION/2;
finishDescent: function (sprite) {
sprite.top = sprite.verticalLaunchP
sprite.descendStopwatch.stop();
sprite.jumping =
sprite.runAnimationRate = snailBait.RUN_ANIMATION_RATE;
中的方法进行了总结:
表 3. jumpBehavior 的下降方法isDescending()如果跑步小人下降秒表正在运行,则返回 true。descend()根据上一动画帧的运行时间、跳跃持续时间和跳跃高度,向下 移动跑步小人。isDoneDescending()如果跑步小人下落到跳跃之前的位置,则返回 true。finishDescent()通过停止跑步小人的下降秒表,并将跑步小人的 jumping 标记分别设置为 false,停止下降运动,然后跳起。完成下降运动后,跑步小人可能不在跳跃开始的那个位置,因此 finishDescent() 将跑步小人的位置设置为起跳之前的垂直位置。最后,finishDescent() 将跑步小人的动画速度设置为正常值,跑步小人开始跑步。 中的上升方法和
中的下降方法具有对称性。ascend() 和 descend() 将计算像素值,采用相同的方法沿着当前帧的垂直方向移动跑步小人。不过,descend() 方法会将该值添加到跳跃顶点,反之,从起跳位置减去该值。(回忆一下画布 Y 轴自上而下的增加。)
完成跳跃的下降过程后,finishDescent() 将跑步小人放回到起跳之前的相同垂直位置,然后重新开始跑步动画。
结束语在本系列的下一篇文章中,我将向您展示如何实现非线性运动,形成
中所示的实际跳跃运动。顺便我还向您介绍如何延伸时间,时间的其他衍生(比如颜色变化)可以产生非线性效果。下期见!
下载描述名字大小样例代码1.2MB
参考资料 :(David Geary,Prentice Hall,2012 年):David Geary 的书广泛介绍了 Canvas API 与游戏开发。您还可以查看
:在任何支持 HTML5 的浏览器(最好是 Chrome V18 以上版本)上在线玩 Snail Bait。
:观看 David Geary 在 Strange Loop 2011 上的演讲。 :观看 David Geary 在 Norwegian Developer's Conference (NDC) 2011 上的演讲。
:在 Wikipedia 上阅读有关平台游戏的资料。
:在 Wikipedia 上阅读有关 side-scroller 视频游戏的资料。
:阅读关于 Strategy 设计模式的 Wikipedia 文章。
:通过 developerWorks 知识路径学习 HTML5 基础知识。 :这里有数百篇关于 Java 编程各个方面的文章。
:您可以下载这个面向 Android 的流行开源平台视频游戏的资源。大多数 Snail Bait sprite 都来自 Replica Island(在许可的情况下使用)。 加入 。探索由开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户进行交流。
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
文章、教程、演示,帮助您构建、部署和管理云应用。
立即加入来自 IBM 的专业 IT 社交网络。
为灾难恢复构建应用,赢取现金大奖。
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=Java technology, Web developmentArticleID=937288ArticleTitle=HTML5 2D 游戏开发: 操纵时间,第 1 部分publish-date=