飞机的弹幕网倾泻为什么打断不了回复f的?

正文 第一百五十章 打断小日本的獠牙
作者:不打内战&&&&
&&&&">热河北票华夏阵地上,东北军热河守军一〇七旅董福亭和义勇军耿继周终于率部暂时击退了关东军步兵的冲击。董福亭擦了擦额头上的汗水,端起一杯早就有些发冷的白开水,咕咚两口就喝了个精光,“妈的,关东军太能欺负人了,打仗没有这样整的。”&&&&耿继周眉头先是一皱,苦笑着说,“是啊,他们的炮兵先是破坏了我们的防御工事,工事里面的一个营几乎丧失殆尽,接着他们的步兵以飞机和战车掩护攻击前进,我数了数他们竟然有将近30门各式大炮,要是我们有几挺高射机枪,大炮神马的就好了,不然这仗没法打。”&&&&关东军第八师团步兵第四旅团旅团长铃木美通因为得到了前锋的任务,这几天一直沾沾自喜,卧槽!又能立功咧。神马,还没攻下热河守军的阵地?&&&&这厮在旅团部对着手下两个联队长破口大骂,“八嘎!我们有32门大炮,还有关东军飞行队12架飞机的帮忙,竟然攻不下只有3门迫击炮的北票!再给你们一次机会,再攻不下,你们全部死啦死啦的!”&&&&首先接到任务的飞行队松下中队长顿时火冒三丈,简直快无语了,刚刚返回机场的他正要抓紧时间和随军韩国慰安妇爽一下,刚刚脱了衣服,正要直捣黄龙呢。&&&&“八嘎!第四旅团应该全体剖腹自杀,我们已经帮他们炸毁了所有的防御工事,他们还拿不下阵地,我要是第八师团师团长西义一的话,我就让他们第四旅团统统进军事法庭!全体都有,一会全都降低高度,把支那士兵统统杀死,杀鸡给给!!”&&&&第四旅团后方的一片山林中,刚得到第四旅团炮兵阵地的冯全正要给迫击炮百人队发信号,听到了小鬼子嗡嗡的飞机声,妈的,瞌睡来了,小鬼子就来送枕头,真孝顺啊。&&&&冯全一声令下,两支机枪连的30挺M2重机枪以及机枪手弹药手全部披着白色的伪装,穿甲燃烧弹密密麻麻的堆放在机匣右方,M2全部调节成自动发射状态,黑洞洞的枪口瞄向天空。&&&&现在还是初春,漫山遍野到处都是皑皑的积雪,小伙伴们和美丽的大自然融为一体。&&&&第一架,第二架,第三架……关东军飞行队的12架飞机迅速的飞了过来,以标准间隔鱼贯排开,进入轰炸航路并已经开始俯冲。北票阵地的华夏军队有些绝望了,妈了个巴子的,这下不知又得有多少小伙伴要牺牲咧。心里虽然窝了一团火,却没有发泄之处,只能顺着废弃的防御工事寻找藏身之地。&&&&飞行中队长松下看到俯冲的飞机编队离华夏阵地越来越近,狞笑着想要再次在华夏阵地上倾泻炸弹,各种子弹。&&&&“笃笃笃”&&&&射速每分钟500发的12.7×99毫米大口径重机枪穿甲燃烧弹欢快的飞向这12架低空正在俯冲战斗机和轰炸机,30挺早就计算好提前量射速极快的重机枪,发射出恐怖的密集弹幕,团团笼罩住12架薄皮大馅的所谓飞机,没有任何死角。&&&&“纳尼?他们什么时候有了这么多高射机枪?第四旅团情报科什么的干活?... ...”&&&&没等中队长松下做出闪避的动作,几十发大口径子弹穿过前挡风玻璃,又钻入松下的前额,酒糟鼻,鸡一样的胸脯,飞机顿时失去控制,摇摇晃晃的飞机拖着一股黑烟飘向地面,接着“轰隆”一声,炸弹混合着汽油爆炸了,一股美丽的蘑菇云升上了天空。&&&&一时间,天空中子弹横飞,领头的长机被击毁让其他小日本飞行员大为震惊。余下的11架纷纷脱离俯冲航路,向不同方向转弯躲避。&&&&但还是又有8架飞机被击中油箱,凌空爆炸!向四面八方散发的火焰黑烟比刚才的蘑菇云还要美丽,壮观。侥幸剩下的2架飞机也是伤痕累累,不过主要伤在机翼上,不可思议的他们拼命拉高飞机,一转眼的功夫就消失了。&&&&但是要是冯全知道这两架返回刚被自己重创,关东军废了九牛二虎之力刚修好的锦州飞机场时的后果的话,肯定做梦也会笑掉大牙。&&&&两架飞机刚要在锦州飞机场下落,受了重伤的两个飞行员终于迷糊了,一架飞机冲向地面的30多架挂满了炸弹的飞机,一架竟然冲向了机场油库,结局都是很完美,殉爆呗!听说武藤信义头发都快掉光了,神马?快死了,呵呵。&&&&北票阵地上观战的热河守军先是迷惑,卧槽!这是哪来的好基友哟?看到一架领头的飞机被击落又是一愣,等他们看到又有8架飞机凌空爆炸,随即大喜,纷纷从石头缝中中探出身来,欢呼声在小小的山谷里不断回荡。&&&&在沈思南侦察支队的指引下,PM1938重型迫击炮百人队找到一位当地的百姓,在他的带领下,百人队沿着樵夫打柴的羊肠山道,一路披荆斩棘,翻山越岭,终于确定了第四旅团炮兵阵地的具体位置。&&&&二话不说,他们选中一片背山坡,迅速组装好迫击炮,炮手紧张的计算射击诸元,弹药手从后背卸下重达16公斤,射程5.7公里的炮弹,万事俱备只欠东风,只要冯全这边发过来进攻的信号,20门射速每分钟20发的重型迫击炮就会把炮弹倾泻在小日本的炮兵阵地。&&&&“呜呜”信号枪响了。收到信号的迫击炮百人队开始了发言,&&&&“嗖嗖嗖”&&&&“轰轰轰”&&&&光着膀子正在朝热河北票阵地发射炮弹的第四旅团炮兵大队的小日本看到满天飞来的迫击炮炮弹,惊呆了,大声哀嚎之后,纷纷夺命奔逃,但这是徒劳的。&&&&由于是覆盖式轰炸,加上骄横跋扈的炮兵一直没受到攻击,炮弹箱离的很近,很多炮弹都已经安装好爆炸引信,在16公斤的迫击炮炮弹的突然袭击下,终于被引爆,32门各式山炮,野炮,步兵炮都被炸成了零件。炮兵更是无一幸存,残肢断臂在华夏的天空中飞舞了好久,才不甘心的落回地面。&&&&小日本的飞行中队被陌生友军击溃,更加让热河守军兴奋的是,第四旅团的炮兵阵地上,响起了更加猛烈地爆炸声,神马?他们的炮兵也完了!&&&&怎么办?整吧!一〇七旅董福亭和义勇军耿继周不约而同的发出命令,全线反击!东北军纷纷从各个山头直起身子,手握钢枪,大刀,呐喊着冲向小日本关东军第八师团第六旅团。&&&&“安德鑫听令,我让你担任北玄武小组组长,7个百人队都归你管理,很多人不服气,这下就看你的了,他们东北军还有义勇军从前面进攻,咱们从后面包围第四旅团,有没有信心全歼他们?”&&&&“大当家,你就瞧好吧!”安德鑫等着牛铃一般大小的双眼,往手心重重的吐了一口唾沫,扭头对几个百夫长大声嘶吼道,“宁叫白山黑水化为赤白之区,不愿华胄倭奴同立与黄海之岸!兄弟们,承蒙大当家的收留,报仇的机会到了,小日本现在就像一只没了牙的老虎,冲啊!”
鼠标滚屏说明:1-10,1最慢,10最快
① 精彩小说《抗战之临时工》连载于天书中文网,更多关于《抗战之临时工》内容,
请关注天书中文网。本站已开通手机()阅读功能,敬请通过手机访问《抗战之临时工》最新情节!
② 本站所收录精彩小说 《抗战之临时工》(作者:不打内战)及有关此小说《抗战之临时工》
评论所代表观点,均属作者个人行为,并不代表本站立场。
③书友如发现本小说《抗战之临时工》内容有与法律抵触之处,请马上向本站举报。希望您多多支持本站,非常感谢您的支持!
④《抗战之临时工》是一本优秀小说,情节动人,为了让作者:不打内战能提供更多更好的作品,请您购买本书的VIP、或多多宣传本书和推荐,也是作者的一种另类支持!小说的未来,是需要您我共同的努力!为什么东方project的游戏刚开始都是打飞机的弹幕游戏?_百度知道
为什么东方project的游戏刚开始都是打飞机的弹幕游戏?
提问者采纳
作者喜欢吧
提问者评价
太给力了,你的回答完美解决了我的问题!
其他类似问题
为您推荐:
东方project的相关知识
其他1条回答
东方永夜抄
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁当前访客身份:游客 [
这个人很懒,啥也没写
:好文章。
:我也希望这玩意好用,同事推荐用这个来开发安卓程...
:checkout 不了 能发份到
:引用来自“10yuecf”的评论svn登录需要密码?读取...
:svn登录需要密码?
:引用来自“Xiao_f”的评论 效率不高,优化空间很...
:效率不高,优化空间很大
今日访问:0
昨日访问:0
本周访问:9
本月访问:3
所有访问:2410
HTML5演示碰撞及基本弹幕的实现
发表于1年前( 11:00)&&
阅读(1087)&|&评论()
0人收藏此文章,
上一年8月,有师弟想做一个弹幕游戏作为毕业设计,于是我写了个程序来给他讲解碰撞检测及弹幕运动的算法。最近整理以往的代码库时想起了这个,决定以此写一篇文章。
0、演示在此:
1、框架搭建
&&&&为了方便演示,我搭建了一个简单的游戏“框架”,框架包含描述游戏状态的部分及逻辑部分。
&&&&一个弹幕游戏至少应当包含“自机”及“弹幕”。首先,游戏页面中应当包含一个用于绘制实际图形的canvas、一个用于演示的描述自机及弹幕形状的canvas。此外,为了便于更换图形,我还创建了两个canvas用于绘制自机和子弹。
&&&&不包含JS代码时,页面如下:
&!doctype&html&
&&&&&meta&charset="UTF-8"&
&&&&&title&.&/title&
&style&type="text/css"&
&&&&#stage{
&&&&&&&&display:
&&&&&&&&float:
&&&&&&&&width:400
&&&&&&&&height:300
&&&&&&&&box-shadow:
&&&&&&&&&&&&-2px&-2px&4px&rgba(0,&0,&0,&0.3),
&&&&&&&&&&&&2px&2px&4px&rgba(0,&0,&0,&0.6);
&&&&#hitck{
&&&&&&&&display:
&&&&&&&&float:
&&&&&&&&width:400
&&&&&&&&height:300
&&&&&&&&box-shadow:
&&&&&&&&&&&&-2px&-2px&4px&rgba(0,&0,&0,&0.3),
&&&&&&&&&&&&2px&2px&4px&rgba(0,&0,&0,&0.6);
&&&&#plane{
&&&&&&&&display:
&&&&&&&&float:
&&&&&&&&width:48
&&&&&&&&height:48
&&&&&&&&box-shadow:
&&&&&&&&&&&&-2px&-2px&4px&rgba(0,&0,&0,&0.3),
&&&&&&&&&&&&2px&2px&4px&rgba(0,&0,&0,&0.6);
&&&&#ammo{
&&&&&&&&display:
&&&&&&&&float:
&&&&&&&&width:12
&&&&&&&&height:12
&&&&&&&&box-shadow:
&&&&&&&&&&&&-2px&-2px&4px&rgba(0,&0,&0,&0.3),
&&&&&&&&&&&&2px&2px&4px&rgba(0,&0,&0,&0.6);
&&&&&canvas&id="stage"&&/canvas&
&&&&&canvas&id="hitck"&&/canvas&
&&&&&canvas&id="plane"&&/canvas&
&&&&&canvas&id="ammo"&&/canvas&
&&&&正如前文所说的,整个页面就只有四个canvas,从方便的角度出发,我们把舞台的大小写死为800*600。
2、一个子弹
&&&&在开始探究碰撞检测前,我们需要编写弹幕生成的代码,因为没有实际的弹幕就无法理解碰撞。
&&&&子弹理所当然是一个物体,在此,我们假设每个子弹都是一个对象(注意,这么做的性价比很低),一个基本的子弹定义如下:
DirectAmmo&=&function(x,&y,&vx,&vy,&ax,&ay){
&&&&this.x&&&=&x&&||&400;&//&横坐标
&&&&this.y&&&=&y&&||&300;&//&纵坐标
&&&&this.vx&&=&vx&||&2;&&&//&横向速度
&&&&this.vy&&=&vy&||&2;&&&//&纵向速度
&&&&this.ax&&=&ax&||&0;&&&//&横向加速度
&&&&this.ay&&=&ay&||&0;&&&//&纵向加速度
&&&&this.die&=&&&&&&//&子弹是否已消亡
&&&&假设每个子弹的运动都是独立的,那么可以写一个函数来描述每一个时间片中子弹的移动:
DirectAmmo.prototype.move&=&function(){
&&&&this.vx&+=&this.
&&&&this.vy&+=&this.
&&&&this.x&&+=&this.
&&&&this.y&&+=&this.
&&&&if(this.x&&&0){
&&&&&&&&this.die&=&
&&&&if(this.y&&&0){
&&&&&&&&this.die&=&
&&&&if(this.x&&&800){
&&&&&&&&this.die&=&
&&&&if(this.y&&&600){
&&&&&&&&this.die&=&
&&&&if(this.vx&==&0&&&&this.vy&==&0&&&&this.ax&==&0&&&&this.ay&==&0){
&&&&&&&&this.die&=&
&&&&return&
&&&&当子弹超出屏幕范围之后,子弹便会消亡,将其die属性置为true。
&&&&一个游戏不可能只有一颗子弹,同一个屏幕上可能同时出现很多的子弹,这些子弹按照各自的轨迹独立运动,这构成了弹幕游戏华丽的基础,因此,我们需要一个弹幕队列来管理这些子弹。
var&Queue&=&{
&&&&ammo&:&[],
&&&&initAmmo&:&function(maxAmmoCount){
&&&&&&&&maxAmmoCount&=&maxAmmoCount&||&512;
&&&&&&&&for(var&i&=&0;&i&&&maxAmmoC&i&++){
&&&&&&&&&&&&Queue.ammo[i]&=&
&&&&init&:&function(){
&&&&&&&&Queue.initAmmo();
&&&&在initAmmo方法中,定义了一个maxAmmoCount变量,弹幕队列中之多只能包含maxAmmoCount个子弹对象实例。早期的弹幕游戏通常用此方法控制性能。
&&&&然后,我们需要为子弹添加一个方法,用于将子弹自身加入到弹幕队列中:从头开始扫描队列,当找到空位时把自己装进去空位置中。空位的定义是null或者是指向已死亡的子弹的位置:
DirectAmmo.prototype.queue&=&function(){
&&&&var&i&=&0;
&&&&while(i&&&Queue.ammo.length){
&&&&&&&&if(Queue.ammo[i]&==&null&||&Queue.ammo[i].die){
&&&&&&&&&&&&Queue.ammo[i]&=&
&&&&&&&&&&&&return&
&&&&&&&&i&++;
&&&&return&
&&&&至此,子弹本身就实现了。
3、一组子弹
&&&&弹幕游戏中,敌机通常都是一次性倾泻出一堆子弹——一堆有规律的子弹,譬如如下图的从圆心开始往外扩散的子弹:
&&&&自然不可能逐个子弹去生成、去描述,我们需要定义一个方法来生成这样的一组子弹,这样的一个整体比起单个子弹来多了两个属性:数量、速度。
RoundDirectAmmo&=&function(x,&y,&count,&speed,&ax,&ay){
&&&&x&&&&&&&&&&=&x&||&400;
&&&&y&&&&&&&&&&=&y&||&300;
&&&&count&&&&&&=&count&||&32;
&&&&speed&&&&&&=&speed&||&2;
&&&&ax&&&&&&&&&=&ax&||&0;
&&&&ay&&&&&&&&&=&ay&||&0;
&&&&var&offset&=&0.00001;
&&&&var&step&&&=&Math.PI&*&2&/&
&&&&var&ammos&&=&[];
&&&&var&i,&vx,&vy,&
&&&&for(i&=&0;&i&&&&i++){
&&&&&&&&vx&=&speed&*&Math.cos(offset);
&&&&&&&&vy&=&speed&*&Math.sin(offset);
&&&&&&&&da&=&new&DirectAmmo(x,&y,&vx,&vy,&ax,&ay);
&&&&&&&&offset&+=&
&&&&&&&&ammos[ammos.length]&=&
&&&&this.ammos&=&
& & RoundDirectAmmo这个对象实际上包含了一组子弹,在生成这组子弹时按照每一个子弹的扩散方向赋予不同的初速度,环状弹幕就这样实现了。
&&&&然后给RoundDirectAmmo写一个将子弹加入到队列的函数:
RoundDirectAmmo.prototype.queue&=&function(){
&&&&var&i&=&0,&
&&&&&&&&j&=&0;
&&&&while(i&&&Queue.ammo.length&&&&j&&&this.ammos.length){
&&&&&&&&if(Queue.ammo[i]&==&null&||&Queue.ammo[i].die){
&&&&&&&&&&&&Queue.ammo[i]&=&this.ammos[j];
&&&&&&&&&&&&j&++;
&&&&&&&&i&++;
&&&&return&
& &&这里相当于对每个子弹直接调用DirectAmmo的queue方法,至于为什么没直接调用queue,我也忘记当时写这段代码时的目的了。
& & 环状弹幕的“散开”,除了上述这种同步散开外,还有螺旋状散开的例子:
&&&&要实现这种弹幕,只需要对RoundDirectAmmo的加入队列的方式进行一些修改,来添加一个queue_delay方法:
RoundCircleAmmo.prototype.queue_delay&=&function(n,&i){
&&&&n&=&n&||&10;
&&&&i&=&i&||&0;
&&&&if(this.ammos[i]){
&&&&&&&&this.ammos[i].queue();
&&&&&&&&var&qr&=&
&&&&&&&&setTimeout(function(){qr.queue_delay(n,&i&+&1)},&n);
&&&&return&
&&&&如上,只要添加每个子弹加入到队列的时间间隔,就可以实现螺旋散开的弹幕。
4、绘制对象
&&&&对子弹的讲解到此为止,接下来是实际的绘制过程。
&&&&在上面我们创建了四个canvas,这里我们创建几个变量用来指向这几个canvas:
var&cvs_plane,&&//&自机
&&&&ctx_plane,
&&&&cvs_ammo,&&&//&子弹
&&&&ctx_ammo,
&&&&cvs,&&&&&&&&//&舞台
&&&&cvs_ck,&&&&&//&碰撞演示
&&&&为了偷懒,灰机和子弹都画一个圆来表示,实际上程序写完之后只要替换一下这个绘制过程,无论什么形状的自机和子弹都没问题:
cvs_plane&=&document.getElementById('plane');
cvs_plane.height&=&48;
cvs_plane.width&&=&48;
ctx_plane&=&cvs_plane.getContext('2d');
ctx_plane.fillStyle&=&'rgba(0,&192,&248,&1)';
ctx_plane.beginPath();
ctx_plane.arc(24,24,24,0,Math.PI*2,true);
ctx_plane.closePath();
ctx_plane.fill();
var&plane_data&=&ctx_plane.getImageData(0,&0,&48,&48).
for(var&i&=&0;&i&&&48&*&48;&i&++){
&&&&var&dot&=&i&*&4;
&&&&if(plane_data[dot]&&&0&||&plane_data[dot&+&1]&&&0&||&plane_data[dot&+&2]&&&0){
&&&&&&&&Matrix.plane[i]&=&1;
&&&&}else{
&&&&&&&&Matrix.plane[i]&=&0;
cvs_ammo&=&document.getElementById('ammo');
cvs_ammo.height&=&12;
cvs_ammo.width&&=&12;
ctx_ammo&=&cvs_ammo.getContext('2d');
ctx_ammo.fillStyle&=&'rgba(255,&255,&255,&0.5)';
ctx_ammo.beginPath();
ctx_ammo.arc(6,6,6,0,Math.PI*2,true);
ctx_ammo.closePath();
ctx_ammo.fill();
var&ammo_data&=&ctx_ammo.getImageData(0,&0,&12,&12).
for(var&i&=&0;&i&&&12&*&12;&i&++){
&&&&var&dot&=&i&*&4;
&&&&if(ammo_data[dot]&&&0&||&ammo_data[dot&+&1]&&&0&||&ammo_data[dot&+&2]&&&0){
&&&&&&&&Matrix.ammo[i]&=&1;
&&&&}else{
&&&&&&&&Matrix.ammo[i]&=&0;
cvs&=&document.getElementById('stage');
cvs.height&=&600;
cvs.width&&=&800;
ctx&=&cvs.getContext('2d');
ctx.fillStyle&=&'#000000';
ctx.fillRect(0,&0,&800,&600);
cvs_ck&=&document.getElementById('hitck');
cvs_ck.height&=&600;
cvs_ck.width&&=&800;
ctx_ck&=&cvs_ck.getContext('2d');
ctx_ck.fillStyle&=&'#000000';
ctx_ck.fillRect(0,&0,&800,&600);
&&&&上面这段代码中牵扯到了一个Matrix对象,这个对象,我们姑且称之为“碰撞检测矩阵”。
5、碰撞检测
&&&&碰撞检测的方法很多,最容易实现的是基于颜色。
&&&&就如同我们肉眼看到子弹撞上飞机一样,只要设想,在飞机所处的位置上出现了子弹,就认为两者发生了碰撞。
&&&&弹幕游戏都有着“擦弹”的设定。面对形状多变的子弹和飞机,我们不能简单的对子弹的坐标宽高与飞机的坐标宽高进行比对来断定是否发生了碰撞。譬如上面绘制的圆形子弹,其画板面积是一个矩形,但实际能参与到碰撞的只有包含图形的一个圆形部分,自机同理。
&&&&如是,很容易得出一个理论:只有自机、子弹画板中不透明的部分发生了重叠,才是真碰撞。
&&&&屏幕上的图形有很多的颜色,而在检测碰撞时我们只需要两种颜色:透明、不透明。
&&&&因此,我们来定义几个大小等于画板宽度乘以画板高度的数组,用来单纯地绘制形状,此外,我们再定义几个方法,组成Matrix对象:
var&Matrix&=&{
&&&&&*&自机形状
&&&&&*&@type&{Array}
&&&&plane&:&[],
&&&&&*&子弹形状
&&&&&*&@type&{Array}
&&&&ammo&&:&[],
&&&&&*&舞台MAP
&&&&&*&@type&{Array}
&&&&stage&:&[],
&&&&&*&碰撞位置
&&&&&*&@type&{Array}
&&&&hited&:&[],
&&&&&*&重置舞台
&&&&init&:&function(){
&&&&&&&&var&i,&
&&&&&&&&&&&&n&=&800&*&600;
&&&&&&&&for(i&=&0;&i&&&n;&i&++){
&&&&&&&&&&&&Matrix.stage[i]&=&0;
&&&&drawAmmo&:&function(x,&y,&w,&h){
&&&&drawPlane&:&function(x,&y,&w,&h){
&&&&在绘制对象这一步中,我们已经把子弹形状跟飞机形状绘制到了Matrix.ammo和Matrix.plane数组中。当然对于后期扩展来说,我们也可以不断修改这两个数组,但在本次演示中,两者的形状已经固定了。
&&&&Matrix.drawAmmo的任务是把弹幕队列中的所有子弹绘制到Matrix.stage中:
drawAmmo&:&function(x,&y,&w,&h){
&&&&w&=&w&||&12;
&&&&h&=&h&||&12;
&&&&x&=&parseInt(x);
&&&&y&=&parseInt(y);
&&&&var&i&=&0,
&&&&&&&&j&=&0,
&&&&&&&&k&=&0,
&&&&&&&&l&=&0,
&&&&&&&&m&=&0,
&&&&&&&&n&=&0;
&&&&for(i&=&0;&i&&&w;&i&++){
&&&&&&&&for(j&=&0;&j&&&h;&j&++){
&&&&&&&&&&&&m&=&parseInt(j&*&w&+&i);
&&&&&&&&&&&&if(Matrix.ammo[m]&&&0){
&&&&&&&&&&&&&&&&n&=&parseInt((j&+&y)&*&800&+&(i&+&x));
&&&&&&&&&&&&&&&&Matrix.stage[n]&=&1;
&&&&&&&&&&&&}
&&&&Matrix.stage中,每一项表示一个像素点。设值为0时,这个像素点中没有内容,是虚空;值为1时,这个像素点中有子弹;值为2时,这个像素点中有子弹且有飞机;值为3时,这个像素点中有飞机。
&&&&在每一个时间片中,我们先调用Matrix.drawAmmo绘制所有的子弹,然后调用Matrix.drawPlane绘制自机。
&&&&那么,Matrix.drawPlane方法实际上包含了碰撞检测的流程:
drawPlane&:&function(x,&y,&w,&h){
&&&&w&=&w&||&48;
&&&&h&=&h&||&48;
&&&&x&=&parseInt(x);
&&&&y&=&parseInt(y);
&&&&var&i&=&0,
&&&&&&&&j&=&0,
&&&&&&&&k&=&0,
&&&&&&&&l&=&0,
&&&&&&&&m&=&0,
&&&&&&&&n&=&0,
&&&&&&&&hit&=&
&&&&Matrix.hited.length&=&0;
&&&&for(i&=&0;&i&&&w;&i&++){
&&&&&&&&for(j&=&0;&j&&&h;&j&++){
&&&&&&&&&&&&m&=&parseInt(j&*&w&+&i);
&&&&&&&&&&&&if(Matrix.plane[m]&&&0){
&&&&&&&&&&&&&&&&n&=&parseInt((j&+&y)&*&800&+&(i&+&x));
&&&&&&&&&&&&&&&&if(Matrix.stage[n]&==&1){
&&&&&&&&&&&&&&&&&&&&Matrix.stage[n]&=&2;
&&&&&&&&&&&&&&&&&&&&hit&=&
&&&&&&&&&&&&&&&&&&&&Matrix.hited.push(n);
&&&&&&&&&&&&&&&&}else{
&&&&&&&&&&&&&&&&&&&&Matrix.stage[n]&=&3;
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&}
&&&&return&
&&&&当有碰撞发生时,Matrix.drawPlane返回true。
&&&&接下来,定义一个plane对象来保存飞机的位置速度信息:
var&plane&=&{
&&&&x&:&0,
&&&&y&:&0,
&&&&speed&:&2
&&&&至此,我们已经可以着手写游戏的主线程了。
&&&&在主线程中,我们在stage画板中绘制实际的游戏舞台,包括实际的子弹和飞机;此外,我们还在hitck画板中绘制子弹、飞机的形状及碰撞状态,不妨用高对比的颜色来分别标示这些像素,譬如用红色、绿色、蓝色分别代表子弹、飞机、碰撞。
&&&&那么,基本的主线程如下:
function&run(){
&&&&Matrix.init();
&&&&ctx.fillStyle&=&'#000000';
&&&&ctx.fillRect(0,&0,&800,&600);
&&&&ctx.fillStyle&=&'#00ff00';
&&&&ctx.drawImage(cvs_plane,&plane.x,&plane.y);
&&&&var&i,&j;
&&&&for(i&=&0;&i&&&Queue.ammo.&i&++){
&&&&&&&&if(Queue.ammo[i]&!=&null&&&&!Queue.ammo[i].die){
&&&&&&&&&&&&Queue.ammo[i].move();
&&&&&&&&&&&&ctx.drawImage(cvs_ammo,&Queue.ammo[i].x,&Queue.ammo[i].y);
&&&&&&&&&&&&Matrix.drawAmmo(Queue.ammo[i].x,&Queue.ammo[i].y);
&&&&if(Matrix.drawPlane(plane.x,&plane.y)){
&&&&&&&&//碰撞发生时执行
&&&&//&绘制碰撞演示内容
&&&&var&ck_data&=&ctx_ck.createImageData(800,&600);
&&&&for(i&=&0,&j&=&0;&i&&&480000;&i++,&j&+=&4){
&&&&&&&&switch(Matrix.stage[i]){
&&&&&&&&&&&&case&1:
&&&&&&&&&&&&&&&&ck_data.data[j]&=&255;
&&&&&&&&&&&&&&&&ck_data.data[j&+&1]&=&0;
&&&&&&&&&&&&&&&&ck_data.data[j&+&2]&=&0;
&&&&&&&&&&&&&&&&ck_data.data[j&+&3]&=&255;
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&case&2:
&&&&&&&&&&&&&&&&ck_data.data[j]&=&0;
&&&&&&&&&&&&&&&&ck_data.data[j&+&1]&=&0;
&&&&&&&&&&&&&&&&ck_data.data[j&+&2]&=&255;
&&&&&&&&&&&&&&&&ck_data.data[j&+&3]&=&255;
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&case&3:
&&&&&&&&&&&&&&&&ck_data.data[j]&=&0;
&&&&&&&&&&&&&&&&ck_data.data[j&+&1]&=&255;
&&&&&&&&&&&&&&&&ck_data.data[j&+&2]&=&0;
&&&&&&&&&&&&&&&&ck_data.data[j&+&3]&=&255;
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&default:
&&&&&&&&&&&&&&&&ck_data.data[j]&=&0;
&&&&&&&&&&&&&&&&ck_data.data[j&+&1]&=&0;
&&&&&&&&&&&&&&&&ck_data.data[j&+&2]&=&0;
&&&&&&&&&&&&&&&&ck_data.data[j&+&3]&=&255;
&&&&&&&&&&&&&&&&
&&&&ctx_ck.putImageData(ck_data,&0,&0);
&&&&setTimeout(function(){run()},&20);
&&&&作为一个游戏,我们还需要记录游戏状态,譬如是否暂停,来引入一个对象:
var&Game&=&{
&&&&playing&:&true
&&&&再次,我们需要一个对象来记录键盘状态,以便让玩家操作飞机移动,在此我们定义移动的方向键为WASD:
var&Keyboard&=&{
&&&&//&上下左右的键盘码
&&&&UP&&&&:&87,
&&&&DOWN&&:&83,
&&&&LEFT&&:&65,
&&&&RIGHT&:&68,
&&&&//&上下左右四个键是否被按下
&&&&up&&&&:&false,
&&&&down&&:&false,
&&&&left&&:&false,
&&&&right&:&false
&&&&然后,在主线程run函数中加入如下语句对游戏状态及键盘进行响应:
if(!Game.playing){
&&&&setTimeout(function(){run()},&20);
if(Keyboard.up&&&&&&&plane.y&&&0){
&&&&plane.y&-=&plane.
if(Keyboard.down&&&&&plane.y&&&600){
&&&&plane.y&+=&plane.
if(Keyboard.left&&&&&plane.x&&&0){
&&&&plane.x&-=&plane.
if(Keyboard.right&&&&plane.x&&&800){
&&&&plane.x&+=&plane.
&&&&要让游戏在飞机与子弹发生碰撞时暂停,在run对Matrix.drawPlane的调用中作修改:
if(Matrix.drawPlane(plane.x,&plane.y)){
&&&&//碰撞发生时执行
&&&&Game.playing&=&
&&&&然后我们需要产生子弹——定义两种子弹产生的流程:一是定时生成螺旋散开的弹幕,二是鼠标点击画面后在点击处生成均匀散开的弹幕。
function&test_ammo(){
&&&&var&rca&=&new&RoundCircleAmmo(Math.random()&*&400&+&100,&Math.random()&*&300&+&100,&512);
&&&&rca.queue_delay(10);
&&&&setTimeout(function(){test_ammo()},&8000);
test_ammo();
& & 这里会每八秒钟生成一个随机位置出现、包含512颗子弹的螺旋弹幕。
&&&&要让鼠标点击生成弹幕,先来引入一个Mouse对象来记录鼠标状态:
var&Mouse&=&{
&&&&downX&:&0,
&&&&downY&:&0
&&&&然后引入两个方法用于判断鼠标点击位置是否在画板范围内以及相对画板的偏移:
&*&@type&{Object}
var&Util&=&{
&&&&&*&是否在画板范围内
&&&&&*&@param&&{canvas}&&&canvas&
&&&&&*&@param&&{float}&&&&x&&&&&&
&&&&&*&@param&&{float}&&&&y&&&&&&
&&&&&*&@return&{bool}&&&&&
&&&&canvasInScope&:&function(canvas,&x,&y){
&&&&&&&&x&=&x&||&Mouse.downX;
&&&&&&&&y&=&y&||&Mouse.downY;
&&&&&&&&return&(
&&&&&&&&&&&&x&&&canvas.offsetLeft&&&&
&&&&&&&&&&&&x&&&canvas.offsetLeft&+&canvas.clientWidth&&&
&&&&&&&&&&&&y&&&canvas.offsetTop&&&
&&&&&&&&&&&&y&&&canvas.offsetTop&+&canvas.clientHeight
&&&&&&&&);
&&&&&*&位置在画板上的坐标偏移
&&&&&*&@param&&{canvas}&canvas&
&&&&&*&@param&&{float}&&x&&&&&&
&&&&&*&@param&&{float}&&y&&&&&&
&&&&&*&@return&{Vect}&&&&&&&&
&&&&offsetOnCanvas&:&function(canvas,&x,&y){
&&&&&&&&x&=&x&||&Mouse.downX;
&&&&&&&&y&=&y&||&Mouse.downY;
&&&&&&&&var&ratioX&=&canvas.width&&/&canvas.clientW
&&&&&&&&var&ratioY&=&canvas.height&/&canvas.clientH
&&&&&&&&var&offsetX&=&(x&-&canvas.offsetLeft)&*&ratioX;
&&&&&&&&var&offsetY&=&(y&-&canvas.offsetTop)&&*&ratioY;
&&&&&&&&return&new&Vect(offsetX,&offsetY);
Vect&=&function(x,&y){
&&&&this.x&=&x&||&0;
&&&&this.y&=&y&||&0;
&&&&然后可以给window添加事件了:
window.onkeydown&=&function(e){
&&&&switch(e.keyCode){
&&&&&&&&case&Keyboard.UP:
&&&&&&&&&&&&Keyboard.up&&&&=&
&&&&&&&&&&&&
&&&&&&&&case&Keyboard.DOWN:
&&&&&&&&&&&&Keyboard.down&&=&
&&&&&&&&&&&&
&&&&&&&&case&Keyboard.LEFT:
&&&&&&&&&&&&Keyboard.left&&=&true
&&&&&&&&&&&&
&&&&&&&&case&Keyboard.RIGHT:
&&&&&&&&&&&&Keyboard.right&=&
&&&&&&&&&&&&
&&&&&&&&default:
&&&&&&&&&&&&
window.onkeyup&=&function(e){
&&&&switch(e.keyCode){
&&&&&&&&case&Keyboard.UP:
&&&&&&&&&&&&Keyboard.up&&&&=&
&&&&&&&&&&&&
&&&&&&&&case&Keyboard.DOWN:
&&&&&&&&&&&&Keyboard.down&&=&
&&&&&&&&&&&&
&&&&&&&&case&Keyboard.LEFT:
&&&&&&&&&&&&Keyboard.left&&=&
&&&&&&&&&&&&
&&&&&&&&case&Keyboard.RIGHT:
&&&&&&&&&&&&Keyboard.right&=&
&&&&&&&&&&&&
&&&&&&&&default:
&&&&&&&&&&&&
window.onclick&=&function(e){
&&&&Game.playing&=&
&&&&Mouse.downX&=&e.x&||&e.clientX;
&&&&Mouse.downY&=&e.y&||&e.clientY;
&&&&if(Util.canvasInScope(cvs)){
&&&&&&&&var&ammo2v&=&Util.offsetOnCanvas(cvs);
&&&&&&&&new&RoundDirectAmmo(ammo2v.x,&ammo2v.y).queue();
&&&&if(Util.canvasInScope(cvs_ck)){
&&&&&&&&var&ammo2v&=&Util.offsetOnCanvas(cvs_ck);
&&&&&&&&new&RoundDirectAmmo(ammo2v.x,&ammo2v.y).queue();
&&&&至此,程序算是完成了。
&&&&从左到右依次为:stage、hitck、plane、ammo
*、运行演示:
*、完整代码:
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读}

我要回帖

更多关于 弹幕网 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信