繁体   English   中英

THREE.js-用曲线(X / Z轴)射击球

[英]THREE.js - shooting a ball with a curve ( X / Z axis)

我是THREE.js的新手,并且对物理学的知识很差,但是我仍然想制作一个足球经理游戏(从顶视图看),并且我需要知道球的踢脚要尽可能切合实际。

当球击中边界时,我能够使球朝正确的方向移动和旋转,同时改变运动的位置。

现在我需要处理一个球的弯曲问题,以及如何使它弯曲,以便使球根据脚部击球的角度成弧形移动到顶部和侧面(X / Y)

可以说,我需要知道如何处理两种情况:

  • 1)从球的底轴附近开始踢球
  • 2)当从球的右轴开始踢球时

您的帮助非常合适。 谢谢!

**-我添加了一个代码来显示到目前为止的内容-我添加了一张说明我的目标的图片(或此人为目标得分)

在此处输入图片说明

  /* * * SET UP MOTION PARAMS * */ var boundries = [40, 24] //indicate where the ball needs to move in mirror position var completeFieldDistance = boundries[0] * 2; var fullPower = 1.8; //the power needed to move the ball the enitre field in one kick var power = null; //will be set when the kick set in depending on the distance var isKickStop = false; //indicate the renderer weather to stop the kick var velocityX = null; var velocityY = null; //*** this is where i need help! *** //how can I make the ball move in the Z axis with a nice curv up depending on a given angle var curv = 15; var peak = curv; var velocityZ = 0; var friction = 0.98; var gravity = 0.5; var bounciness = 0.8; var minVelocity = 0.035; //for when it need to stop the kick rendering var ballRadius = 3; var ballCircumference = Math.PI * ballRadius * 2; var ballVelocity = new THREE.Vector3(); var ballRotationAxis = new THREE.Vector3(0, 1, 0); //world meshes var ball = {}; var field = {}; /* * * THE KICK HANDLERS * */ function onKick(angleDeg, distance) { isKickStop = true; peak = curv; power = (distance / completeFieldDistance) * fullPower; velocityX = Math.cos(angleDeg) * power; velocityY = Math.sin(angleDeg) * power; velocityZ = peak / (distance / 2); requestAnimationFrame(function (params) { isKickStop = false; animateKick(); }) } //** THIS IS WHERE I NEED HELP - how do I make the ball move // render the movements of the ball var animateKick = function (params) { if (isKickStop) { return; } ball.position.x += velocityX; ball.position.z += velocityZ; ball.position.y += velocityY; if (Math.abs(velocityX) < minVelocity && Math.abs(velocityY) < minVelocity) { ball.position.z = ball.bottom; isKickStop = true; console.log("DONE!"); return; } if (ball.position.z >= peak) { ball.position.z = peak; velocityZ *= -1; } if (ball.position.z < ball.bottom) { peak *= gravity; velocityZ *= -1; ball.position.z = ball.bottom; } // Figure out the rotation based on the velocity and radius of the ball... ballVelocity.set(velocityX, velocityY, 0); ballRotationAxis.set(0, 0, 1).cross(ballVelocity).normalize(); var velocityMag = ballVelocity.length(); var rotationAmount = velocityMag * (Math.PI * 2) / ballCircumference; ball.rotateOnWorldAxis(ballRotationAxis, rotationAmount); //reduce velocity due to friction velocityX *= friction; velocityY *= friction; //making sure ball is not outside of its boundries if (Math.abs(ball.position.x) > boundries[0]) { velocityX *= -1; ball.position.x = (ball.position.x < 0) ? boundries[0] * -1 : boundries[0]; } if (Math.abs(ball.position.y) > boundries[1]) { velocityY *= -1; ball.position.y = (ball.position.y < 0) ? boundries[1] * -1 : boundries[1]; } } window.onload = (function (params) { /* * * SET UP THE WORLD * */ //set up the ratio var gWidth = window.innerWidth; var gHeight = window.innerHeight; var ratio = gWidth / gHeight; //set the scene scene = new THREE.Scene(); scene.background = new THREE.Color(0xeaeaea); //set the camera var camera = new THREE.PerspectiveCamera(35, ratio, 0.1, 1000); camera.position.z = 120; //set the light var light = new THREE.SpotLight(0xffffff, 1); light.castShadow = true; light.position.set(0, 0, 35); scene.add(light); // set the renderer var renderer = new THREE.WebGLRenderer(); //properties for casting shadow renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.setSize(gWidth, gHeight); document.body.appendChild(renderer.domElement); /* * * ADD MESH TO SCENE * */ // create and add the ball var geometry = new THREE.SphereGeometry(ballRadius, 8, 8); //make a checkerboard texture for the ball... var canv = document.createElement('canvas') canv.width = canv.height = 256; var ctx = canv.getContext('2d') ctx.fillStyle = 'white'; ctx.fillRect(0, 0, 256, 256); ctx.fillStyle = 'black'; for (var y = 0; y < 16; y++) for (var x = 0; x < 16; x++) if ((x & 1) != (y & 1)) ctx.fillRect(x * 16, y * 16, 16, 16); var ballTex = new THREE.Texture(canv); ballTex.needsUpdate = true; var material = new THREE.MeshLambertMaterial({ map: ballTex }); ball = new THREE.Mesh(geometry, material); ball.castShadow = true; ball.receiveShadow = false; ball.bottom = ballRadius / 2; scene.add(ball); // create and add the field var margin = 20; var fieldRatio = 105 / 68; var width = 90; var height = width / fieldRatio; var material = new THREE.MeshLambertMaterial({ color: 'green' }); var geometry = new THREE.BoxGeometry(width, height, 1); field = new THREE.Mesh(geometry, material); field.receiveShadow = true; field.position.z = -1; scene.add(field); /* * * HANDLING EVENTS * */ var domEvents = new THREEx.DomEvents(camera, renderer.domElement); domEvents.addEventListener(field, 'click', function (e) { //set points 1 and 2 var p1 = { x: e.intersect.point.x, y: e.intersect.point.y }; var p2 = { x: ball.position.x, y: ball.position.y }; var angleDeg = Math.atan2(p1.y - p2.y, p1.x - p2.x); var a = p1.x - p2.x; var b = p1.y - p2.y; var distance = Math.sqrt(a * a + b * b); window.onKick(angleDeg, distance); }, false); /* * * ANIMATION STEP * */ var render = function (params) { //render kick if it is on the go if(!isKickStop){ animateKick(); } //render the page renderer.render(scene, camera); requestAnimationFrame(render); } render(); })() 
 body { padding: 0; margin: 0; } 
 <html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script> <script src="https://www.klika.co.il/scripts/three.events.js"></script> </head> <body> </body> </html> 

我建立一个模型对此进行模拟,该模型接受几个参数,即初始速度和角速度,球上有三个力,重力,空气阻力和马格努斯力。

 v0_x = 0; //initial velocity v0_y = 4; v0_z = 1; w_x = 0 * Math.PI; // initial angular velocity w_y = 2 * Math.PI; w_z = 0 * Math.PI; m = 2; //weight rho = 1.2; // air density g = 9.8; // gravity f = 10; //frequency of the rotation of the ball cl = 1.23; //horizontal tension coefficient cd = 0.5; //air resistance coefficient D = 0.22; // diameter of the ball A = Math.PI * Math.pow((0.5 * D), 2); //cross-sectional area of the ball t_step = 1 / 60; b = (1 / 2) * cd * rho * A; //for convenience c = cl * rho * Math.pow(D, 3) * f; // for convenience vt_x = v0_x vt_y = v0_y vt_z = v0_z animateKick = function() { if (ball.position.y < 0) { return; } tmp_1 = c * Math.pow(Math.pow(vt_x, 2) + Math.pow(vt_z, 2) + Math.pow(vt_y, 2), 2) tmp_2 = (Math.sqrt(Math.pow(w_z * vt_y - w_y * vt_z, 2) + Math.pow(w_y * vt_x - w_x * vt_y, 2) + Math.pow(w_x * vt_z - w_z * vt_x, 2))) tmp = tmp_1 / tmp_2 Fl_x = tmp * (w_z * vt_y - w_y * vt_z) Fl_z = tmp * (w_y * vt_x - w_x * vt_y) Fl_y = tmp * (w_x * vt_z - w_z * vt_y) //Motion differential equation a_x = -(b / m) * Math.sqrt((Math.pow(vt_z, 2) + Math.pow(vt_y, 2) + Math.pow(vt_x, 2))) * vt_x + (Fl_x / m) a_z = -(b / m) * Math.sqrt((Math.pow(vt_z, 2) + Math.pow(vt_y, 2) + Math.pow(vt_x, 2))) * vt_z + (Fl_z / m) a_y = -g - (b / m) * Math.sqrt((Math.pow(vt_z, 2) + Math.pow(vt_y, 2) + Math.pow(vt_x, 2))) * vt_y + (Fl_y / m) //use formula : s_t = s_0 + v_0 * t to update the position ball.position.x = ball.position.x + vt_x * t_step ball.position.z = ball.position.z + vt_z * t_step ball.position.y = ball.position.y + vt_y * t_step //use formula : v_t = a * t to update the velocity vt_x = vt_x + a_x * t_step vt_z = vt_z + a_z * t_step vt_y = vt_y + a_y * t_step } window.onload = (function() { gWidth = window.innerWidth; gHeight = window.innerHeight; ratio = gWidth / gHeight; scene = new THREE.Scene(); scene.background = new THREE.Color(0xeaeaea); camera = new THREE.PerspectiveCamera(35, ratio, 0.1, 1000); camera.position.z = -15; light = new THREE.SpotLight(0xffffff, 1); light.castShadow = true; light.position.set(0, 5, -10); scene.add(light); renderer = new THREE.WebGLRenderer(); //properties for casting shadow renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.setSize(gWidth, gHeight); document.body.appendChild(renderer.domElement); geometry = new THREE.SphereGeometry(D, 8, 8); //make a checkerboard texture for the ball... canv = document.createElement('canvas') canv.width = canv.height = 256; ctx = canv.getContext('2d') ctx.fillStyle = 'white'; ctx.fillRect(0, 0, 256, 256); ctx.fillStyle = 'black'; for (y = 0; y < 16; y++) for (x = 0; x < 16; x++) if ((x & 1) != (y & 1)) ctx.fillRect(x * 16, y * 16, 16, 16); ballTex = new THREE.Texture(canv); ballTex.needsUpdate = true; material = new THREE.MeshLambertMaterial({ map: ballTex }); ball = new THREE.Mesh(geometry, material); ball.castShadow = true; ball.receiveShadow = false; ball.bottom = D / 2; scene.add(ball); camera.lookAt(ball.position); plane_geometry = new THREE.PlaneGeometry(20, 100, 32); plane_material = new THREE.MeshBasicMaterial({ color: 'green', side: THREE.DoubleSide }); ground_plane = new THREE.Mesh(plane_geometry, plane_material); ground_plane.rotation.x = 0.5 * Math.PI ground_plane.position.y = -1 ground_plane.position.z = 20 scene.add(ground_plane); render = function(params) { animateKick(); renderer.render(scene, camera); requestAnimationFrame(render); }; render(); }) 
 body { padding: 0; margin: 0; } 
 <html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script> <script src="https://www.klika.co.il/scripts/three.events.js"></script> </head> <body> </body> </html> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM