整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

纯CSS也可以实现边界碰撞检测?#css

个视频来看一个小球碰撞边界的运动效果。可以看到有一个小球在随机运动,然后当碰到边界它就会反弹出去,似乎可以用来做碰撞边界的检测。

想一下这个例子可不可以只用CSS来做?其实是可以的,但是这里它并不算是边界检测,又或者说它只能检测到整个窗口的边界,然后反弹。如果是有其它元素,想检测和其它元素有没有发生碰撞,用CSS就很难实现了。

先来看一下这个demo,现在非常简单,就写了一个div,然后给它一些基本的样式,用来模拟这个小球。

接下来就要想一下,怎么样可以让这个小球动起来?无非就是给它添加一个动画对吧?这个动画应该控制哪些属性发生变化,可以让这个小球动起来呢?是不是控制这两个属性?

先来控制水平方向的运动,也就是left,因为初始状态就是让它从0开始。CSS上面设置的也是0,所以from可以省略不写,只写吐就行了。结束的状态是让小球运动到边界。这里可以用一个计算的函数,水平方向用整个视口的宽度,再减去小球自身的宽度,再把这个动画给它绑定到小球上面,这样小球它就可以动起来了。

但是它只是往一个方向来动并没有反弹的效果,要让小球反弹的也很简单,给它加一个alternate,当动画执行到最后状态的时候,再反过来执行就可以了。看一下,小球运动到边界它就反弹了,但是现在只是水平方向的运动,还要加上垂直方向的运动。

垂直方向和水平方向原理是一样的,给它复制一下,再改一下动画的名称,left改成top,视口的宽度就改成视口的高度,再把这个动画绑定上去。这里名称再改一下,看一下效果。现在确实水平和垂直方向同时在运动了,但是它只是往对角线运动,没有一种随机弹跳的效果。

怎么样可以让这个运动不要那么规律?不要只是往对角线来运动,看起来有一些随机性。这里也很简单,只要让这两个动画完成的时间稍微错开一点就可以了。

→比方水平方向的给它3.6秒,垂直方向就2.3秒,看一下最终的效果。现在的运动就不是只往对角线来运动了,看起来有一定的随机性,然后运动到边界就可以回弹过来。

这个视频就到这里,感谢大家的收看。

代码

<!DOCTYPE html>
<html lang="zh_CN">
<head>
 <meta charset="UTF-8">
 <title>弹球</title>
 <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
 // 全局canvas
 let canvas = document.getElementById("canvas");
 let context = canvas.getContext("2d");
 // 弹球对象
 class Ball{
 x = 100;
 y = 40;
 xSpeed = -2;
 ySpeed = -2;
 constructor(){};
 getX(){
 return this.x;
 }
 getY(){
 return this.y;
 }
 setX(x){
 this.x = x;
 }
 setY(y){
 this.y = y;
 }
 getXSpeed(){
 return this.xSpeed;
 }
 setXSpeed(xSpeed){
 this.xSpeed = xSpeed;
 }
 getYSpeed(){
 return this.ySpeed;
 }
 setYSpeed(ySpeed){
 this.ySpeed = ySpeed;
 }
 // 绘制小球的方法
 draw = () => {
 context.beginPath();
 context.arc(this.x, this.y, 10, 0, Math.PI * 2, false);
 context.strokeRect(0, 0, 400, 400);
 context.fill();
 };
 // 移动操作
 move = () => {
 this.x = this.x + this.xSpeed;
 this.y = this.y + this.ySpeed;
 };
 // 边缘检测,碰撞检测
 checkCanvas = (panel) => {
 // 左右
 if(this.x < 5 || this.x > 400 - 5){
 this.xSpeed = -this.xSpeed;
 }
 // 上方
 if(this.y < 0){
 this.ySpeed = -this.ySpeed;
 }
 // 下方
 // 碰到挡板
 if(this.y > 390 - 10){
 if(this.x > panel.x && this.x < panel.xSize + panel.x){
 this.ySpeed = -this.ySpeed;
 }else{
 alert("游戏结束");
 this.x = 100;
 this.y = 10;
 }
 }
 }
 }
 // 增加一个挡板对象
 class Panel{
 constructor(){};
 // 左x
 x = 200;
 // 左y
 y = 390;
 // 长度
 xSize = 50;
 // 宽度
 ySize = 5;
 draw(){
 context.fillRect(this.x, this.y, this.xSize, this.ySize);
 }
 }
 // 创建出一个小球对象
 let ball = new Ball();
 // 创建出挡板对象
 let panel = new Panel();
 // 每10秒为一帧
 window.setInterval(() => {
 // 清空画布
 context.clearRect(0, 0, 400, 400);
 // 画出小球
 ball.draw();
 // 画出挡板
 panel.draw();
 // 移动
 ball.move();
 // 进行边界判断
 ball.checkCanvas(panel);
 },10);
 // 控制挡板
 $("body").keydown((event) => {
 if(event.keyCode == 37){
 panel.x = panel.x - 5;
 // 移出边界问题处理
 if(panel.x < 0){
 panel.x = 0;
 }
 }
 if(event.keyCode == 39){
 panel.x = panel.x + 5;
 // 移出边界处理
 if(panel.x + panel.xSize > 400){
 panel.x = 400 - panel.xSize;
 }
 }
 })
</script>
</body>
</html>

思路

这就是俩对象,,一个依赖于另一个。。

碰撞检测时实的坐标判断,碰撞完成以后两个速度分量为取反即可。

事件是左右事件。。移动即可。

需要时实刷新,即,帧的概念

尔夫球的设计环节会有样品冲击测试,以便了解产品在冲击作用下的响应。

高尔夫球的球体一般会有2~5层,分别采用不同材料,利用球体结构的刚度分布,来影响球的操控性。根据网上搜到的试验数据与材料参数,使用Abaqus对试验中的3层球进行撞击响应建模分析。球体按层切分,并赋予指定材料的截面属性。

通过Abaqus/Explicit分析的高尔夫球冲击过程中的应力以及速度云图如下:



对于球体在球杆打击作用下的响应(速度与旋转速率),在设计环节也会进行大量的计算分析,通常会计算球杆不同表面特征(U型开槽、V型开槽)下的出球响应。


如下图所示,设计部门在仿真前期会做一些基于试验参数的对标工作,以矫正仿真分析时高应变率条件下的材料本构模型参数。

在参数修正的基础上,再进行仿真计算,以更准确地对高尔夫球的动态响应进行预测,从而指导产品设计,缩短研发周期。对标后的仿真基本上可以做到和高速摄影同步。

现在再来谈谈,球面上的凹槽怎么回事。上面提到高尔夫球的出球响应中,有个变量是旋转速率,原来,球在飞行的过程中,不同旋转速率下,由于凹凸的气动外形,导致球体产生气动阻力、升力是完全不一样的,这也就决定了高尔夫球的运动轨迹。

对于高速飞行的高尔夫球,凹凸的表面会导致湍流,影响球体受力,下面这个视频是Youtube上ID为CFD Support的团队通过OpenFOAM计算的不同旋转速率条件下高尔夫球的升力和阻力系数。有没有旋转,差别还是挺显著的,所以球杆的击球面要开槽,这样在出球时,球才会更容易转起来。

https://v.qq.com/x/page/n0660gsrpd2.html

作者:邓怡超,仿真秀科普作者。

声明:原创文章,版权所有,禁止私自转载,欢迎分享,转载请联系我。