- 如何使用SpringJoint2D组件制作一个弹簧,并且使图片跟随弹簧一并拉伸和挤压。
- SpringJoint2D我会用,但是不知道如何让贴图跟随弹簧一并拉伸和挤压。
- 示例动图如下:
大家能帮帮我么,我太难了,谢谢!
上面的示意图不是已经有拉伸了吗,这道题不会等物理引擎熟悉的大佬来解答,吃瓜
示意图是我录屏的别人的小游戏,我不知道他怎么做的,我想学习一下,所以发上来请高手指点
我好像知道怎么做了,等我测试一下,等我吃完饭,如果可行我就把解决方案发出来
1赞
吃完了吗?
- 图片拉伸和挤压的方法非常简单,就是字面意思,单纯的在长度方向进行拉伸和挤压。
- 例如弹簧贴图的原始尺寸为10x50,如果拉伸它的话,就将它的尺寸变为10x100,如果挤压它的话,就将它的尺寸变为10x20。
- 然后再根据弹簧的两个端点计算一下贴图的坐标,和旋转,每帧都更新就行了。
- 弹簧的贴图用ps在透明背景中画几条直线就行了,或者画几个圆柱绘制上阴影,都行。
1赞
import { _decorator, Color, Component, director, EventMouse, Input, input, Node, Quat, RigidBody2D, SpringJoint2D, Sprite, SpriteFrame, UITransform, Vec2, Vec3 } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('Spring')
export class Spring extends Component {
spring: Node; // 弹簧图片
point1: Node; // 保存弹簧的A端(本组件所在的节点上的标记点)
point2: Node; // 保存弹簧的B端(弹簧的另一端)
counter: number = 0;
start() {
// 此脚本挂在拥有SpringJoint2D组件的node上
const sj = this.node.getComponent(SpringJoint2D);
// 在本物体的弹簧锚点位置创建一个空Node用于标记
let point1 = new Node('mark_point');
point1.position = new Vec3(sj.anchor.x, sj.anchor.y, 0);
point1.parent = this.node;
this.point1 = point1;
// 在对方物体的弹簧锚点位置创建一个空Node用于标记
let point2 = new Node('mark_point');
point2.position = new Vec3(sj.connectedAnchor.x, sj.connectedAnchor.y, 0);
point2.parent = sj.connectedBody.node;
this.point2 = point2;
// 我将弹簧图片直接放到了场景中了, 方便从中提取spriteFrame
// 开发的时候, 我喜欢这样加载资源, 就不用从AB包或者resources中加载了
// 总之这里我需要找到弹簧图片的spriteFrame
const canvas = director.getScene().getChildByPath('Canvas');
const spf = canvas.getChildByPath('spring').getComponent(Sprite).spriteFrame;
// 创建弹簧图片
const spring = new Node('springxxx');
spring.parent = canvas;
const tf = spring.addComponent(UITransform);
const sp = spring.addComponent(Sprite);
sp.spriteFrame = spf;
sp.color = Color.YELLOW;
// 添加完Sprite后再修改UITransform的属性, 否则添加Sprite的时候会将UITransform属性重置
tf.width = 50;
this.spring = spring;
// 监听鼠标, 给物体力, 使物体产生移动
input.on(Input.EventType.MOUSE_DOWN, this.on_mouse_down, this);
}
update(deltaTime: number) {
// 找到两个标记点
const p1 = this.point1.worldPosition;
const p2 = this.point2.worldPosition;
// 图片的世界位置是这两个标记点的中点
const pos = new Vec3((p1.x + p2.x) / 2, (p1.y + p2.y) / 2, 0);
const vector = new Vec2(p2.x - p1.x, p2.y - p1.y);
// 图片的世界角度是这两个标记点构成的直线的方向, 由于我的图片是竖直的, 所以我要计算这条直线与Y轴的夹角
// 负号是我测试的, 原理不详, 你也可以调换一下p1-p2这个向量的方向, 随意
const angle = -vector.signAngle(new Vec2(0, 1)) / Math.PI * 360 / 2;
// 图片的长度是这两个标记点的距离
const length = vector.length();
// 更新弹簧图片
this.spring.worldPosition = pos;
const quat = new Quat();
Quat.fromAngleZ(quat, angle);
this.spring.worldRotation = quat;
this.spring.getComponent(UITransform).height = length;
}
on_mouse_down(e: EventMouse) {
const rb = this.node.getComponent(RigidBody2D);
const mass = rb.getMass();
if (e.getButton() == EventMouse.BUTTON_LEFT) {
// 按左键, 给物体一个向下的力来拉伸弹簧
const i = new Vec2(0, -mass * 20);
rb.applyLinearImpulseToCenter(i, true);
} else {
// 按右键, 给物体一个向右的力来使弹簧旋转
const i = new Vec2(mass, 0);
rb.applyLinearImpulseToCenter(i, true);
}
}
}
此脚本会在start的时候给弹簧的两个锚点创建两个空Node,使用这两个辅助Node来计算弹簧图片的位置、旋转、大小。
喝多了,但是不影响写demo
gif帧率太低,导致观看效果不好,实测效果特别丝滑,好像装了一个真弹簧上去一样,此问题结案了。
大佬, 好强
大佬, 有源码么
我不知道如何发cocos的项目代码,我刚开始接触cocos1个月,还没研究cocos的项目结构,不知道应该发哪些文件。我把关键的代码已经发到了5楼,你们自己研究一下吧。