505 lines
18 KiB
TypeScript
505 lines
18 KiB
TypeScript
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;
|
||
}
|
||
} |