使用Box2dWeb模拟飞行箭矢
[HTML5]使用Box2dWeb模拟飞行箭矢
版权声明:本文为博主原创文章,未经博主允许不得转载。
Box2d是一个2D游戏物理引擎,由Erin Catto开发,于2007年发布。很多2D游戏都用过Box2d,其中最有名的自然是愤怒的小鸟。Box2d本身是C++编写,但在不同平台都有它的衍生版本,像Flash版的Box2dFlash,JS版的Box2dJS和Box2dWeb。最近偶然看到一篇使用Box2dFlash模拟箭矢飞行效果的文章:
http://www.emanueleferonato.com/2012/12/10/flying-arrows-simulation-with-box2d/
很有意思,想尝试使用下Box2d。
之前从没接触过Flash,选择JS版的Box2d,而Box2dJS已经很久没更新,所以使用Box2dWeb重写箭矢飞行效果。
网上有不少Box2d教程,不过介绍其应用的多些。对于Box2d基本概念和原理,推荐阿蕉的博客,他将Box2d C++的系列教程译成中文。虽然C++和JS不同,但是Box2d原理是相通的,可以参考。
http://blog.csdn.net/wen294299195/article/category/1227604
首先下载Box2dWeb
https://code.google.com/p/box2dweb/downloads/list
压缩包里只有四个文件,这里只需要Box2dWeb-2.1.a.3.min.js(也可以用Box2dWeb-2.1.a.3.js,方便了解Box2DWeb的各个函数)。
按照下面的目录结构创建各个文件即可:
|-js/
| |-Box2dWeb-2.1.a.3.min.js
| |-game.js
|-arrow.html
编辑arrow.html,引用javascript文件并创建一个canvas标签,代码如下:
- <!DOCTYPE HTML>
- <html>
- <head>
- <title>Box2DWeb Test</title>
- <scripttypescripttype="text/javascript"src="js/Box2dWeb-2.1.a.3.min.js"></script>
- <scripttypescripttype="text/javascript" src="js/game.js"></script>
- </head>
- <bodyonloadbodyonload="init();">
- <canvasidcanvasid="canvas" width="640" height="480"style="background-color:#333333;"></canvas>
- </body>
- </html>
接下来编辑game.js。从arrow.html中可以看到,页面载入后调用init方法模拟整个过程,添加下面的代码:
- function init() {
- // Commen code for usingBox2D object.
- var b2Vec2 =Box2D.Common.Math.b2Vec2;
- var b2AABB =Box2D.Collision.b2AABB;
- var b2BodyDef =Box2D.Dynamics.b2BodyDef;
- var b2Body =Box2D.Dynamics.b2Body;
- varb2FixtureDef = Box2D.Dynamics.b2FixtureDef;
- var b2Fixture =Box2D.Dynamics.b2Fixture;
- var b2World =Box2D.Dynamics.b2World;
- varb2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape;
- var b2DebugDraw =Box2D.Dynamics.b2DebugDraw;
- /* 下文添加 */
- };
以上代码是为了方便使用Box2d中的对象。接着就是设置全局属性,像canvas的大小、Box2d的世界参数、鼠标消息响应方法等。
- // Get canvas fordrawing.
- var canvas =document.getElementById("canvas");
- var canvasPosition =getElementPosition(canvas);
- var context =canvas.getContext("2d");
- // World constants.
- var worldScale = 30;
- var dragConstant=0.05;
- var dampingConstant = 2;
- var world = newb2World(new b2Vec2(0, 10),true);
- document.addEventListener("mousedown",onMouseDown);
- debugDraw();
- window.setInterval(update,1000/60);
设置好Box2d的世界之后就可以放置各种模型。接下来的代码创建四面墙壁来封闭区域:
- // Create bottom wall
- createBox(640,30,320,480,b2Body.b2_staticBody,null);
- // Create top wall
- createBox(640,30,320,0,b2Body.b2_staticBody,null);
- // Create left wall
- createBox(30,480,0,240,b2Body.b2_staticBody,null);
- // Create right wall
- createBox(30,480,640,240,b2Body.b2_staticBody,null);
- functioncreateBox(width,height,pX,pY,type,data){
- var bodyDef = new b2BodyDef;
- bodyDef.type = type;
- bodyDef.position.Set(pX/worldScale,pY/worldScale);
- bodyDef.userData=data;
- var polygonShape = new b2PolygonShape;
- polygonShape.SetAsBox(width/2/worldScale,height/2/worldScale);
- var fixtureDef = new b2FixtureDef;
- fixtureDef.density = 1.0;
- fixtureDef.friction = 0.5;
- fixtureDef.restitution = 0.5;
- fixtureDef.shape = polygonShape;
- var body=world.CreateBody(bodyDef);
- body.CreateFixture(fixtureDef);
- }
希望点击鼠标时,从左下角向鼠标点击的位置发射一支箭。所以在鼠标点击消息的响应方法中调用createArrow方法,根据传入的坐标生成一支箭,并赋给它初速度,代码如下:
- function onMouseDown(e) {
- var evt = e||window.event;
- createArrow(e.clientX-canvasPosition.x,e.clientY-canvasPosition.y);
- }
- function createArrow(pX,pY) {
- // Set the left corner as the originalpoint.
- var angle = Math.atan2(pY-450, pX);
- // Define the shape of arrow.
- var vertices = [];
- vertices.push(new b2Vec2(-1.4,0));
- vertices.push(new b2Vec2(0,-0.1));
- vertices.push(new b2Vec2(0.6,0));
- vertices.push(newb2Vec2(0,0.1));
- var bodyDef = new b2BodyDef;
- bodyDef.type = b2Body.b2_dynamicBody;
- bodyDef.position.Set(40/worldScale,400/worldScale);
- bodyDef.userData = "Arrow";
- var polygonShape = new b2PolygonShape;
- polygonShape.SetAsVector(vertices,4);
- var fixtureDef = new b2FixtureDef;
- fixtureDef.density = 1.0;
- fixtureDef.friction = 0.5;
- fixtureDef.restitution = 0.5;
- fixtureDef.shape = polygonShape;
- var body = world.CreateBody(bodyDef);
- body.CreateFixture(fixtureDef);
- // Set original state of arrow.
- body.SetLinearVelocity(newb2Vec2(20*Math.cos(angle), 20*Math.sin(angle)));
- body.SetAngle(angle);
- body.SetAngularDamping(dampingConstant);
- }
接下来就是系统方法,绘制物体并定时更新:
- function debugDraw() {
- var debugDraw = new b2DebugDraw();
- debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
- debugDraw.SetDrawScale(worldScale);
- debugDraw.SetFillAlpha(0.5);
- debugDraw.SetLineThickness(1.0);
- debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
- world.SetDebugDraw(debugDraw);
- }
- function update() {
- world.Step(1/60,10,10);
- world.ClearForces();
- for(var b = world.m_bodyList; b != null; b = b.m_next){
- if(b.GetUserData() === "Arrow") {
- updateArrow(b);
- }
- }
- world.DrawDebugData();
- }
注意上面update方法中调用的updateArrow方法,它负责模拟箭矢在空中运动形态,让整个过程更加真实。
- functionupdateArrow(arrowBody) {
- // Calculate arrow's fligth speed.
- var flightSpeed =Normalize2(arrowBody.GetLinearVelocity());
- // Calculate arrow's pointingdirection.
- var bodyAngle = arrowBody.GetAngle();
- var pointingDirection = new b2Vec2(Math.cos(bodyAngle),-Math.sin(bodyAngle));
- // Calculate arrow's flightingdirection and normalize it.
- var flightAngle =Math.atan2(arrowBody.GetLinearVelocity().y,arrowBody.GetLinearVelocity().x);
- var flightDirection = newb2Vec2(Math.cos(flightAngle), Math.sin(flightAngle));
- // Calculate dot production.
- var dot = b2Dot( flightDirection,pointingDirection );
- var dragForceMagnitude = (1 -Math.abs(dot)) * flightSpeed * flightSpeed * dragConstant *arrowBody.GetMass();
- var arrowTailPosition =arrowBody.GetWorldPoint(new b2Vec2( -1.4, 0 ) );
- arrowBody.ApplyForce( newb2Vec2(dragForceMagnitude*-flightDirection.x,dragForceMagnitude*-flightDirection.y),arrowTailPosition );
- }
- function b2Dot(a, b) {
- return a.x * b.x + a.y * b.y;
- }
- function Normalize2(b) {
- return Math.sqrt(b.x * b.x + b.y *b.y);
- }
最后是getElementPosition方法,用于获得canvas的偏移坐标:
- //http://js-tut.aardon.de/js-tut/tutorial/position.html
- function getElementPosition(element) {
- var elem=element, tagname="",x=0, y=0;
- while((typeof(elem) =="object") && (typeof(elem.tagName) != "undefined")){
- y += elem.offsetTop;
- x += elem.offsetLeft;
- tagname = elem.tagName.toUpperCase();
- if(tagname == "BODY"){
- elem=0;
- }
- if(typeof(elem) =="object"){
- if(typeof(elem.offsetParent) =="object"){
- elem = elem.offsetParent;
- }
- }
- }
- return {x: x, y: y};
- }
程序的运行结果(Chrome 25.0.1323.1下测试)如下图所示:
源代码下载地址:http://download.csdn.net/detail/raymondcode/5151381
使用Box2dWeb模拟飞行箭矢相关推荐
- [HTML5]使用Box2dWeb模拟飞行箭矢
Box2d是一个2D游戏物理引擎,由Erin Catto开发,于2007年发布.很多2D游戏都用过Box2d,其中最有名的自然是愤怒的小鸟.Box2d本身是C++编写,但在不同平台都有它的衍生版本,像 ...
- android 模拟飞行,安卓版模拟飞行 X Plane 9试玩
2004年的圣诞节那天,我垂头丧气地坐在我家的廉价电脑前,盯着那老式的CRT显示器屏幕.我都不知道电脑里的模拟飞行游戏是正在安装,还是已经卡死了.电脑主机在桌子下面嗡嗡嗡地响,都快带不动这个庞然大物般 ...
- matlab如何模拟竹蜻蜓飞行,JSBSim_Matlab 将 与 进行联合仿真 模拟飞行计算 247万源代码下载- www.pudn.com...
文件名称: JSBSim_Matlab下载 收藏√ [ 5 4 3 2 1 ] 开发工具: Visual C++ 文件大小: 7092 KB 上传时间: 2015-07-26 下载次数: ...
- 微软模拟飞行2020服务器多少内存,《微软模拟飞行2020》配置公开,想玩爽还需玩家加大投入...
作为众多硬核玩家在2020年最为期待的游戏之一,<微软模拟飞行2020>的所有细节公开都广受关注.要知道,这款游戏除了具有顶级的画面外,其对全球航线.机场和即使天气的模拟演算都堪称专业级. ...
- visual studio 代码提示_《微软模拟飞行2020》代码暗示下一代Xbox或支持VR
(映维网 2020年10月24日)<微软模拟飞行2020>已经开始内测VR功能,并且将头显支持范围扩大到支持3Glasses S2等.但更令社区感到兴奋的是,PC游戏的代码变化引起了人们对 ...
- 模拟飞行 android,RFS模拟飞行pro安卓版
RFS模拟飞行pro安卓版是一款十分真实的飞行与驾驶体验,在这里更多的危险也即将要发生了,充满了危机的时刻.更加真实的冒险也在等待你的完成哦,属于你的热血游戏与体验模式,全新的与充满了危险的时刻也在等 ...
- 盲僧一键r闪用什么设置_美加狮R.A.T. PRO X3至尊版带你畅玩模拟飞行
很多模拟飞行或者皇牌空战的玩家们都追求在游戏过程中的真实驾驶体验,渴望通过游戏来实现自己的飞行梦.但普通鼠标的左右键及滚轮并不能带给玩家逼真的体验,美加狮全新发布的鼠标R.A.T. PRO X3至尊版 ...
- 运用卫星数据及AI技术 微软推出新一代模拟飞行游戏
在E3 2019游戏展上,微软展示了将于2020年推出的新一代<Microsoft Flight Simulator>游戏.借助卫星数据和最新的AI技术,图片看起来非常令人印象深刻. 自2 ...
- 8in1模拟器v2模拟飞行_重新想象飞行模拟器:过去和现在
8in1模拟器v2模拟飞行 本文是Microsoft的Web开发系列的一部分. 感谢您支持使SitePoint成为可能的合作伙伴. Apple于1980年推出了Flight Simulator的第一个 ...
- 微软模拟飞行10教程
新手入门和实用技巧图文教程 微软模拟飞行的知识性和趣味性都很强,涉及的知识面广,游戏里有详细的飞行课程指导,网上也有许多高手写的经验帖.但初学者面对各种资料,入手有难度,不易操作.本文针对有关飞行的最 ...
最新文章
- 在ASP.NET Core中获取客户端IP地址
- 打开ftp服务器上的文件夹时出错505,FTP提示505错误解决办法
- WinDbg 查看静态变量
- 微课|玩转Python轻松过二级(2.1.4节):列表、元组、字典、集合概述
- PHP第十次实验总结,The Clean Architecture in PHP 读书笔记(十)
- LeetCode 150. Evaluate Reverse Polish Notation
- 腾讯云-Linux 基础入门
- Max(TM)仓库管理系统v2.0.5.1网络版
- 2022年电气试验考试试题模拟考试平台操作
- iOS网络编程---根据URL下载网络文件的方法
- nodejs实现单点登录系统
- cadlisp框选打印_在CAD中实现批量打印
- 微信公众号--根据用户的opneId发送模版消息
- 手机app注册登录服务器客户端流程图
- 手机OTG是什么功能,怎样使用?
- Mac系统升级后导致AS不能使用SVN
- 信捷PLC以太网通讯数据采集解决方案
- linux命令jps意思是什么
- pdf图片如何转可编辑文字,加密pdf如何破解,你也能轻松学会的pdf处理技能
- 为了更有效率地偷钱,Android root木马开始试水短信扣费诈骗