构建自己的WebGL物理游戏

null

该项目将分为不同的部分。我们将简要介绍Heroku,展示如何使用带有three.js的Physijs,解释如何处理Node.js上的套接字事件以及我们如何处理发送的数据。

01. Heroku

Heroku is an easy to use and free to trial node.js web server

Heroku是一个易于使用且免费试用的node.js网络服务器

该项目将托管在Heroku的,这是一个托管您的应用程序的云平台。它有各种支持的语言,如Ruby,Java,PHP和Python。我们将使用Node.js.

注册一个帐户,然后选择Node.js.对于这个项目,我们可以使用免费的基本服务器。注册后,您将进入仪表板,您可以在其中创建应用程序。这将在herokuapp.com上创建一个子域。

作为部署方法,您可以选择使用Heroku命令行界面(CLI)使用其git存储库进行部署,或者将连接设置为GitHub或Dropbox。我选择使用它的CLI;这将需要安装。但作为回报,您将获得各种新的有用工具,其中之一是通过终端进行实时调试。

要设置服务器,我建议您按照以下步骤操作如此处所述

要部署,请使用默认的git命令。您使用的每一个都将触发构建服务器,您的应用程序将部署到Heroku服务器,然后可以在您的子域中查看。

部署代码后,您可以在[yourproject] .herokuapp.com上查看您的项目。要查看日志,请在终端中使用“heroku logs - tail”命令。显示的一些内容是为客户端提供的内容 - 它显示套接字连接,如果要调试代码,还可以使用console.log输出到终端。

02.建立物理场景

Tap your screen or hit the spacebar to bounce the table up

点按屏幕或点击空格键可将桌面反弹

我们将使用最受欢迎的WebGL的框架,Three.js所,构建一个包含我们将附加物理的对象的3D场景。选择的物理库是Physijs,一个three.js的插件。作为three.js的扩展,Physijs使用相同的编码约定,如果您已经熟悉three.js,则更容易使用。

第一件事就是台球桌。我们正在使用PhysijsHeightfieldMesh,因为此网格将从PlaneGeometry读取高度。所以它基本上将自己包裹在three.js对象周围。

var tableGeometry = new THREE.PlaneGeometry(650,500,10,10); var tableMaterial = Physijs.createMaterial(new THREE.MeshPhongMaterial({shininess:1,color:0xb00000,emissive:0x111111,side:THREE.DoubleSide}),. 8,// friction .4 // restitution); table = new Physijs.HeightfieldMesh(tableGeometry,tableMaterial,0);

所以HeightfieldMesh需要几何体,但也需要Physijs材质。我们在three.js材质中添加了两个新功能。那些是摩擦归还变量。摩擦是物体产生的阻力,恢复原状是指“弹性”。这两个变量将定义物理在场景中的真实感。

对于创建的球池,我们不希望它们太有弹性,所以保持低数字。与three.js一样,Physijs也有一系列基本形状可以绕过原始网格。SphereMesh包裹着SphereGeometry将给球物理。初始化场景时,我们打电话BuildBall(8),这将触发以下功能......

var buildBall = function(numberBall){var ballTexture = new THREE.Texture(); var ballIndex = ball.length;

添加纹理:

ballTexture = THREE.ImageUtils.loadTexture('textures /'+ numberBall +'_ Ball.jpg',function(image){ballTexture.image = image;});

使用一些合适的摩擦和弹跳属性创建支持physijs的材质:

var ballMaterial = Physijs.createMaterial(new THREE.MeshLambertMaterial({map:ballTexture,shininess:10,color:0xdddddd,emissive:0x111111,side:THREE.FrontSide}),。6,// friction .5 // restitution);

纹理映射:

ballMaterial.map.wrapS = ballMaterial.map.wrapT = THREE.RepeatWrapping; ballMaterial.map.repeat.set(1,1);创建启用物理的SphereMesh,并在空中启动:ball [ballIndex] = new Physijs.SphereMesh(new THREE.SphereGeometry(25,25,25),ballMaterial,100); // y偏移到画布球的顶部[ballIndex] .position.y = 500; // shadow ball [ballIndex] .receiveShadow = true; ball [ballIndex] .castShadow = true; //将球添加到画布scene.add(ball [ballIndex]); };

我们正在从.jpg文件中添加纹理。创建材料并将其用于SphereMesh创建对象,我们将垂直放置在顶部,使其落入屏幕。

03.套接字连接

The key goal of our game is emulating the physical movements to the screen

我们游戏的关键目标是模拟屏幕的物理移动

对于服务器和客户端之间的通信,我们将使用Socket.io。这是Node.js最可靠的库之一。它建立在WebSockets API之上。

现在物理已启用网格我们需要用户输入以使游戏交互。我们使用的输入设备是移动设备。移动浏览器是将提供数据的控制器来自加速度计和陀螺仪到你将看到游戏的桌面。

首先,必须在移动浏览器和桌面浏览器之间建立连接。每次浏览器与我们的Node.js应用程序连接时,我们都需要建立新的连接。使用以下内容设置客户端连接:

var socket = io.connect();

要发送消息,请使用发射功能:

socket.emit('event name',data);

而接收你使用。上()功能:

socket.on('event name',function(){});

03.1。设置桌面游戏

如果我们在桌面上,我们将发送我们的套接字设备发出告诉我们的服务器桌面是使用以下代码行的游戏:

var socket = io.connect(); //当初始欢迎消息时,回复'游戏'设备类型socket.on('welcome',function(data){socket.emit(“device”,{“type”:“game”});});

服务器将返回一个唯一的密钥/游戏代码由加密生成。这将显示在桌面上。

//生成代码var gameCode = crypto.randomBytes(3).toString('hex')。substring(0,4).toLowerCase(); //确保唯一性while(gameCode in socketCodes){gameCode = crypto.randomBytes(3).toString('hex')。substring(0,4).toLowerCase(); } //存储游戏代码 - >套接字关联socketCodes [gameCode] = io.sockets.sockets [socket.id]; socket.gameCode = gameCode

告诉游戏客户端初始化并向用户显示游戏代码......

socket.emit(“initialize”,gameCode);

03.2。将控制器连接到游戏

要将移动设备连接到游戏,我们将使用表单从桌面屏幕提交游戏代码。在表单提交上,我们将游戏代码发送到服务器进行身份验证。

socket.emit(“device”,{“type”:“controller”,“gameCode”:gameCode});

服务器将检查游戏代码是否有效,并将设置与桌面游戏的连接

if(socketCodes中的device.gameCode){//保存控制器命令的游戏代码socket.gameCode = device.gameCode //初始化控制器socket.emit(“connected”,{}); //启动游戏socketCodes [device.gameCode] .emit(“connected”,{}); }

一旦连接全部设置完毕,我们将使用以下命令从x和z给出8-ball小推...

ball [0] .setLinearVelocity(new THREE.Vector3(30,0,30));

04.发送数据

现在连接已建立,我们希望将陀螺仪和加速度计变量发送到游戏中。通过使用Window.ondevicemotionWindow.ondeviceorientation事件,我们需要模拟我们的手机到台球桌的相同倾斜运动所需的数据。我选择使用100ms的间隔来发射这些值。

setInterval(function(){socket.emit('send gyro',[Math.round(rotY),Math.round(rotX),ay,ax]);},intervalTime);

在客户端,我们将通过将服务器的传入值补间到池表的倾斜来解决延迟。对于补间我们使用TweenMax

//处理输入的陀螺仪数据socket.on('new gyro',function(data){var degY = data [1] <0?Math.abs(data [1]): -  data [1]; TweenMax.to( table.rotation,0.3,{x:degToRad(degY-90),y:degToRad(data [0]),ease:Linear.easeNone,onUpdate:function(){table .__ dirtyRotation = true;}});}) ;

05.额外活动

More balls equals more fun. Try hitting the spacebar or tapping the screen of your mobile

更多的球等于更多的乐趣。尝试按空格键或点按手机屏幕

为了给它更多的交互性,我添加了一些额外的事件供用户使用。我们将通过使用键盘上的数字为用户提供在8球旁边添加额外球的选项。

另一个是向上反弹桌子。为此你可以点击空格键。但我们还在控制器设备上添加了一个tap事件。这会将一个事件发送到台球桌,这会使桌子上升并将球送出。

首先我们需要抓住键盘事件......

//在空格键上创建ball / slam表document.addEventListener('keydown',function(e){if(e.keyCode == 49){// key:1 buildBall(1);} else if(e.keyCode = = 50){// key:1 buildBall(2);} else if(e.keyCode == 51){// key:1 buildBall(3);} else if(e.keyCode == 32){// key:spacebar bounceTable();}});

BuildBall功能与我们用于创建球体8球的功能相同。我们只是使用不同的纹理来包裹球体。为了推动桌子,我们使用此代码沿y轴向上移动桌子......

table.setLinearVelocity(new THREE.Vector3(0,500,0));

结论

Add more balls and see how much your browser can handle

添加更多球,看看您的浏览器可以处理多少

当你有一个游戏概念或其他任何东西时,很可能有一些库可以让你的生活更轻松。这是一个演示如何工作的演示。我们希望这有助于激发一些创意或帮助您完成当前项目。查看游戏的实时示例这里,或找到它GitHub上

本文最初发表于第300期,专业网页设计师和开发者的世界顶级杂志。购买问题300要么订阅这里

相关文章:



翻译字数超限