cb/assets/Script/lq_collide_system/lq_collide.ts
2025-07-01 19:39:23 +08:00

505 lines
18 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import ccclass = cc._decorator.ccclass;
import property = cc._decorator.property;
import requireComponent = cc._decorator.requireComponent;
import menu = cc._decorator.menu;
import Component = cc.Component;
import Enum = cc.Enum;
import Size = cc.Size;
import Vec2 = cc.Vec2;
import Graphics = cc.Graphics;
import Node = cc.Node;
import macro = cc.macro;
import Color = cc.Color;
import {LQCollideShape, LQCollideStatus} from "../lq_base/data/lq_const";
import {LQCollideConfig, LQCollideInfoList} from "./lq_collide_config";
import {LQCollideSystem} from "./lq_collide_system";
import {LQRect} from "../lq_base/data/lq_data";
import {LQCollideBase} from "./lq_collide_base";
import {LQGameUtil} from "../lq_base/util/lq_game_util";
import MapConroler from "../Map";
@ccclass
@requireComponent(LQCollideBase)
@menu("lq/collide")
export class LQCollide extends Component {
velocity: any;
@property({displayName: '绘制形状'})
get draw_collide(): boolean {
return this._draw_collide;
}
set draw_collide(value: boolean) {
this._draw_collide = value;
this.draw_shape();
}
@property
protected _draw_collide: boolean = true;
@property({tooltip: '能否移动'})
protected can_move: boolean = true;
@property({
tooltip: '碰撞形状None就是无敌不参与碰撞',
type: Enum(LQCollideShape),
displayName: '碰撞形状'
})
get collide_shape(): LQCollideShape {
return this._collide_shape;
}
set collide_shape(value: LQCollideShape) {
this._collide_shape = value;
this.draw_shape();
}
@property()
public _collide_shape: LQCollideShape = LQCollideShape.Rect;
@property({
type: Enum(LQCollideInfoList), tooltip: '碰撞类别',
displayName: '碰撞类别'
})
get collide_group_index() {
if (this._collide_group_index === -1) {
this._collide_group_index = LQCollideSystem.get_info_by_id(this.collide_group_id).index;
}
return this._collide_group_index;
}
set collide_group_index(value) {
if (this._collide_group_index === value) {
return;
}
this._collide_group_index = value;
this.collide_group_id = LQCollideSystem.get_group_by_index(value).id;
}
@property({serializable: false})
private _collide_group_index = -1;
@property({visible: false})
protected collide_group_id: number = 0;
@property({visible: false})
protected collide_scle: number = 1;
@property({
tooltip: 'collide半径',
visible() {
// @ts-ignore
return this._collide_shape === LQCollideShape.Circle;
},
displayName: '半径'
})
get radius(): number {
return this._radius;
}
set radius(value: number) {
this._radius = value;
this.draw_shape();
}
@property()
protected _radius: number = 50;
// 物体速度
// public velocity: Vec2 = new Vec2(0, 0);
@property({
tooltip: 'collide长宽',
visible() {
// @ts-ignore
return this._collide_shape === LQCollideShape.Rect;
},
displayName: '长宽'
})
get size(): Size {
return this._size;
}
set size(value: Size) {
this._size = value;
if (this.world_rect) {
this.world_rect.width = value.width;
this.world_rect.height = value.height;
this.world_rect.half_width = value.width * 0.5;
this.world_rect.half_height = value.height * 0.5;
}
this.draw_shape();
}
@property()
protected _size: Size = new Size(100, 100);
@property({displayName: '位置偏移'})
get offset(): Vec2 {
return this._offset;
}
set offset(value: Vec2) {
this._offset = value;
this.draw_shape();
}
@property({
type: Vec2,
visible() {
// @ts-ignore
return this._collide_shape === LQCollideShape.Polygon;
},
displayName: '多边形碰撞点'
})
get polygon_points(): Vec2[] {
return this._polygon_points;
}
set polygon_points(value: Vec2[]) {
this._polygon_points = value;
this.draw_shape();
}
@property()
public _polygon_points: Vec2[] = [new Vec2(-45, -45), new Vec2(45, -45), new Vec2(60, 40), new Vec2(0, 70), new Vec2(-60, 40)];
//collide碰撞位置偏移
@property()
public _offset: Vec2 = new Vec2(0, 0);
@property({displayName: '自定义字符串'})
public data_string: string = '';
//每个collide的id唯一
public collide_id: number = 0;
//状态
public collide_status: LQCollideStatus = LQCollideStatus.Idle;
//是否可碰撞
public is_enable: boolean = true;
//是否开启碰撞前后的函数
public is_open_func: boolean = true;
//碰撞类别
public collide_category = 0;
//碰撞筛选
public collide_mask = 0;
//缓存多边形碰撞数据
public cache_polygon_points: number[];
//绘制collide形状组件
private _debugDrawer!: Graphics;
public world_rect!: LQRect;
public collide_map: { [key: number]: { collide: LQCollide, status: 1 | 2 } } = {};
public follow_target_category: number | undefined;
private static id_maker: number = 1;
//检测绘制组件是否添加
private checkDebugDrawValid() {
if (!this._debugDrawer || !this._debugDrawer.isValid) {
let node = this.node.getChildByName('Collide');
if (!node) {
node = new Node('Collide');
node.zIndex = macro.MAX_ZINDEX;
this.node.addChild(node);
// @ts-ignore
node._objFlags = 1096;
this._debugDrawer = node.addComponent(Graphics);
this._debugDrawer.lineWidth = 3;
this._debugDrawer.strokeColor = new Color(255, 0, 0);
this._debugDrawer.fillColor = new Color(255, 0, 0);
} else {
this._debugDrawer = node.getComponent(Graphics);
}
}
}
//绘制形状
protected draw_shape() {
if (!this._draw_collide) {
if (this._debugDrawer) {
this._debugDrawer.clear();
}
return;
}
this.checkDebugDrawValid();
this._debugDrawer.clear();
let o1 = {key: 'scaleX', value: this.node.scale};
let o2 = {key: 'scaleY', value: this.node.scale};
LQGameUtil.recursion_node_property(this.node, o1);
LQGameUtil.recursion_node_property(this.node, o2);
if (o1.value === 0 || o2.value === 0) {
return;
}
this._debugDrawer.node.scaleX = 1 / o1.value;
this._debugDrawer.node.scaleY = 1 / o2.value;
switch (this._collide_shape) {
case LQCollideShape.Circle:
this._debugDrawer.circle(+this._offset.x, +this._offset.y, this._radius);
this._debugDrawer.stroke();
break;
case LQCollideShape.Rect:
this._debugDrawer.moveTo(-this._size.width * 0.5 + this._offset.x, -this._size.height * 0.5 + this._offset.y);
this._debugDrawer.lineTo(-this._size.width * 0.5 + this._offset.x, +this._size.height * 0.5 + this._offset.y);
this._debugDrawer.lineTo(this._size.width * 0.5 + this._offset.x, +this._size.height * 0.5 + this._offset.y);
this._debugDrawer.lineTo(this._size.width * 0.5 + this._offset.x, -this._size.height * 0.5 + this._offset.y);
this._debugDrawer.lineTo(-this._size.width * 0.5 + this._offset.x, -this._size.height * 0.5 + this._offset.y);
this._debugDrawer.stroke();
break;
case LQCollideShape.Polygon:
this._debugDrawer.moveTo(this._polygon_points[0].x + this._offset.x, this._polygon_points[0].y + this._offset.y);
for (let i = 1; i < this._polygon_points.length; i++) {
this._debugDrawer.lineTo(this._polygon_points[i].x + this._offset.x, this._polygon_points[i].y + this._offset.y);
}
this._debugDrawer.lineTo(this._polygon_points[0].x + this._offset.x, this._polygon_points[0].y + this._offset.y);
this._debugDrawer.stroke();
break;
}
}
//仅用于矩形
public update_size(width: number, height: number) {
this._size.width = width;
this.world_rect.width = width;
this.world_rect.half_width = width * 0.5;
this._size.height = height;
this.world_rect.height = height;
this.world_rect.half_height = height * 0.5;
this.draw_shape();
}
public init_lq_collide() {
this.world_rect = new LQRect(0, 0, this._size.width, this._size.height);
this.draw_shape();
const info = LQCollideSystem.get_info_by_id(this.collide_group_id);
this.collide_mask = info.mask;
this.collide_category = info.category;
this.collide_id = LQCollide.id_maker++;
this.updateCollisionArea();
}
private updateCollisionArea() {
if(this._size.width==0 || this._size.height==0 || MapConroler._instance == undefined){
return;
}
if(MapConroler._instance.node.scale){
let scaleX = MapConroler._instance.node.scale;
let scaleY = MapConroler._instance.node.scale;
if (scaleX === 0 || scaleX == undefined || scaleX == null || scaleX == 1) {
return;
}
switch (this._collide_shape) {
case LQCollideShape.Circle:
// 圆形碰撞区域半径更新
this._radius = this._radius * Math.max(scaleX, scaleY);
break;
case LQCollideShape.Rect:
// 矩形碰撞区域尺寸更新
// console.log(this.data_string);
if (this._size.width !== 10 && this.data_string!="-1") {
// if(this._size.width == 105 || this._size.height == 105){}
this._size.width = this._size.width * scaleX;
// console.log("放大倍数",scaleX);
}
if (this._size.height!== 10 && this.data_string!="-1") {
// if(this._size.width == 105 || this._size.height == 105){}
this._size.height = this._size.height * scaleY;
// console.log("放大倍数",scaleY);
}
// this._size.width = this._size.width * scaleX;
// this._size.height = this._size.height * scaleY;
if (this.world_rect) {
this.world_rect.width = this._size.width;
this.world_rect.height = this._size.height;
this.world_rect.half_width = this._size.width * 0.5;
this.world_rect.half_height = this._size.height * 0.5;
}
break;
case LQCollideShape.Polygon:
// 多边形碰撞点坐标更新
this._polygon_points = this._polygon_points.map(point => {
return new Vec2(point.x * scaleX, point.y * scaleY);
});
break;
}
this.draw_shape();
}
}
public enable_lq_collide() {
if (this.collide_status === LQCollideStatus.Live) {
console.warn(this.node.name + '重复添加');
return;
}
this.is_enable = true;
this.collide_status = LQCollideStatus.Live;
LQCollideSystem.add_collide(this);
}
public disable_lq_collide() {
if (this.collide_status !== LQCollideStatus.Live) {
return;
}
this.is_enable = false;
this.collide_status = LQCollideStatus.Idle;
LQCollideSystem.remove_collide(this);
}
public update_lq_collide() {
}
// @ts-ignore
// public on_collide(collide: LQCollide): void {
// if(collide.node.parent.uuid == this.node.parent.uuid){
// return;
// }
// if (LQCollideConfig.switch_print_log) {
// if(this.node.parent.getComponent("Block")){
// let block = this.node.parent.getComponent("Block");
// if(block.isTouch){
// block.checkCollision = true;
// // console.log("碰撞",this.node.name);
// if(this.node.name == "top" ){
// console.log("碰到上边缘");
// block.moveUp = false;
// if(block.touchPointY > (this.node.parent.y+this.node.height)){
// block.moveY = 1;
// }
// }
// if(this.node.name === "down"){
// block.moveDown = false;
// console.log("碰到下边缘");
// if(block.touchPointY < (this.node.parent.y )){
// block.moveY = -1;
// }
// }
// if(this.node.name === "left" ){
// block.moveLeft = false;
// console.log("碰到左边缘");
// if(block.touchPointX < (this.node.parent.x - this.node.parent.width)){
// block.moveX = -1;
// }
// }
// if(this.node.name === "right"){
// block.moveRight = false;
// console.log("碰到右边缘");
// if(block.touchPointX > (this.node.parent.x)){
// block.moveX = 1;
// }
// }
// }
// }
// }
// }
//@ts-ignore
public on_enter(collide: LQCollide) {
if(this.disableCollider(collide)){
return;
}
// if (LQCollideConfig.switch_print_log) {
// console.log(this.node.name + ' on_enter');
// }
}
//@ts-ignore
public on_exit(collide: LQCollide) {
if(this.disableCollider(collide)){
return;
}
if (LQCollideConfig.switch_print_log) {
if(this.node.parent.getComponent("Block")){
let block = this.node.parent.getComponent("Block");
// if(!block.isTouch){
// return;
// }
block.checkCollision = false;
if(this.node.name == "top" ){
block.moveUp = true;
}
if(this.node.name === "down"){
block.moveDown = true;
}
if(this.node.name === "left" ){
block.moveLeft = true;
}
if(this.node.name === "right"){
block.moveRight = true;
}
}
}
}
public on_collide(collide: LQCollide): void {
if(this.disableCollider(collide)){
return;
}
if (LQCollideConfig.switch_print_log) {
if(this.node.parent.getComponent("Block")){
let block = this.node.parent.getComponent("Block");
let jg = false;
if(block.isTouch){
block.checkCollision = true;
// console.log("碰撞",this.node.name);
if(this.node.name == "top" ){
// console.log(collide.node.parent.name);
block.moveUp = false;
if(block.touchPointY > (this.node.parent.y+this.node.parent.height)){
block.moveY = 1;
}
// console.log("碰到上边缘");
}
if(this.node.name === "down"){
block.moveDown = false;
if(block.touchPointY < (this.node.parent.y )){
block.moveY = -1;
}
// console.log("碰到下边缘");
}
if(this.node.name === "left" ){
block.moveLeft = false;
if(block.touchPointX < (this.node.parent.x - this.node.parent.width)){
block.moveX = -1;
}
}
if(this.node.name === "right"){
block.moveRight = false;
if(block.touchPointX > (this.node.parent.x)){
block.moveX = 1;
}
}
}
}
}
}
public disableCollider(collide: LQCollide){
let jg = false;
if(collide.node && this.node){
if(collide.node.parent && this.node.parent){
if(collide.node.parent.uuid == this.node.parent.uuid){
jg = true;
}
if(this.node.parent.getComponent("Block")){
let block = this.node.parent.getComponent("Block");
if(block.type == 1 || block.type == 10 || block.type == 9){
if(collide.node.parent == block.block_Info.node){
jg = true;
}
}
}
}
}
return jg;
}
}