<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Vinh's Blog</title>
    <description>Xin chào, mình tên là Lưu Thế Vinh. Mình thích Lập trình, làm Game và cũng tập tành Thiết kế mấy thứ linh tinh.
</description>
    <link>https://luuthevinh.me/</link>
    <atom:link href="https://luuthevinh.me/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 03 Sep 2022 15:57:11 +0000</pubDate>
    <lastBuildDate>Sat, 03 Sep 2022 15:57:11 +0000</lastBuildDate>
    <generator>Jekyll v3.9.2</generator>
    
      <item>
        <title>Random Unity tips #1</title>
        <description>&lt;p&gt;Xin chào các bạn, tip đầu tiên là về Unity animation bị lỗi &lt;em&gt;GameObject or Component is missing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Để fix trường hợp bị &lt;strong&gt;Missing&lt;/strong&gt; do bạn thay đổi cấu trúc/tên GameObject trong animation, bạn có thể nhấn &lt;strong&gt;F2&lt;/strong&gt; để đổi tên lại, thêm dấu &lt;strong&gt;/&lt;/strong&gt; tương ứng với cấu trúc mới để fix lỗi này.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/unity-tips/animation-1.png&quot; alt=&quot;Lỗi GameObject or Component is missing&quot; title=&quot;Lỗi GameObject or Component is missing&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Đổi tên cho đúng&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/unity-tips/animation-2.png&quot; alt=&quot;Đổi tên&quot; title=&quot;Đổi tên fix lỗi GameObject or Component is missing&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Đơn giản vậy thôi ;)&lt;/p&gt;

</description>
        <pubDate>Sat, 03 Sep 2022 14:42:18 +0000</pubDate>
        <link>https://luuthevinh.me/2022/09/random-unity-tips-1</link>
        <guid isPermaLink="true">https://luuthevinh.me/2022/09/random-unity-tips-1</guid>
        
        <category>unity</category>
        
        <category>tips</category>
        
        <category>animation</category>
        
        <category>animator</category>
        
        
        <category>bai-viet</category>
        
      </item>
    
      <item>
        <title>Xét và xử lý va chạm bằng Swept AABB</title>
        <description>&lt;p&gt;Xin chào các bạn, bài viết hôm nay mình sẽ giới thiệu cho các bạn về xử lý va chạm trong game bằng &lt;strong&gt;Swept AABB&lt;/strong&gt;. Khi các bạn tự viết framework có phần xử lý va chạm thì có thể sử dụng phương pháp này.&lt;/p&gt;

&lt;h2 id=&quot;aabb-là-gì&quot;&gt;AABB là gì?&lt;/h2&gt;
&lt;p&gt;AABB là viết tắt của Axis-Aligned Bounding Box, nó là thuật toán xét va chạm giữa các cạnh của &lt;strong&gt;hình chữ nhật&lt;/strong&gt; mà ở đây các cạnh này nó &lt;strong&gt;song song&lt;/strong&gt; với cùng &lt;strong&gt;hệ trục tọa độ&lt;/strong&gt;. Vậy cơ bản là xét xem 2 hình chữ nhật nó có chồng lên nhau hay không.&lt;/p&gt;

&lt;h2 id=&quot;swept-aabb&quot;&gt;Swept AABB?&lt;/h2&gt;
&lt;p&gt;Với Swept AABB, chúng ta sẽ xem trước ở frame kế tiếp hình chữ nhật mình có va chạm hay không. Có thì mình xử lý nó theo ý mình muốn.&lt;/p&gt;

&lt;h1 id=&quot;ví-dụ&quot;&gt;Ví dụ:&lt;/h1&gt;
&lt;p&gt;Ở &lt;strong&gt;frame đầu tiên&lt;/strong&gt;, hình chữ nhật chưa có va chạm, &lt;strong&gt;frame tiếp theo&lt;/strong&gt; hình chữ nhật di chuyển 1 đoạn và va chạm với thanh màu xanh. Mình sẽ dự đoán trước và quyết định vị trí kế tiếp của nó, như ở đây nó sẽ đi đoạn ngắn hơn thay vì như bình thường sẽ là ở vị trí nét đứt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/swept-aabb-01.png&quot; alt=&quot;ví dụ swept aabb&quot; title=&quot;Ví dụ Swept AABB&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;xét-va-chạm-aabb&quot;&gt;Xét va chạm AABB&lt;/h2&gt;

&lt;p&gt;Để xem 2 hình chữ nhật có va chạm hay không thì mình sẽ xét từng cặp cạnh của 2 hình như sau:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/swept-aabb-03.png&quot; alt=&quot;ví dụ 2 hình chữ nhật va chạm với nhau&quot; title=&quot;2 hình chữ nhật chồng lấp lên nhau&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Các bạn để ý sẽ thấy, khi 2 hình đè lên nhau thì mình luôn có &lt;strong&gt;ĐỒNG THỜI&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;other.left &amp;lt;= object.right&lt;/li&gt;
  &lt;li&gt;other.right &amp;gt;= object.left&lt;/li&gt;
  &lt;li&gt;other.top  &amp;gt;= object.bottom&lt;/li&gt;
  &lt;li&gt;other.bottom &amp;lt;= object.top&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Như vậy nếu &lt;strong&gt;1 trong 4&lt;/strong&gt; điều kiện trên &lt;strong&gt;sai&lt;/strong&gt; thì 2 hình &lt;strong&gt;không có va chạm&lt;/strong&gt; với nhau.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/swept-aabb-02.png&quot; alt=&quot;ví dụ 2 hình chữ nhật chưa va chạm&quot; title=&quot;2 hình chữ nhật không chồng lấp lên nhau&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ví dụ ở đây ta có &lt;strong&gt;left&lt;/strong&gt; của &lt;strong&gt;other&lt;/strong&gt; lớn hơn &lt;strong&gt;right&lt;/strong&gt; của &lt;strong&gt;object&lt;/strong&gt;, nên không có va chạm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tất cả ví dụ mình lấy gốc tọa độ là bottom-left&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hàm xét va chạm có thể viết đơn giản như sau:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/68db8232903c82ea4256242242d7d391.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Ở trên, mình có hàm kiểm tra hai Rect có va chạm với nhau hay không, mình lấy điều kiện ngược lại cho gọn hơn.&lt;/p&gt;

&lt;h2 id=&quot;xét-va-chạm-với-swept-aabb&quot;&gt;Xét va chạm với Swept AABB&lt;/h2&gt;

&lt;p&gt;Đầu tiên, mình tìm khoảng cách giữa các cạnh của hai hình&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/swept-aabb-04.png&quot; alt=&quot;ví dụ 2 hình chữ nhật chưa va chạm&quot; title=&quot;Khoảng cách giữa các cạnh để tính thời gian với vận tốc cho Swept AABB&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Trong đó,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;dxEntry&lt;/strong&gt;, &lt;strong&gt;dyEntry&lt;/strong&gt;: là khoảng cách cần đi để các bắt đầu va chạm.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;dxExit&lt;/strong&gt;, &lt;strong&gt;dyExit&lt;/strong&gt;: là khoảng cách cần đi kể từ lúc này để khi hết va chạm.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nó cũng như top, left, right, bottom của AABB cơ bản phía trên. Mình xét thêm hướng của vận tốc, để nó đồng bộ với dấu lúc sau tính thời gian không ngược khi có va chạm.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/5a4c3e6aae21f7fd67b6e9caee30bc7e.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Tiếp theo, từ khoảng cách và vận tốc, mình tìm thời gian để bắt đầu và kết thúc va chạm:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;thời gian = quãng đường / vận tốc&lt;/p&gt;
&lt;/blockquote&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/112130880384f8e5a11207d7ab403cfd.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Để xảy ra va chạm, cả hai trục x và y phải &lt;strong&gt;ĐỒNG THỜI XẢY RA VA CHẠM&lt;/strong&gt;, vậy mình lấy thời gian bắt để đầu va chạm &lt;strong&gt;lớn nhất&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Còn khi hết va chạm, chỉ cần 1 trong 2 trục thoát khỏi là được, nên mình lấy thời gian kết thúc va chạm &lt;strong&gt;nhỏ nhất&lt;/strong&gt; giữa 2 trục x, y.&lt;/p&gt;

&lt;div align=&quot;center&quot; style=&quot;margin-bottom: 20px;&quot;&gt;&lt;img src=&quot;http://i.giphy.com/3oz8xAmf8Tsid9dCqk.gif&quot; alt=&quot;ví dụ 2 hình chữ nhật bắt đầu xảy ra va chạm&quot; title=&quot;Ví dụ hai hình chữ nhật bắt đầu xảy ra va chạm&quot; /&gt;&lt;/div&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/023f87bcf897174ca61ad4a13147d572.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Có được thời gian rồi thì mình bắt đầu xét va chạm:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Lớn hơn 1.0f&lt;/strong&gt;: frame tiếp theo nó vẫn chưa thể va chạm.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Thời gian để kết thúc va chạm nhỏ hơn 0.0f&lt;/strong&gt;: 2 hình chữ nhật đang đi ra xa nhau.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Thời gian để kết thúc va chạm phải lớn hơn thời gian để va chạm&lt;/strong&gt; (va chạm xong rồi thì sau đó mới hết chứ đúng không).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Khi có thể va chạm mình sẽ trả về thời gian va chạm đó, còn không trả về 1.0f&lt;/p&gt;

&lt;h1 id=&quot;xử-lý-va-chạm&quot;&gt;Xử lý va chạm&lt;/h1&gt;

&lt;p&gt;Dựa vào thời gian trả về, mình tính quãng đường đi tiếp theo&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/333075430d03eed557da61e274d63f1f.js&quot;&gt;&lt;/script&gt;

&lt;h1 id=&quot;broad-phasing&quot;&gt;Broad-Phasing&lt;/h1&gt;

&lt;p&gt;Tối ưu một tí, mình dùng &lt;strong&gt;Broad-Phasing&lt;/strong&gt; để xét xem nó có thể va chạm trong frame tiếp theo không, không thì mình return luôn cho nhanh.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/swept-aabb-05.png&quot; alt=&quot;ví dụ Broad-Phasing&quot; title=&quot;Ví dụ Broad-Phasing&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mình tạo 1 hình chữ nhật dựa trên &lt;strong&gt;vị trí ban đầu&lt;/strong&gt; và &lt;strong&gt;kế tiếp&lt;/strong&gt;, sau đó lấy hình chữ nhật đó xét xem có chồng lên với hình kia không. Nếu có thì va chạm, còn không thì chắc chắn không thể nên không cần xét tiếp.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/ebf18994458598428835c8d095767356.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Cuối cùng là thêm vào phần đầu của hàm xét va chạm&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/c0de3dc33d96267537d5ecc8f28175a4.js&quot;&gt;&lt;/script&gt;

&lt;h1 id=&quot;kiểm-tra-hướng-va-chạm&quot;&gt;Kiểm tra hướng va chạm&lt;/h1&gt;

&lt;p&gt;Mình dựa vô vị trí của object để suy ra hướng&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/6d9422f2f885b7f248725921b2fdef2d.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Cơ bản xét va chạm chỉ cần thế thôi, từ đây thì các bạn có thể dùng cho các trường hợp cụ thể mà chỉnh sửa thêm cho phù hợp với nó.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Trường hợp 2 vật di chuyển, các bạn tính lại vận tốc của &lt;strong&gt;object&lt;/strong&gt; so với &lt;strong&gt;other&lt;/strong&gt; là được, xem object di chuyển còn other đứng yên.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Full code các bạn có thể xem ở đây: &lt;a href=&quot;https://gist.github.com/luuthevinh/42227ad9712e86ab9d5c3ab37a56936c&quot;&gt;Swept AABB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bài viết tham khảo: &lt;a href=&quot;http://www.gamedev.net/page/resources/_/technical/game-programming/swept-aabb-collision-detection-and-response-r3084&quot;&gt;Swept AABB Collision Detection and Response&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Các bạn có thắc mắc hay phát hiện sai sót gì thì comment bên dưới nhé.&lt;/p&gt;

&lt;p&gt;Cám ơn và hẹn gặp lại.&lt;/p&gt;

</description>
        <pubDate>Mon, 28 Nov 2016 01:50:14 +0000</pubDate>
        <link>https://luuthevinh.me/2016/11/xet-va-xu-ly-va-cham-bang-swept-aabb</link>
        <guid isPermaLink="true">https://luuthevinh.me/2016/11/xet-va-xu-ly-va-cham-bang-swept-aabb</guid>
        
        <category>aabb</category>
        
        <category>swept-aabb</category>
        
        <category>collision</category>
        
        <category>game</category>
        
        
        <category>bai-viet</category>
        
      </item>
    
      <item>
        <title>Ghép khung vào hình với Canvas trong HTML5</title>
        <description>&lt;p&gt;Xin chào các bạn,&lt;/p&gt;

&lt;p&gt;Trong bài này mình sẽ hướng dẫn các bạn cách ghép hình bằng Canvas trong HTML5, cụ thể ở đây mình ghép khung vào hình mà mình chọn từ máy lên. Các bạn có thể xem &lt;a href=&quot;http://luuthevinh.me/up-2016/&quot; target=&quot;_blank&quot;&gt;demo&lt;/a&gt; ở đây.&lt;/p&gt;

&lt;h1 id=&quot;ý-tưởng-ghép-khung-vào-hình&quot;&gt;Ý tưởng ghép khung vào hình&lt;/h1&gt;

&lt;p&gt;Ý tưởng cơ bản là mình vẽ lần lượt hai hình lên canvas, sau đó di chuyển, phóng to thu nhỏ hay xoay hình rồi cho tải về là xong. Rất đơn giản phải không?&lt;/p&gt;

&lt;h1 id=&quot;vẽ-khung-hình&quot;&gt;Vẽ khung hình&lt;/h1&gt;

&lt;p&gt;Trong file html, các bạn thêm các thẻ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;input&amp;gt;&lt;/code&gt; và &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;img&amp;gt;&lt;/code&gt; như sau:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/d964d1aa6c4d41f7379e93c036cb3de3.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Trong đó,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Thẻ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canvas&lt;/code&gt; để mình sử dụng vẽ hình.&lt;/li&gt;
  &lt;li&gt;Thẻ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;img&lt;/code&gt; dùng để chứa hình mà mình tải lên.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tiếp theo, các bạn tạo file js để code một số xử lý hình ảnh.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/a9df7f342273e3597764778bc44389b4.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Mình lấy các đối tượng trong HTML như &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canvas&lt;/code&gt; và &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; và tạo các biến cơ bản. Sau đó tạo đối tượng &lt;strong&gt;frame&lt;/strong&gt; là khung hình muốn ghép.&lt;/p&gt;

&lt;p&gt;Ở hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onload&lt;/code&gt; của &lt;strong&gt;frame&lt;/strong&gt;, mình vẽ khung hình lên context.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/4c65e552d45f7afa44b223852691b5aa.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Ban đầu đơn giản chỉ xóa canvas rồi vẽ frame hình lên trước, các bạn có thể xem thêm hàm &lt;a href=&quot;http://www.w3schools.com/tags/canvas_drawimage.asp&quot; target=&quot;_blank&quot;&gt;drawImage()&lt;/a&gt;, &lt;a href=&quot;http://www.w3schools.com/tags/canvas_clearrect.asp&quot; target=&quot;_blank&quot;&gt;clearRect()&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;load-hình&quot;&gt;Load hình&lt;/h1&gt;

&lt;p&gt;Tiếp theo mình sẽ load hình lên.&lt;/p&gt;

&lt;p&gt;Trong file HTML các bạn thêm thẻ &lt;strong&gt;input&lt;/strong&gt; để up hình.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/d625116940380a89ccbb30b295fe5045.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Viết sự kiện &lt;strong&gt;change&lt;/strong&gt; cho input.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/7ab371366a07171c034fbbdff515fc07.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Khi hình được load lên, mình sử dụng &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileReader&lt;/code&gt; để đọc dữ liệu từ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt; và cập nhật lại source hình từ dữ liệu đó cho đối tượng &lt;strong&gt;userImage&lt;/strong&gt;.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/7c04012eb70ea135c5177af3851bfba6.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Ở hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onload&lt;/code&gt; của &lt;strong&gt;userImage&lt;/strong&gt;, mình sẽ tìm cạnh nhỏ nhất để scale hình cho vừa với khung. Và lưu giá trị vào &lt;strong&gt;minScale&lt;/strong&gt; để giới hạn giá trị scale. (mình thích không cho người ta scale nhỏ hơn canvas thôi).&lt;/p&gt;

&lt;p&gt;Giờ mình có hình rồi nên ta cập nhật thêm cho hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawCurrentImage()&lt;/code&gt;&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/91d6452a1eb970fdd8414f356a095e57.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Các bạn &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;save()&lt;/code&gt; context hiện tại trước khi thay đổi để vẽ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;userImage&lt;/code&gt;, rồi nhớ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;restore()&lt;/code&gt; để trả về mặc định cho context trước khi vẽ cái khác.&lt;/p&gt;

&lt;p&gt;Để vẽ theo tâm của hình (origin là tâm của hình), mình dùng cách &lt;a href=&quot;http://www.w3schools.com/TAgs/canvas_translate.asp&quot; target=&quot;_blank&quot;&gt;translate()&lt;/a&gt; chuyển hình đến tọa độ mong muốn. Sau đó khi vẽ bằng &lt;a href=&quot;http://www.w3schools.com/tags/canvas_drawimage.asp&quot; target=&quot;_blank&quot;&gt;drawImage()&lt;/a&gt;, ta vẽ lùi về một nữa kích thước ngang, dọc của hình.&lt;/p&gt;

&lt;p&gt;Và mình dùng &lt;a href=&quot;http://www.w3schools.com/tags/canvas_rotate.asp&quot; target=&quot;_blank&quot;&gt;rotate()&lt;/a&gt;, &lt;a href=&quot;http://www.w3schools.com/tags/canvas_scale.asp&quot; target=&quot;_blank&quot;&gt;scale()&lt;/a&gt; để gán các giá trị tương ứng cho context.&lt;/p&gt;

&lt;h1 id=&quot;di-chuyển&quot;&gt;Di chuyển&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Ý tưởng:&lt;/strong&gt; mỗi khi chuột di chuyển mình sẽ tính toán độ thay đổi của chuột so với lần trước rồi cập nhật lại vị trí của hình.&lt;/p&gt;

&lt;p&gt;Các bạn thêm các biến như bên dưới và các sự kiện &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mousedown&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mousemove&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseup&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseout&lt;/code&gt; cho canvas.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/2c09826a28f759c769fb3885c3a1bfa7.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Ở sự kiện cho &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mousemove&lt;/code&gt;, ta cập nhật vị trí hiện tại của hình với độ thay đổi của chuột. Các sự kiện &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseup&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mousedown&lt;/code&gt; và &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mouseout&lt;/code&gt; để xác định trạng thái kéo thả hình.&lt;/p&gt;

&lt;p&gt;Mình thêm giới hạn cho tọa đổ để không kéo hình lệch xa quá, chỉ cho nó vừa khung và di chuyển hết hình thôi.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/425df3941532cbc426ad8a63ed483bd8.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Các bạn thêm vào hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drawCurrentImage()&lt;/code&gt;, mình tính phần dư của hình so với canvas, phần này sẽ là giới hạn di chuyển của tọa độ. Nếu tọa độ thấp hơn hoặc lớn hơn thì mình không cho phép vượt qua.&lt;/p&gt;

&lt;h1 id=&quot;thay-đổi-giá-trị-scale&quot;&gt;Thay đổi giá trị scale&lt;/h1&gt;

&lt;p&gt;Với giá trị scale, ta thêm thanh &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;range&lt;/code&gt; để kéo thay đổi giá trị vào HTML như sau&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/3417b5ea8e127b78bf2e1fa429729bec.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Mỗi lần thay đổi giá trị, mình cập nhật lại &lt;strong&gt;imageScale&lt;/strong&gt; với giá trị của &lt;strong&gt;scaleBar&lt;/strong&gt;.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/c0ddc61608e6c66b0d0346e083b3189d.js&quot;&gt;&lt;/script&gt;

&lt;h1 id=&quot;thay-đổi-góc-xoay&quot;&gt;Thay đổi góc xoay&lt;/h1&gt;

&lt;p&gt;Để thay đổi góc xoay, các bạn thêm vào file HTML hai nút xoay trái/phải.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/f330a5f1a452f05db37e5894b513eef4.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/8dbd97397b6eb60a91e6c8f38818159d.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Mỗi lần bấm nút xoay hình, mình cộng / trừ góc xoay cho 90 độ, và đổi width, height của hình cho nhau. Sau đó là vẽ lại hình.&lt;/p&gt;

&lt;h1 id=&quot;tải-hình&quot;&gt;Tải hình&lt;/h1&gt;

&lt;p&gt;Để tải hình, mình gán sự kiện &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;click&lt;/code&gt; cho nút download, dùng hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toDataURL()&lt;/code&gt; để lấy dữ liệu của canvas và tải xuống.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/luuthevinh/c656454778d77648b8600c9a6bf2f093.js&quot;&gt;&lt;/script&gt;

&lt;h1 id=&quot;tổng-kết&quot;&gt;Tổng kết&lt;/h1&gt;

&lt;p&gt;Vậy là xong các chức năng cơ bản của việc ghép khung vào hình, các bạn có thể phát triển thêm như là xoay hình, phóng to thu nhỏ, chọn frame… Còn lại là các thứ như là css lại giao diện theo ý các bạn thôi.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/luuthevinh/up-2016&quot; target=&quot;_blank&quot;&gt;Full Source code của project.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bài viết này mình cũng đang tìm hiểu về Javascript, nên nếu có gì sai sót các bạn có thể góp ý thêm nha. Bạn nào có sử dụng lại nhớ báo mình cho mình biết nhé.&lt;/p&gt;

&lt;p&gt;Hẹn gặp lại các bạn.&lt;/p&gt;

&lt;h1 id=&quot;cập-nhật&quot;&gt;Cập nhật&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;3/10/2016: cập nhật scale hình ảnh&lt;/li&gt;
  &lt;li&gt;11/2/2017: cập nhật xoay hình ảnh&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 20 Jul 2016 00:00:00 +0000</pubDate>
        <link>https://luuthevinh.me/2016/07/ghep-khung-vao-hinh-voi-canvas-trong-html5</link>
        <guid isPermaLink="true">https://luuthevinh.me/2016/07/ghep-khung-vao-hinh-voi-canvas-trong-html5</guid>
        
        <category>canvas</category>
        
        <category>ghep-hinh</category>
        
        <category>html</category>
        
        <category>html5</category>
        
        <category>javascript</category>
        
        
        <category>bai-viet</category>
        
      </item>
    
      <item>
        <title>Sử dụng bit flags để lưu giá trị</title>
        <description>&lt;h1 id=&quot;bit-flags-là-gì&quot;&gt;Bit flags là gì?&lt;/h1&gt;
&lt;p&gt;Sử dụng bit flags là cách chúng ta sử dụng &lt;strong&gt;thứ tự các bit&lt;/strong&gt; của biến được lưu trong bộ nhớ để quy định &lt;strong&gt;một loại giá trị&lt;/strong&gt;. Từ đó mình có thể lưu được nhiều giá trị nhưng chỉ cần một biến.&lt;/p&gt;

&lt;p&gt;Ví dụ ta có kiểu enum quy định các loại giá trị như thế này để sử dụng bit flags.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;TOP&lt;/span&gt; 	&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;		&lt;span class=&quot;c1&quot;&gt;// 0001&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;LEFT&lt;/span&gt; 	&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;		&lt;span class=&quot;c1&quot;&gt;// 0010&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;BOTTOM&lt;/span&gt; 	&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;		&lt;span class=&quot;c1&quot;&gt;// 0100&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;RIGHT&lt;/span&gt; 	&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;		&lt;span class=&quot;c1&quot;&gt;// 1000&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Các bạn thấy giá trị của các enum này nếu là cơ số 2 thì mỗi loại có bit 1 ở vị trí khác nhau.&lt;/p&gt;

&lt;p&gt;Bây giờ các bạn có một biến để lưu hướng như theo ví dụ trên:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_direction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;thêm-một-giá-trị&quot;&gt;Thêm một giá trị&lt;/h1&gt;

&lt;p&gt;Bình thường bạn gán một giá trị cho nó như thế này.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;_direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TOP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vậy khi bạn muốn gán nhiều giá trị cho một biến, bạn chỉ cần sử dụng phép OR để gán thêm cho nó.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;_direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LEFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Khi đó giá trị biến &lt;strong&gt;_direction&lt;/strong&gt; sẽ trở thành &lt;strong&gt;0011&lt;/strong&gt;, có thể hiểu nó được bật 2 cờ tại các giá trị tương ứng là &lt;strong&gt;TOP và LEFT&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;mo&quot;&gt;0001&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;OR&lt;/span&gt;	&lt;span class=&quot;mo&quot;&gt;0010&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;	&lt;span class=&quot;mo&quot;&gt;0011&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;kiểm-tra-giá-trị&quot;&gt;Kiểm tra giá trị&lt;/h1&gt;

&lt;p&gt;Bạn muốn kiếm tra giá trị có trong biến thì các bạn dùng:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TOP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TOP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// làm gì đó...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Khi &lt;strong&gt;AND&lt;/strong&gt; với biến hiện tại, nếu vị trí của bit ở giá trị cần kiểm tra và &lt;strong&gt;biến cùng là 1&lt;/strong&gt;, nó sẽ &lt;strong&gt;giữ lại&lt;/strong&gt; còn những vị trí &lt;strong&gt;khác sẽ trở thành 0&lt;/strong&gt;. Kết quả là nó sẽ ra là giá trị muốn kiểm tra. Sau đó khi đem so sánh với giá trị đó, nếu bằng đương nhiên là nó có chứa trong đó. Cách này sẽ kiểm tra được giá trị toàn bit 0 hoặc toàn bit 1.&lt;/p&gt;

&lt;p&gt;Theo ví dụ trên, biến &lt;strong&gt;_direction&lt;/strong&gt; hiện tại là &lt;strong&gt;0011&lt;/strong&gt;, khi &lt;strong&gt;AND với 0001&lt;/strong&gt; nó sẽ bằng &lt;strong&gt;0001&lt;/strong&gt; nghĩa là nó có giá trị &lt;strong&gt;TOP&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;mo&quot;&gt;0011&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;AND&lt;/span&gt;	&lt;span class=&quot;mo&quot;&gt;0001&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;	&lt;span class=&quot;mo&quot;&gt;0001&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vậy muốn kiểm tra nhiều giá trị thì sao? Tương tự như trên:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TOP&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RIGHT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TOP&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RIGHT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// làm gì đó...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;xóa-giá-trị&quot;&gt;Xóa giá trị&lt;/h1&gt;

&lt;p&gt;Bạn muốn xóa giá trị đó ra khỏi biến hiện tại, các bạn &lt;strong&gt;AND cho NOT&lt;/strong&gt; của giá trị đó:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;_direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TOP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;hoặc bạn &lt;strong&gt;XOR&lt;/strong&gt; cho giá trị đó:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;_direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eDirection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TOP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Theo mình, bạn &lt;strong&gt;nên dùng AND với NOT&lt;/strong&gt;, để khi không có giá trị trong đó, nó sẽ &lt;strong&gt;không bị thay đổi biến hiện tại&lt;/strong&gt; của mình.&lt;/p&gt;

&lt;p&gt;– &lt;strong&gt;NOT của TOP&lt;/strong&gt; là &lt;strong&gt;1110&lt;/strong&gt;, khi &lt;strong&gt;AND&lt;/strong&gt; với _direction là &lt;strong&gt;0011&lt;/strong&gt; nó sẽ còn lại &lt;strong&gt;0010&lt;/strong&gt; là giá trị &lt;strong&gt;LEFT&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;mo&quot;&gt;0011&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;AND&lt;/span&gt;	&lt;span class=&quot;mi&quot;&gt;1110&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;	&lt;span class=&quot;mo&quot;&gt;0010&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;– khi lấy &lt;strong&gt;0001 XOR&lt;/strong&gt; với &lt;strong&gt;0011&lt;/strong&gt; nó bằng &lt;strong&gt;0010&lt;/strong&gt; là giá trị &lt;strong&gt;LEFT&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;mo&quot;&gt;0011&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;XOR&lt;/span&gt;	&lt;span class=&quot;mo&quot;&gt;0010&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;	&lt;span class=&quot;mo&quot;&gt;0010&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Cả 2 &lt;strong&gt;đều đúng nếu đã có giá trị LEFT&lt;/strong&gt; trong đó, giả sử mình kiểm tra giá trị RIGHT.&lt;/p&gt;

&lt;p&gt;– &lt;strong&gt;NOT của RIGHT&lt;/strong&gt; là &lt;strong&gt;0111&lt;/strong&gt;, khi &lt;strong&gt;AND&lt;/strong&gt; với &lt;strong&gt;0011&lt;/strong&gt; nó sẽ ra &lt;strong&gt;0011&lt;/strong&gt; là giá trị &lt;strong&gt;TOP LEFT&lt;/strong&gt;, do RIGHT không có nên nó không xóa đi.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;mo&quot;&gt;0011&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;AND&lt;/span&gt;	&lt;span class=&quot;mo&quot;&gt;0111&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;	&lt;span class=&quot;mo&quot;&gt;0011&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;– Còn khi dùng &lt;strong&gt;1000 XOR 0011&lt;/strong&gt; nó sẽ ra &lt;strong&gt;1011&lt;/strong&gt; là giá trị &lt;strong&gt;TOP LEFT RIGHT&lt;/strong&gt;, vậy cách này để dùng cho trường hợp nếu chưa có thì gán thêm còn có rồi thì xóa đi.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;mo&quot;&gt;0011&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;XOR&lt;/span&gt;	&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;	&lt;span class=&quot;mi&quot;&gt;1011&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Bên trên là cách sử dụng bit flags mà mình tìm được và dùng thấy khá là có ích trong các trường hợp mình gặp phải.&lt;/p&gt;

&lt;p&gt;Ví dụ hồi trước mình làm cho cái font chữ, nó cũng có các trạng thái như là in đậm, nghiêng, gạch dưới… hoặc trạng thái của các nhân vật trong game chẳng hạn.&lt;/p&gt;

&lt;p&gt;Các bạn có thắc mắc hay góp ý gì về bài viết sử dụng bit flags này cứ thoải mái comment bên dưới để cùng thảo luận nhé.&lt;/p&gt;

&lt;p&gt;Tạm biệt và hẹn gặp lại các bạn trong những bài tiếp theo.&lt;/p&gt;
</description>
        <pubDate>Sun, 17 Jul 2016 07:00:00 +0000</pubDate>
        <link>https://luuthevinh.me/2016/07/su-dung-bit-flags-de-luu-gia-tri</link>
        <guid isPermaLink="true">https://luuthevinh.me/2016/07/su-dung-bit-flags-de-luu-gia-tri</guid>
        
        <category>bit</category>
        
        <category>bit-flags</category>
        
        
        <category>bai-viet</category>
        
      </item>
    
      <item>
        <title>Hello World!</title>
        <description>&lt;p&gt;Xin chào các bạn, đây là bài viết đầu tiên trên blog này nè.&lt;/p&gt;
</description>
        <pubDate>Sat, 16 Jul 2016 13:08:18 +0000</pubDate>
        <link>https://luuthevinh.me/2016/07/hello-world</link>
        <guid isPermaLink="true">https://luuthevinh.me/2016/07/hello-world</guid>
        
        
        <category>linh-tinh</category>
        
      </item>
    
  </channel>
</rss>
