Rảnh rỗi ngồi code Gangnam với ASCII

Thảo luận trong 'Lập trình & Đồ hoạ' bắt đầu bởi Nguyễn Tài Hải, 14/10/12.

  1. Nguyễn Tài Hải

    Nguyễn Tài Hải Youtube Master Race

    Tham gia ngày:
    12/5/12
    Bài viết:
    25
    Nơi ở:
    Ho Chi Minh City
    Đến thời điểm này chắc không ai còn lạ lẫm Gangnam style. Cộng đồng đã có một bài viết về vụ việc um xùm này: http://goo.gl/Qc6cU . Ngồi buồn đành kiếm cái làm chơi cho anh em giải sầu.

    Lập trình Gangnam style với ASCII. http://nonit.vn/Apps/GangnamHTML5/


    [YOUTUBE]http://www.youtube.com/watch?v=SVR2vp56Yt8[/YOUTUBE]



    Hướng dẫn:


    Bước 1. Chuẩn bị. Một điệu nhảy Gangnam:

    [​IMG]

    Bước 2: Phân rã hình này thành những hình ảnh cấu thành animation trên:

    [​IMG]

    Bước 3. Viết đoạn code cho hiển thị hình ảnh theo định dạng ASCII


    <html>
    <head>
    <style class="csscreations">/*Some styles*/
    * {margin: 0; padding: 0;}
    body {
    text-align: center;
    }
    #container {
    overflow: hidden;
    display: inline-block;
    }

    #ascii {
    font-family: monospace;
    font-size: 11px;
    line-height: 70%;
    }

    #sprite {
    display: none;
    }

    </style>
    </head>
    <body>
    <!-- Lets create an ascii animation -->
    <!-- We will use a sprite -->
    <img src="anim.png" id="sprite">
    <div id="container">
    <!-- The ascii art comes in the pre tag below -->
    <pre id="ascii"></pre>
    </div>
    </body>
    <script>
    window.onload = function(){
    //some variables
    var r, g, b, gray;
    var character, line = "";

    //sprite stuff
    var sprite = document.getElementById("sprite");
    var W = sprite.width;
    var H = sprite.height;

    //temporary canvas for pixel processing
    var tcanvas = document.createElement("canvas");
    tcanvas.width = W;
    tcanvas.height = H; //same as the image
    var tc = tcanvas.getContext("2d");
    //painting the canvas white before painting the image to deal with pngs
    tc.fillStyle = "white";
    tc.fillRect(0, 0, W, H);
    //drawing the image on the canvas
    tc.drawImage(sprite, 0, 0, W, H);

    //accessing pixel data
    var pixels = tc.getImageData(0, 0, W, H);
    var colordata = pixels.data;
    //every pixel gives 4 integers -> r, g, b, a
    //so length of colordata array is W*H*4
    for(var i = 0; i < colordata.length; i = i+4)
    {
    r = colordata;
    g = colordata[i+1];
    b = colordata[i+2];
    //converting the pixel into grayscale
    gray = r*0.2126 + g*0.7152 + b*0.0722;
    //overwriting the colordata array with grayscale values
    colordata = colordata[i+1] = colordata[i+2] = gray;

    //text for ascii art.
    //blackish = dense characters like "W", "@"
    //whitish = light characters like "`", "."
    if(gray > 250) character = " "; //almost white
    else if(gray > 230) character = "`";
    else if(gray > 200) character = ":";
    else if(gray > 175) character = "*";
    else if(gray > 150) character = "+";
    else if(gray > 125) character = "#";
    else if(gray > 50) character = "W";
    else character = "@"; //almost black

    //newlines and injection into dom
    if(i != 0 && (i/4)%W == 0) //if the pointer reaches end of pixel-line
    {
    ascii.appendChild(document.createTextNode(line));
    //newline
    ascii.appendChild(document.createElement("br"));
    //emptying line for the next row of pixels.
    line = "";
    }

    line += character;
    }

    //repainting the gray image
    //tc.putImageData(pixels, 0, 0);
    //you can see the grayscale version of the sprite now
    //injecting the canvas into the DOM
    //sprite.parentNode.insertBefore(tcanvas, sprite);
    //you can see the canvas now with the image

    //animation time
    var frames = 11; //sprite got 10 frames
    var container = document.getElementById("container");
    //width of container should allow only 1 frame to be seen
    var frame_width = parseInt(window.getComputedStyle(container).width)/frames;
    //window.getComputedStyle is supported in Chrome, FF, Opera, and IE9+
    //The width has "px" at the end so parseInt is used to remove that
    container.style.width = frame_width+"px";

    //We will change the margin-left of ascii to move it.
    ascii.style.marginLeft = "0";

    setInterval(loop, 1000/20);

    function loop()
    {
    var current_ml = parseFloat(ascii.style.marginLeft);
    //if the ascii reaches the last frame(9th in this case)
    //margin needs to be reset to 0
    //frame_width * (10-1) * -1(because we are taking the margin negative)
    if(current_ml == frame_width*(frames-1)*-1)
    ascii.style.marginLeft = "0";
    else
    ascii.style.marginLeft = (current_ml - frame_width) + "px";
    }

    }
    </script>
    </html>

    Bonus:

    [​IMG]

    Nguồn hình: http://www.sodahead.com

    Enjoy.
    Tác giả: Nguyễn Tài Hải: http://vietgamedev.net

    - - - Updated - - -

    Link youtube http://www.youtube.com/watch?v=SVR2vp56Yt8
    Bạn nào biết chèn Youtube bào bài chỉ mình với nhé.
     
  2. dark_dragons

    dark_dragons Hyperion Captain ‍ ⚚ Mystic Mage ⚚ Moderator Lão Làng GVN

    Tham gia ngày:
    9/6/08
    Bài viết:
    22,066
    Nơi ở:
    TP. HCM
    --Được chuyển đến từ box GAME DEVELOPMENT--​
     
  3. NewfolderVN

    NewfolderVN Youtube Master Race

    Tham gia ngày:
    17/8/12
    Bài viết:
    4
    Thanks bác mấy cái này trông rất ngộ :D.
     

Chia sẻ trang này