01/10/2018, 14:22

Create custom event chạm tường cho quả bóng

Bài toán của mình đặt trong tình huống là một trái banh ‘hình chữ nhật’ va chạm và phản xạ từ thành bàn. Dĩ nhiên đoạn code như thế này thì vẫn chạy tốt

            update: function () {
            this.count++;

            this.rect.x += this.rect.vx;
            this.rect.y += this.rect.vy;

            var wh = this.get_wh();
            if (this.rect.x > wh.w || this.rect.x < 0) {//su kien cham tuong dung
                this.rect.vx = -this.rect.vx;
            }

            if (this.rect.y > wh.h || this.rect.y < 0) {//su kien cham tuong ngang
                this.rect.vy = -this.rect.vy;
            }

        },

Nhưng bây giờ mình muốn cài đặt một cái sự kiện: “cham_tuong”

thì cài đặt thế nào? Trong bài toán của mình.

Toàn bộ source code như sau:

<script>

class Rect {
    constructor(x,y,w,h) {
        this.name = "Rect";
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.vx = 0;
        this.vy = 0;
    }
    draw(ctx) {
        ctx.rect(this.x,this.y,this.w,this.h);
        ctx.strokeStyle = 'blue';
        ctx.stroke();
    }
}


new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue.js!',
        count: 0,
        rect:null,
    },
    mounted: function () {
        var canvas = this.get_canvas();
        var wh = { w: canvas.width, h: canvas.height }
        this.draw_rec(0, 0, wh.w, wh.h, 'blue');


        this.rect = new Rect(0, 0, 20, 10);
        this.rect.vx = 1;
        this.rect.vy = 1;

        this.run();

        var el = this.$el;
        $(el).find("canvas").bind('click', this.on_click);

        //code here
        //var event = new Event('cham_tuong');
        //$(el).find("canvas").dispatchEvent(event);
        //$(el).find("canvas").bind('cham_tuong', this.on_cham_tuong);
        //end code here

    },
    methods: {
        get_canvas: function () {
            var el = this.$el;
            var canvas = $(el).find("canvas")[0];
            return canvas;
        },
        get_ctx: function () {
            var el = this.$el;
            var ctx = $(el).find("canvas")[0].getContext('2d');
            return ctx;
        },
        get_wh: function () {
            var canvas = this.get_canvas();
            var wh = { w: canvas.width, h: canvas.height }
            return wh;
        },
        on_click: function (e) {
            //alert('click')
            var x = e.offsetX;
            var y = e.offsetY;
            this.rect.x = x;
            this.rect.y = y;
        },
        on_cham_tuong: function () {
            alert('hi');
        },
        draw_rec: function (x1, y1, x2, y2, color) {
            var ctx = this.get_ctx()
            ctx.beginPath();
            ctx.rect(x1, y1, x2, y2);
            ctx.strokeStyle = color;
            ctx.stroke();
        },
        draw_rec_fill: function (x1, y1, x2, y2, color, fill) {
            var ctx = this.get_ctx()
            ctx.beginPath();
            ctx.strokeStyle = color;
            ctx.fillStyle = fill;
            ctx.fillRect(x1, y1, x2, y2);
        },

        draw: function () {
            this.message = this.count;
            var ctx = this.get_ctx()

            this.draw_rec_fill(0, 0, this.get_wh().w, this.get_wh().h, 'red', 'yellow');
            this.rect.draw(ctx);

        },
        update: function () {
            this.count++;

            this.rect.x += this.rect.vx;
            this.rect.y += this.rect.vy;

            var wh = this.get_wh();
            if (this.rect.x > wh.w || this.rect.x < 0) {//su kien cham tuong dung
                this.rect.vx = -this.rect.vx;
            }

            if (this.rect.y > wh.h || this.rect.y < 0) {//su kien cham tuong ngang
                this.rect.vy = -this.rect.vy;
            }

        },
        run: function () {
            var that = this;
            (function tick() {
                that.update();
                that.draw();
                setTimeout(function () { that.run(); }, 37);
            })();
        }
    }


})

Minh họa giao dien thế này

voss viết 16:27 ngày 01/10/2018

Ngưỡng mộ quá, mình tập tành làm mấy cái đơn giản đã thấy khoai rồi

Thuc Nguyen Tan viết 16:23 ngày 01/10/2018

Để anh chị dễ support em copy luôn cái phần html

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
            <div>{{ message }}</div>
            <canvas width="200" height="100"></canvas>
</div>
voss viết 16:27 ngày 01/10/2018

Mình không biết nhiều về javascript nhưng bạn thử nghĩ đến sét điệu kiện chạm tường thì tọa độ của đường viền hình vuông nhỏ trùng tọa độ đường viền của cái bàn. Về phản xạ thì góc phản xạ bằng góc tới. Thử theo hướng đó thử xem.

Thuc Nguyen Tan viết 16:23 ngày 01/10/2018

https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

document thì có rất nhiều nhưng mình không biết cài đặt thế nào!!!

Trần Minh Thắng viết 16:31 ngày 01/10/2018

Nếu hàm update của bạn được gọi liên tục theo thời gian thì xem qua thử hướng dùng Swept AABB, trên gamedev có 1 bài, nó dùng để xác định 2 vật thể di chuyển có vận tốc có va chạm nhau không theo hướng tổng quát.

Thuc Nguyen Tan viết 16:23 ngày 01/10/2018
var event = new Event('cham_tuong');
//còn một cái gọi là dispatchEvent(event) ở khúc này không biết viết thế nào????
this.rect.addEventListener('cham_tuong',function(event){
})
Thuc Nguyen Tan viết 16:29 ngày 01/10/2018

optimize như thế này cũng ok như xem có vẽ ngớ ngẫn

        update: function () {
            this.count++;

            this.rect.x += this.rect.vx;
            this.rect.y += this.rect.vy;

            var wh = this.get_wh();
            if (this.rect.x > wh.w || this.rect.x < 0) {//su kien cham tuong dung

                $(document).trigger("cham_tuong_dung", { vx: this.rect.vx, vy: this.rect.vy });
                //khi nào chạm tường đứng thì phát ra một event cham_tuong_dung với thông tin vx,vy
                //this.rect.vx = -this.rect.vx;

            }

            if (this.rect.y > wh.h || this.rect.y < 0) {//su kien cham tuong ngang
                $(document).trigger("cham_tuong_ngang", { vx: this.rect.vx, vy: this.rect.vy });
                //this.rect.vy = -this.rect.vy;
            }

        },




        mounted: function () {
        var canvas = this.get_canvas();
        var wh = { w: canvas.width, h: canvas.height }
        this.draw_rec(0, 0, wh.w, wh.h, 'blue');


        this.rect = new Rect(0, 0, 20, 10);
        this.rect.vx = 1;
        this.rect.vy = 1;

        this.run();

        var el = this.$el;
        $(el).find("canvas").bind('click', this.on_click);


        var that = this;
        $(document).on("cham_tuong_dung", function (event, data) {
            //console.log(data);//Object { vx: -1, vy: -1 }
            //hehe this.rect đã chạm tường đứng với vx:-1,vy:-1
            that.rect.vx=-data.vx
        });
        $(document).on("cham_tuong_ngang", function (event, data) {
            //console.log(data);//Object { vx: -1, vy: -1 }
            //hehe this.rect đã chạm tường đứng với vx:-1,vy:-1
            that.rect.vy = -data.vy
        });

    },

uh sao lại trigger vào document, mình muốn trigger vào đối tượng Rect, làm sao đây?

Thuc Nguyen Tan viết 16:35 ngày 01/10/2018

đoạn code thế này lại tiếp tục ok

        mounted: function () {
        var canvas = this.get_canvas();
        var wh = { w: canvas.width, h: canvas.height }
        this.draw_rec(0, 0, wh.w, wh.h, 'blue');


        this.rect = new Rect(0, 0, 20, 10);
        this.rect.vx = 1;
        this.rect.vy = 1;

        this.run();

        var el = this.$el;
        $(el).find("canvas").bind('click', this.on_click);


        var that = this;
        //$(document).on("cham_tuong_dung", function (event, data) {
        //    //console.log(data);//Object { vx: -1, vy: -1 }
        //    //hehe this.rect đã chạm tường đứng với vx:-1,vy:-1
        //    that.rect.vx=-data.vx
        //});
        //$(document).on("cham_tuong_ngang", function (event, data) {
        //    //console.log(data);//Object { vx: -1, vy: -1 }
        //    //hehe this.rect đã chạm tường đứng với vx:-1,vy:-1
        //    that.rect.vy = -data.vy
        //});

        $(this.rect).on("cham_tuong_dung2", function (e, data) {
            //console.log(data)
            that.rect.vx = -data.vx
        })
        $(this.rect).on("cham_tuong_ngang2", function (event, data) {
            //console.log(data);//Object { vx: -1, vy: -1 }
            //hehe this.rect đã chạm tường đứng với vx:-1,vy:-1
            that.rect.vy = -data.vy
        });


    },





            update: function () {
            this.count++;

            this.rect.x += this.rect.vx;
            this.rect.y += this.rect.vy;

            var wh = this.get_wh();
            if (this.rect.x > wh.w || this.rect.x < 0) {//su kien cham tuong dung

                //$(document).trigger("cham_tuong_dung", { vx: this.rect.vx, vy: this.rect.vy });
                //khi nào chạm tường đứng thì phát ra một event cham_tuong_dung với thông tin vx,vy
                //this.rect.vx = -this.rect.vx;
                $(this.rect).trigger("cham_tuong_dung2", { vx: this.rect.vx, vy: this.rect.vy})

            }

            if (this.rect.y > wh.h || this.rect.y < 0) {//su kien cham tuong ngang
                //$(document).trigger("cham_tuong_ngang", { vx: this.rect.vx, vy: this.rect.vy });
                //this.rect.vy = -this.rect.vy;
                $(this.rect).trigger("cham_tuong_ngang2", { vx: this.rect.vx, vy: this.rect.vy })
            }

        },

hum, làm sao đẩy cái đống hầm bà lần này vào trong class của nó luôn…??? Bí rồi, help

Thuc Nguyen Tan viết 16:31 ngày 01/10/2018

hum, cuối cùng cũng đẩy được nó vào lớp khởi tạo. Nhờ một lá bùa copy từ mạng…

    var events = new function () {
    var _triggers = {};

    this.on = function (event, callback) {
        if (!_triggers[event])
            _triggers[event] = [];
        _triggers[event].push(callback);
    }

    this.triggerHandler = function (event, params) {
        if (_triggers[event]) {
            for (i in _triggers[event])
                _triggers[event][i](params);
        }
    }
};
Thuc Nguyen Tan viết 16:36 ngày 01/10/2018

full source sẽ là thế này.

<script>


var events = new function () {
    var _triggers = {};

    this.on = function (event, callback) {
        if (!_triggers[event])
            _triggers[event] = [];
        _triggers[event].push(callback);
    }

    this.triggerHandler = function (event, params) {
        if (_triggers[event]) {
            for (i in _triggers[event])
                _triggers[event][i](params);
        }
    }
};



class Rect {
    constructor(x,y,w,h) {
        this.name = "Rect";
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.vx = 0;
        this.vy = 0;
    }
    draw(ctx) {
        ctx.rect(this.x,this.y,this.w,this.h);
        ctx.strokeStyle = 'blue';
        ctx.stroke();
    }
    Cham_tuong_dung3(ww,hh) {
        if (this.x > ww || this.x < 0) {//su kien cham tuong dung
            events.triggerHandler('cham_tuong_dung3', [this.vx,this.vy]);
        }
    }
    Cham_tuong_ngang3(ww, hh) {
        if (this.y > hh || this.y < 0) {//su kien cham tuong dung
            events.triggerHandler('cham_tuong_ngang3', [this.vx, this.vy]);
        }
    }
}


new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue.js!',
        count: 0,
        rect:null,
    },
    mounted: function () {
        var canvas = this.get_canvas();
        var wh = { w: canvas.width, h: canvas.height }
        this.draw_rec(0, 0, wh.w, wh.h, 'blue');

        this.rect = new Rect(0, 0, 20, 10);
        this.rect.vx = 1;
        this.rect.vy = 1;

        this.run();

        var el = this.$el;
        $(el).find("canvas").bind('click', this.on_click);

        var that = this;

        events.on('cham_tuong_dung3', function (data) {
            that.rect.vx = -data[0]
        });
        events.on('cham_tuong_ngang3', function (data) {
            that.rect.vy = -data[1]
        });

    },
    methods: {
        get_canvas: function () {
            var el = this.$el;
            var canvas = $(el).find("canvas")[0];
            return canvas;
        },
        get_ctx: function () {
            var el = this.$el;
            var ctx = $(el).find("canvas")[0].getContext('2d');
            return ctx;
        },
        get_wh: function () {
            var canvas = this.get_canvas();
            var wh = { w: canvas.width, h: canvas.height }
            return wh;
        },
        on_click: function (e) {
            //alert('click')
            var x = e.offsetX;
            var y = e.offsetY;
            this.rect.x = x;
            this.rect.y = y;
        },
        on_cham_tuong: function () {
            alert('hi');
        },
        draw_rec: function (x1, y1, x2, y2, color) {
            var ctx = this.get_ctx()
            ctx.beginPath();
            ctx.rect(x1, y1, x2, y2);
            ctx.strokeStyle = color;
            ctx.stroke();
        },
        draw_rec_fill: function (x1, y1, x2, y2, color, fill) {
            var ctx = this.get_ctx()
            ctx.beginPath();
            ctx.strokeStyle = color;
            ctx.fillStyle = fill;
            ctx.fillRect(x1, y1, x2, y2);
        },

        draw: function () {
            this.message = this.count;
            var ctx = this.get_ctx()

            this.draw_rec_fill(0, 0, this.get_wh().w, this.get_wh().h, 'red', 'yellow');
            this.rect.draw(ctx);

        },
        update: function () {
            this.count++;

            this.rect.x += this.rect.vx;
            this.rect.y += this.rect.vy;

            var wh = this.get_wh();
            this.rect.Cham_tuong_dung3(wh.w, wh.h);
            this.rect.Cham_tuong_ngang3(wh.w, wh.h);

        },
        run: function () {
            var that = this;
            (function tick() {
                that.update();
                that.draw();
                setTimeout(function () { that.run(); }, 37);
            })();
        }
    }

})
Thuc Nguyen Tan viết 16:29 ngày 01/10/2018

Cuối cùng là trên plunker

https://plnkr.co/edit/BYLDrl?p=preview

wait for góp ý gần xa…

voss viết 16:29 ngày 01/10/2018

Chúc mừng bạn

Bài liên quan
0