const { ccclass, property } = cc._decorator;

@ccclass
export default class Test extends cc.Component {

    private ball1: Ball1;
    private ball2: Ball2;

    protected start(): void {
        this.ball1 = new Ball1(this.node.getChildByName("ball1"), this.node.getChildByName("center1"));
        this.ball2 = new Ball2(this.node.getChildByName("ball2"), this.node.getChildByName("center2"));
    }

    protected update(): void {
        this.ball1.step();
        this.ball2.step();
    }

}

const r = 150;
const w = Math.PI * 2 / 240;

abstract class Ball {

    protected node: cc.Node;
    protected center: cc.Node;

    public constructor(node: cc.Node, center: cc.Node) {
        this.node = node;
        this.center = center;

        let oldP: cc.Vec2;
        this.center.on(cc.Node.EventType.TOUCH_START, (evt: cc.Event.EventTouch) => {
            oldP = evt.getLocation();
        });
        this.center.on(cc.Node.EventType.TOUCH_MOVE, (evt: cc.Event.EventTouch) => {
            const p = evt.getLocation();
            this.center.x += p.x - oldP.x;
            this.center.y += p.y - oldP.y;
            oldP = p;
        });

        this.node.x = this.center.x + r;
        this.node.y = this.center.y;
    }

}

class Ball1 extends Ball {

    private rad: number;

    public constructor(node: cc.Node, center: cc.Node) {
        super(node, center);

        this.rad = 0;
    }

    public step(): void {
        this.rad = (this.rad + w) % (Math.PI * 2);
        this.node.x = this.center.x + Math.cos(this.rad) * r;
        this.node.y = this.center.y + Math.sin(this.rad) * r;
    }

}

class Ball2 extends Ball {

    private vx: number;
    private vy: number;

    public constructor(node: cc.Node, center: cc.Node) {
        super(node, center);

        this.vx = 0;
        this.vy = r * w;
    }

    public step(): void {
        const ax: number = -w * w * (this.node.x - this.center.x);
        const ay: number = -w * w * (this.node.y - this.center.y);
        this.vx += ax;
        this.vy += ay;
        this.node.x += this.vx;
        this.node.y += this.vy;
    }

}
