怎样制作网页游戏
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎样制作网页游戏相关的知识,希望对你有一定的参考价值。
很多人想投身游戏行业,成为真正的游戏制作人。但是他们对游戏的制作过程,和各个职位的职能都是比较陌生的。对网页游戏开发也不够了解,游戏到底是怎么制作出来的呢?\x0d\x0a\x0d\x0a网页游戏开发的程序构成分为三大部分:第一是数据流程。第二是美术。第三是程序。\x0d\x0a1、数据流程\x0d\x0a数据流程其中,数据流程包括了功能。也只有在功能中才能体现数据流程。\x0d\x0a比如最简单的卖买产品。要实现这个功能,那么需要有产品基础表、产品详细表、商店表、背包表。如果扩展性更强,相应的双表是少不不了的。\x0d\x0a表的问题都简单了,关键是这个物品有什么用,这样物品的来源,一大堆数据,物品的走向,又是一大堆数据。最后,这些数据得绕成一个圈。绕圈是一件困难的事情,特别是功能和道具多了起来的时候。难度是2的n次方。\x0d\x0a2、美术\x0d\x0aUI:简洁漂亮的界面总会有好处。\x0d\x0a小图标:道具,地图,装备,一类至少10个吧?大体上百把个是需要的。\x0d\x0a3、程序分5个部分\x0d\x0a数据库:一大堆基础数据表和详细数据表。基础数据表:比如等级1到等级100的用户的属性初始值。详细数据表:每个用户的具体属性。\x0d\x0a功能页面、功能函数。主要就是数据存取,判断,数据走向。\x0d\x0aajax函数:(可选)某些需要伪即时的功能要用到。\x0d\x0ajavascript函数:(可选)模拟客户端的数据计算。也就是webgame的与时间相关的数据。分为两部分。一部分是真实数据,是由服务器端的定时器计算的。另一部分是只有初始值,客户端显示用的。不需要即时同步,仅仅需要模拟同步就行。\x0d\x0a服务器定时器:(C语言或自己设定服务器)定时循环执行某一段代码。而这段代码主要是根据数据库的数据进行更新。这个可以找个C语言程序员来做。对于C语言程序员来讲,这个功能是相当的简单。当然,具体的处理数据的判断和操作数据库,需要你自己写。让C语言程序员给你段标准代码就行了。完全支持sql语句的。\x0d\x0a当然在网页游戏开发前,还要组织相关的专业人才,制作一款网络游戏需要的最核心人才是原画、2D、3D、程序设计、策划等这些方面的人才是必不可少的,因此,要开发一个网页游戏除了要程序员以外,千万不要忘了准备以上人才。 参考技术A 今天给各位详细介绍关于“网页游戏怎么制作”的核心内容以及“怎么开发小游戏app”的相关知识,希望对各位有所帮助。什么是小游戏?
首先为大家介绍一下什么是小游戏:小游戏特指微信小游戏,是小程序的一个子类目,可在微信内被便捷地获取和传播,即点即玩,具备出色的用户体验。在开发的视角来看,小游戏是一个基于Canvas/WebGL + 微信社交开放能力的新平台。在框架上看分为三层,是一个典型的分层架构。微信中有一个小游戏的Runtime去运行小游戏,而OS本身可能会涉及到不同类的设备。
如果放大小游戏的Runtime可以看到很多的细节,第一就是游戏逻辑,也就是与平台无关的游戏逻辑的开发。第二部分是游戏引擎,大部分会用到一些引擎的工作流、一些各种系统封装好的高层的API。第三部分是weapp,小游戏的框架是参考了webview的框架,但其实它的底层不是webview,而是webview精简优化过的平台,小游戏有的只是与核心相关的一些渲染的API。这里的weapp-adaper是把小游戏的能力适配到与webview更接近的环境,让更上层的游戏或引擎本身能够更快速地集入到平台中。
小游戏Runtime
微信的Runtime对外暴露的都是微信的API,所有的能力都是通过微信API发布出去的。底层最基本的能力是渲染相关的,即Canvas 2d和WebGL。其他一些微信相关的能力是另外一部,所以小游戏在架构上和小程序是有差别的,但用户体验起来没有太大的区别。小游戏是没有页面概念的,在实现上也不完全是webview,其中不必要的部分已经被去掉了。
总的来说小游戏的入口为game.js,游戏可以利用底层的一些能力将游戏的整个界面绘制出来。配置文件为game.json主要用来配置小游戏是横屏还是竖屏,小游戏的全局对象game Gobal类似于webview中的window对象,同时支持javascript语言。但是小游戏有一个重要的一个限制是禁止动态执行代码,开发者必须先提交审核,在审核通过后才可以上架给普通用户。另外,小游戏包括引擎的代码量比较大,所以限制大小比小程序要大,首包限制大小为4M。
下面来说一下Webview Adapter,它的初衷是为了让游戏开发者更好地熟悉我们的平台,所以我们的平台在能力上会尽可能地与webview做一些适配,其实这个适配也是很简单的一层。比如说我们在浏览器里面使用image对象创建一个图片,而在小游戏里是通过wx.createimage来创建的,在代码中需要做一个简单的适配。比如说Canvas、Document都是在Adapter中实现的,大家可以研究链接中的代码。其中有一些优化的版本,之后官方不会继续维系这个Adapter,因为我们会更专注于底层能力的建设。如果大家已经比较熟悉这个平台的话,就会比较容易地开发游戏。比如Document这个对象在小游戏框架本身中跟普通对象是没有区别的,它是Adapter做的一个简单的适配。
小游戏能力概览
小游戏的社交开放能力现在已经对外开放了。其中最重要的一个能力是开放域,将微信的好友关系列开放出去,给开发者一起使用,但也存在着一些限制。因为小游戏去中心化的特点,分享这一部分也是非常重要的,开发者要考虑如何将这个能力利用起来。在代码方面,因为首包限制是4兆,但部分小游戏的代码量可能比较大。我们最近也在规划一个分包的能力,异步加载代码,但这个代码是一定要经过我们审核的。
龙源科技是杭州市IT行业的领先企业。服务类别涵盖Internet服务领域,主要包括网站建设,小程序商城,小程序定制开发,游戏开发,APP定制开发和推广服务。 龙源科技致力于为大多数需求者解决各种实际需求问题,并提供全方位的创意服务
如何开发一款小游戏?
那么如何开发一款小游戏?因为我本人也只是开发过一些简单的游戏,并不是专业进行游戏开发,所以接下来我会更多地介绍一下如何利用微信的能力来开发小游戏。
选择小游戏引擎
首先在开发游戏时要选择引擎,我们与引擎商也有着比较密切的合作,开发小游戏的引擎一定要是适配的。比如在底层,一开始引擎可能只支持原生的游戏,在微信小游戏上就要做一些适配,依赖浏览器特有的能力。Cocos Creator、Egret Engine、LayaAir Engine这三个引擎已经支持了小游戏的开发,网上也有相应的文章介绍如何发布到微信小游戏的平台。
设备/环境适配
有关设备管理的适配,小游戏会有API提供获取屏幕的宽高、设备像素比等能力。在小游戏开发完成后,在开发者工具也可以发起真机测试的请求,微信提供了不同设备的测试集群,帮助开发者提前去发现问题。基础库提供的wx API本身是一个不断迭代更新的过程,对于使用了新能力的小游戏,需要做低版本兼容。比如在检测到不支持新 API的低版本允许有损服务用户。同时,如果某个低版本的用户占比较少,可以考虑在管理后台直接配置小游戏要求的基础库最低版本,当然也意味着这一部分用户在接触到这个小游戏时,微信客户端会弹出一个要求用户更新到微信新版本才可使用该小游戏的提示,如果不更新可能就会失去这个用户。
设备/环境适配
微信登录
小游戏的登陆过程与小程序类似,需要用户自定义登录状态。appsecret/session_key代表的是小游戏开发者和微信平台之间的一种信任约定,比如支付、上报托管数据,平台方需要验证 access_token,和用户相关的还要验证session_key的签名,才能保证请求来自于小游戏开发者或用户。access_token是一种应用态的 access_token,与用户无关,需要保证全局维护一份,应该有一个中控的模块去保证 access_token有效,同时在有效期内直接使用本地 cache的 access_token,而不是每次使用都去生成新的 access_token,否则可能遇到调用频率限制的错误而影响服务。切记 appsecret/session_key不要放到前端代码中去,否则可能会被恶意利用从而损坏小游戏开发者或用户的权益。
微信登录
缓存
缓存类型包括数据缓存和文件缓存两种。数据缓存即key-value存储,适合结构化类型的小数据存储,上限为 10MB。文件缓存提供了一个完整的文件系统 API,包括目录 /文件的增删改读,适合针对经常使用的网络资源做本地缓存,上限是50MB。
和浏览器不同的是,微信只提供了基本的存储管理能力,并不对存储什么以及存储满时删除什么做一些操作。开发者自行灵活定义缓存及淘汰策略,比如对经常访问的资源存储到文件系统以及在文件存储满时,清理一些最近不常访问的文件。
缓存
开放数据域
我们来说一下开发数据域,也就是在保护用户隐私的前提下把用户的数据开放给小游戏。这是一个封闭、独立的javascript作用域,开放数据域是一个独立的目录,其入口文件是index.js。目前的限制在于仅支持2d渲染模式,数据只进不出。比如说一个排行榜,它的目的肯定是用来给用户看的。
我们简单看一下它的实现方案,左边是主域。用户拿到这些数据后实现排行榜其实也是一个Canvas。它的区别在于Canvas不能把数据取出来,无法分析其中的数据是什么。主域里面有一个Canvas,在微信里上屏Canvas跟屏幕关联,后面都是离线的Canvas,离线的Canvas可以自己根据需求使用的。一旦开放数据以后,上屏Canvas不能把里面的数据取出来,下一个Canvas也不能取出来,保证了数据的安全性。
开放数据域
因为我们的数据在开发数据域中,用户没有办法进行开发。所以要求开发者在开发时将需要的数据托管到我们这里,与用户关联起来。这样就可以在开发数据域里面取到相关数据,其应用场景有好友排行、群排行榜、超越好友提示等。用户在输入的时候,重复用户的所有操作,在上屏的Canvas和离屏的Canvas上就得到了用户的所有输入,不会有开放数据渗透进去。
开放数据域
分享
如果用户在游戏中达到了很高的分数,可以与好友PK一下。在自定义转发的窗口,标题和图片都可以自定义。但是现在有很多小游戏非常骚扰用户,他们做了很多一定需要分享,才能允许玩游戏的设定。这是大家需要思考的部分,如何既不影响用户的体验,又能够促进小游戏的互动,在这里需要找到一个合适的平衡点。同时,在分享数据后将小游戏与这个群聊关联起来,我们就可以看到一个小游戏平台。
分享
支付
小游戏是支持虚拟支付的,但目前仅适用于安卓系统中。且它的方式目前只有一种,即货币托管的方式。主要分为两个流程,一是用户花钱购买游戏币,这与游戏的服务端是没有关系的。发起支付时微信客户端会生成一个订单,让用户确认支付,这是异步的。平台负责把用户RMB兑换成对应的游戏币,存储到用户对应的游戏帐号上。二是使用游戏币购买道具,开发者可以扣除对应的游戏币,给用户发放游戏内道具,扣除游戏币的过程需要有一定的事务机制,保证在网络异常的情况下交易正常。扣除游戏币的接口支持根据订单ID去重,意味着在网络超时等情况下,开发者可用同样的订单ID去重试扣除,直至返回明确的响应。
支付
性能
小游戏常见的性能问题,一般是内存造成的。如果内存占用太多会被微信客户端主动关闭,因此开发者在用户游戏过程中要及时释放不再使用的内存,特别是Canvas和Image类的大型对象,同时可以主动调用wx.triggerGC触发底层回收对应资源。对于和游戏逻辑相对独立的工作,可以考虑在worker中去实现,小游戏提供了独立的worker线程执行js逻辑的能力。
性能
版本更新机制
小游戏有热启动和冷启动之分,冷启动是指内存中无该小游戏的运行实例的情况下,启动小游戏的过程;热启动是指小游戏的运行实例在内存中还存在,只是暂时切换到了后台,这时用户再次触发小游戏回到前台的过程。在如果用户点击启动之后,游戏运行时会加载出来这款游戏。在点击右上角的菜单时,按钮只是挂后台,在一定的时间内再启动时,它会立即恢复,这时内存将会释放。
小游戏会在冷启动时检查小游戏的版本,如有新版本,在下载回本地后,下一次冷启动即可使用最新版。当然,我们也提供了 API可以供开发者决策在有版本可用时,是否需要强制更新,应用最新的版本。
版本更新机制
运维
管理端提供了发布、回滚、停服等能力,开发者可以充分利用平台的能力。比如在后台操作中,js可能会报错。脚本错误主要由运行过程中未捕获的异常触发,该类异常可能会导致用户小游戏前端的js逻辑暂停执行。同时,平台也提供了完善的数据分析服务,可以通过小游戏使用助手进行数据分析。 参考技术B 厄。。。LZ的这个问题也太牛了,
建议,一个成功web游戏需要一个开发团队,不是一个人能够搞定的~~如果真的像GM02那么牛的人,需要有娴熟的web技术。
想学习web游戏的开发,最好能够找到一个游戏培训公司去学习,并且需要有深厚的计算机系功底~~
厄。。。拿MYJ来说,是java框架,所以LZ找java软件就可以了,然后慢慢摸索各种编程语言、美工、页面制作,数据库编写、游戏运营及管理,这一切完成后,基本上就成大师了~~
怎么用html5制作简单的大球吃小球的游戏
<html><head>
<title>
大球吃小球by大奔
</title>
<script type="text/javascript" src="src/jscex.js"></script>
<script type="text/javascript" src="src/jscex-parser.js"></script>
<script type="text/javascript" src="src/jscex-jit.js"></script>
<script type="text/javascript" src="src/jscex-builderbase.js"></script>
<script type="text/javascript" src="src/jscex-async.js"></script>
<script type="text/javascript" src="src/jscex-async-powerpack.js"></script>
</head>
<body>
<canvas id="myCanvas" width="480" height="300" style="border:1px solid #c3c3c3">
你的浏览器改换了
</canvas>
<script type="text/javascript">
var d=document.getElementByIdx_x("myCanvas");
var cxt=d.getContext("2d");
var balls=[];
//这里为了获得随机数的向量
function getRandom(a,b)
return (a+Math.floor(Math.random()*(b-a+1)))
//这里对向量进行赋值
var Vector2=function(a,b)
this.x=a||0;
this.y=b||0;
;
//这里需要注意,对象的默认方法在这里写不会管用。例如sub
Vector2.prototype=//写对象的构造函数
constructor:Vector2,
multiplyScalar:function(s)
this.x*=s;
this.y*=s;
return this;
,
divideScalar:function(s)
if(s)
this.x/=s;
this.y/=s;
else
this.set(0,0);
return this;
,
dot:function(v)
return this.x*v.x+this.y*v.y;//即两个向量相乘
,
lengthSq:function()
return this.x*this.x+this.y*this.y;
,
length:function()
return Math.sqrt(this.lengthSq());
,
normalize:function()
//这里得到的是单位向量,按照google的定义,单位的向量是, //(a,b)则a*a+b*b=1;
return this.divideScalar(this.length());
,
reflectionSelf:function(v)
//这里得到的是反射向量。公式参考这个网址。
//blog.physwf.com/?p=42
var nv=v.normalize();
this.sub(nv.multiplyScalar(2*this.dot(nv)));
,
distanceToSquared:function(v)//求出两点之间的距离
var dx=this.x-v.x,
dy=this.y-v.y;
return dx*dx+dy*dy;
;
Vector2.sub=function(v1,v2)//这里重写sub方法
return new Vector2(v1.x-v2.x,v1.y-v2.y);
;
for(var i=0;i<40;i++)//初始化40个小球
var ball=
position:new Vector2(getRandom(20,600),getRandom(20,600)),
r:getRandom(6,20),
speed:new Vector2(getRandom(-200,200),getRandom(-200,200)),
mass:1,//这是小球的质量
restitution:1//这是弹性系数
;
balls.push(ball);
var filterBalls=[];
for(var i=0;i<balls.length;i++)
var overlapCount=0;
for(var j=i+1;j<balls.length;j++)//两个两个比较防止重复,而且初始化的位置不能重 //叠,否则符合碰撞的条件。去掉这个判断以后,效果不太显著,可以多放些球试试。
var distance=balls[i].position.distanceToSquared(balls[j].position);
var l=balls[i].r+balls[j].r;
if(distance<=(l*l))
overlapCount++;
if(overlapCount===0)
filterBalls.push(balls[i]);
balls=filterBalls;//这里可以去掉试试。
cxt.fillStyle="#030303";
cxt.fillRect(0,0,d.width,d.height);
function init()
cxt.fillStyle="#fff";
for(i in balls)
cxt.beginPath();
cxt.arc(balls[i].position.x,balls[i].position.y,balls[i].r,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();
init();
var cyc=20;
var moveAsync2=eval_r(Jscex.compile("async",function()
var tag=0;
while(true)
try
cxt.fillStyle="rgba(0,0,0,3)";
cxt.fillRect(0,0,d.width,d.height);
cxt.fillStyle="#fff";
for(var i=0;i<balls.length;i++)
//这里是为了两个小球比较会重复所以,每次比较都是i与i+1 //开始相比较
for(var j=i+1;j<balls.length;j++)
collisionSolver(balls[i],balls[j]);
for(i in balls)
cxt.beginPath();
cxt.arc(balls[i].position.x,balls[i].position.y,balls[i].r,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();
if(balls[i].r+balls[i].position.x>d.width)
//如果小球x轴跑出了画布的范围
balls[i].position.x=d.width-balls[i].r;
//小球的位置返回到画布的边缘位置
balls[i].speed.x*=-1;
//同时x轴的方向变为反方向
if(balls[i].position.x<balls[i].r)
//如果小球的x坐标小于小球的半径。肯定画不成完整的圆了,所以要归位
balls[i].position.x=balls[i].r;
balls[i].speed.x*=-1; if(balls[i].r+balls[i].position.y>d.height)//同理y轴
balls[i].position.y=d.height-balls[i].r;
balls[i].speed.y*=-1;
if(balls[i].position.y<balls[i].r)
balls[i].position.y=balls[i].r;
balls[i].speed.y*=-1;
balls[i].position.x+=balls[i].speed.x*cyc/1000;
//小球的x轴不断按照速度增大
balls[i].position.y+=balls[i].speed.y*cyc/1000;
catch(e)
alert(e);
$await(Jscex.Async.sleep(cyc));
));
function collisionSolver(bodyA,bodyB)//判断小球发生碰撞的时候的变化。
var vB=bodyB.speed;
var vA=bodyA.speed;
var l=bodyA.r+bodyB.r;
var distSqr=bodyA.position.distanceToSquared(bodyB.position);
var isTouching=distSqr<=l*l? true:false;
//判断两圆心之间的距离如果小于两半径之和的平方。则为true
var normal=Vector2.sub(bodyB.position,bodyA.position).normalize();
//请看上面的解释,所以得到的是B相对于A的单位向量。
var ratio=bodyA.r/l;//这是一个比例
var contactPoint=new Vector2();
//根据平行线切割的三角形,两边的边的比例相等,
contactPoint.x=bodyA.position.x+(bodyB.position.x-bodyA.position.x)*ratio;
contactPoint.y=bodyA.position.y+(bodyB.position.y-bodyA.position.y)*ratio;
var rA=Vector2.sub(contactPoint,bodyA.position);
//这两个地方没有找到是哪里用到的?????
var rB=Vector2.sub(contactPoint,bodyB.position);
var vrn=Vector2.sub(vA,vB).dot(normal);
//这里得到的是Va相对于vB的速度向量与两球的圆心的单位向量相乘。
///a*b=|a|*|b|*cos@.所以如果vrn大于零,则夹角小于90度。
if(isTouching&&vrn>0)
//这里是冲量公式的一个部分
var normalMass=1/(1/bodyA.mass+1/bodyB.mass);
var restitution=(bodyA.restitution+bodyB.restitution)/2;
var normalImpulse=-normalMass*vrn*(1+restitution);
bodyA.speed.x+=normalImpulse*normal.x/bodyA.mass;
//这里总之是一个大球一个小球,所以速度一个增大一个减小
bodyA.speed.y+=normalImpulse*normal.y/bodyA.mass;
bodyB.speed.x-=normalImpulse*normal.x/bodyB.mass;
bodyB.speed.y-=normalImpulse*normal.y/bodyB.mass;
moveAsync2().start();
</script>
</body>
</html> 参考技术A <html>
<head>
<title>
大球吃小球by大奔
</title>
<script type="text/javascript" src="src/jscex.js"></script>
<script type="text/javascript" src="src/jscex-parser.js"></script>
<script type="text/javascript" src="src/jscex-jit.js"></script>
<script type="text/javascript" src="src/jscex-builderbase.js"></script>
<script type="text/javascript" src="src/jscex-async.js"></script>
<script type="text/javascript" src="src/jscex-async-powerpack.js"></script>
</head>
<body>
<canvas id="myCanvas" width="480" height="300" style="border:1px solid #c3c3c3">
你的浏览器改换了
</canvas>
<script type="text/javascript">
var d=document.getElementByIdx_x("myCanvas");
var cxt=d.getContext("2d");
var balls=[];
//这里为了获得随机数的向量
function getRandom(a,b)
return (a+Math.floor(Math.random()*(b-a+1)))
//这里对向量进行赋值
var Vector2=function(a,b)
this.x=a||0;
this.y=b||0;
;
//这里需要注意,对象的默认方法在这里写不会管用。例如sub
Vector2.prototype=//写对象的构造函数
constructor:Vector2,
multiplyScalar:function(s)
this.x*=s;
this.y*=s;
return this;
,
divideScalar:function(s)
if(s)
this.x/=s;
this.y/=s;
else
this.set(0,0);
return this;
,
dot:function(v)
return this.x*v.x+this.y*v.y;//即两个向量相乘
,
lengthSq:function()
return this.x*this.x+this.y*this.y;
,
length:function()
return Math.sqrt(this.lengthSq());
,
normalize:function()
//这里得到的是单位向量,按照google的定义,单位的向量是, //(a,b)则a*a+b*b=1;
return this.divideScalar(this.length());
,
reflectionSelf:function(v)
//这里得到的是反射向量。公式参考这个网址。
//blog.physwf.com/?p=42
var nv=v.normalize();
this.sub(nv.multiplyScalar(2*this.dot(nv)));
,
distanceToSquared:function(v)//求出两点之间的距离
var dx=this.x-v.x,
dy=this.y-v.y;
return dx*dx+dy*dy;
;
Vector2.sub=function(v1,v2)//这里重写sub方法
return new Vector2(v1.x-v2.x,v1.y-v2.y);
;
for(var i=0;i<40;i++)//初始化40个小球
var ball=
position:new Vector2(getRandom(20,600),getRandom(20,600)),
r:getRandom(6,20),
speed:new Vector2(getRandom(-200,200),getRandom(-200,200)),
mass:1,//这是小球的质量
restitution:1//这是弹性系数
;
balls.push(ball);
var filterBalls=[];
for(var i=0;i<balls.length;i++)
var overlapCount=0;
for(var j=i+1;j<balls.length;j++)//两个两个比较防止重复,而且初始化的位置不能重 //叠,否则符合碰撞的条件。去掉这个判断以后,效果不太显著,可以多放些球试试。
var distance=balls[i].position.distanceToSquared(balls[j].position);
var l=balls[i].r+balls[j].r;
if(distance<=(l*l))
overlapCount++;
if(overlapCount===0)
filterBalls.push(balls[i]);
balls=filterBalls;//这里可以去掉试试。
cxt.fillStyle="#030303";
cxt.fillRect(0,0,d.width,d.height);
function init()
cxt.fillStyle="#fff";
for(i in balls)
cxt.beginPath();
cxt.arc(balls[i].position.x,balls[i].position.y,balls[i].r,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();
init();
var cyc=20;
var moveAsync2=eval_r(Jscex.compile("async",function()
var tag=0;
while(true)
try
cxt.fillStyle="rgba(0,0,0,3)";
cxt.fillRect(0,0,d.width,d.height);
cxt.fillStyle="#fff";
for(var i=0;i<balls.length;i++)
//这里是为了两个小球比较会重复所以,每次比较都是i与i+1 //开始相比较
for(var j=i+1;j<balls.length;j++)
collisionSolver(balls[i],balls[j]);
for(i in balls)
cxt.beginPath();
cxt.arc(balls[i].position.x,balls[i].position.y,balls[i].r,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();
if(balls[i].r+balls[i].position.x>d.width)
//如果小球x轴跑出了画布的范围
balls[i].position.x=d.width-balls[i].r;
//小球的位置返回到画布的边缘位置
balls[i].speed.x*=-1;
//同时x轴的方向变为反方向
if(balls[i].position.x<balls[i].r)
//如果小球的x坐标小于小球的半径。肯定画不成完整的圆了,所以要归位
balls[i].position.x=balls[i].r;
balls[i].speed.x*=-1; if(balls[i].r+balls[i].position.y>d.height)//同理y轴
balls[i].position.y=d.height-balls[i].r;
balls[i].speed.y*=-1;
if(balls[i].position.y<balls[i].r)
balls[i].position.y=balls[i].r;
balls[i].speed.y*=-1;
balls[i].position.x+=balls[i].speed.x*cyc/1000;
//小球的x轴不断按照速度增大
balls[i].position.y+=balls[i].speed.y*cyc/1000;
catch(e)
alert(e);
$await(Jscex.Async.sleep(cyc));
));
function collisionSolver(bodyA,bodyB)//判断小球发生碰撞的时候的变化。
var vB=bodyB.speed;
var vA=bodyA.speed;
var l=bodyA.r+bodyB.r;
var distSqr=bodyA.position.distanceToSquared(bodyB.position);
var isTouching=distSqr<=l*l? true:false;
//判断两圆心之间的距离如果小于两半径之和的平方。则为true
var normal=Vector2.sub(bodyB.position,bodyA.position).normalize();
//请看上面的解释,所以得到的是B相对于A的单位向量。
var ratio=bodyA.r/l;//这是一个比例
var contactPoint=new Vector2();
//根据平行线切割的三角形,两边的边的比例相等,
contactPoint.x=bodyA.position.x+(bodyB.position.x-bodyA.position.x)*ratio;
contactPoint.y=bodyA.position.y+(bodyB.position.y-bodyA.position.y)*ratio;
var rA=Vector2.sub(contactPoint,bodyA.position);
//这两个地方没有找到是哪里用到的?????
var rB=Vector2.sub(contactPoint,bodyB.position);
var vrn=Vector2.sub(vA,vB).dot(normal);
//这里得到的是Va相对于vB的速度向量与两球的圆心的单位向量相乘。
///a*b=|a|*|b|*cos@.所以如果vrn大于零,则夹角小于90度。
if(isTouching&&vrn>0)
//这里是冲量公式的一个部分
var normalMass=1/(1/bodyA.mass+1/bodyB.mass);
var restitution=(bodyA.restitution+bodyB.restitution)/2;
var normalImpulse=-normalMass*vrn*(1+restitution);
bodyA.speed.x+=normalImpulse*normal.x/bodyA.mass;
//这里总之是一个大球一个小球,所以速度一个增大一个减小
bodyA.speed.y+=normalImpulse*normal.y/bodyA.mass;
bodyB.speed.x-=normalImpulse*normal.x/bodyB.mass;
bodyB.speed.y-=normalImpulse*normal.y/bodyB.mass;
moveAsync2().start();
</script>
</body>
</html>本回答被提问者采纳
以上是关于怎样制作网页游戏的主要内容,如果未能解决你的问题,请参考以下文章