Xin lưu ý trước là tôi hoàn toàn không biết gì về lập trình, chỉ lên mạng copy mấy cái code về: Cụ thể là tôi có một cái sprite như thế này: Tôi muốn lập trình cho nó thành animation chạy trên web, nhưng không tìm thấy đoạn code dùng cho tấm ảnh gốc này, mà chỉ có code dùng cho ảnh cuộn từ trái qua phải, câu hỏi thứ nhất là phải dùng code gì để dùng luôn tấm ảnh gốc này mà không cần chỉnh sửa gì. Vì không tìm được nên thế tôi phải chuyển nó thành như thế này: Rồi copy trên mạng 1 đoạn code dài vcl thế này: Spoiler (function() { var lastTime = 0; var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; }()); (function () { var coin, coinImage, canvas; function gameLoop () { window.requestAnimationFrame(gameLoop); coin.update(); coin.render(); } function sprite (options) { var that = {}, frameIndex = 0, tickCount = 0, ticksPerFrame = options.ticksPerFrame || 0, numberOfFrames = options.numberOfFrames || 1; that.context = options.context; that.width = options.width; that.height = options.height; that.image = options.image; that.update = function () { tickCount += 1; if (tickCount > ticksPerFrame) { tickCount = 0; // If the current frame index is in range if (frameIndex < numberOfFrames - 1) { // Go to the next frame frameIndex += 1; } else { frameIndex = 0; } } }; that.render = function () { // Clear the canvas that.context.clearRect(0, 0, that.width, that.height); // Draw the animation that.context.drawImage( that.image, frameIndex * that.width / numberOfFrames, 0, that.width / numberOfFrames, that.height, 0, 0, that.width / numberOfFrames, that.height); }; return that; } // Get canvas canvas = document.getElementById("animated"); canvas.width = 154; canvas.height = 105; // Create sprite sheet coinImage = new Image(); // Create sprite coin = sprite({ context: canvas.getContext("2d"), width: 2309, height: 105, image: coinImage, numberOfFrames: 15, ticksPerFrame: 1 }); // Load sprite sheet coinImage.addEventListener("load", gameLoop); coinImage.src = "images/001.PNG"; } ()); Câu hỏi thứ hai là đoạn trên có phần nào thừa bỏ đi được hay không, vì nhiều quá nhìn rối mắt vcl. Nhưng mà đoạn code trên kia chỉ có thể cuộn từ trái qua phải (1 row, nhiều column), có những sprite xếp theo chiều dọc (nhiều row, 1 column), câu hỏi thứ ba là nếu nó xếp theo chiều dọc thì phải làm thế nào? Câu hỏi cuối cùng là muốn xoay tấm hình 270 độ thì dùng code gì? Tìm trên mạng được đoạn này: Spoiler var canvas = document.getElementById('animated'); var context = canvas.getContext('2d'); // translate context to center of canvas context.translate(canvas.width / 1000, canvas.height / 1); // rotate 270 degrees clockwise context.rotate(Math.PI*3/2); Thật ra code gốc nó là canvas.width / 2, canvas.height / 2 (vị trí center hay sao đó), tôi chỉnh sửa bậy bạ thành canvas.width / 1000, canvas.height / 1 cho nó phù hợp với tấm hình. Kết quả là xoay được nhưng mà nó lại bị chậm nếu dùng ảnh lớn. Mẫu sau khi hoàn thành (xoay 270 độ): html: Spoiler <canvas id="animated" width="154" height="105"></canvas> <script src="./Animated_files/animated.js"></script> animated.js Spoiler (function() { var lastTime = 0; var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; }()); (function () { var coin, coinImage, canvas; function gameLoop () { window.requestAnimationFrame(gameLoop); coin.update(); coin.render(); } function sprite (options) { var that = {}, frameIndex = 0, tickCount = 0, ticksPerFrame = options.ticksPerFrame || 0, numberOfFrames = options.numberOfFrames || 1; that.context = options.context; that.width = options.width; that.height = options.height; that.image = options.image; that.update = function () { tickCount += 1; if (tickCount > ticksPerFrame) { tickCount = 0; // If the current frame index is in range if (frameIndex < numberOfFrames - 1) { // Go to the next frame frameIndex += 1; } else { frameIndex = 0; } } }; that.render = function () { // Clear the canvas that.context.clearRect(0, 0, that.width, that.height); // Draw the animation that.context.drawImage( that.image, frameIndex * that.width / numberOfFrames, 0, that.width / numberOfFrames, that.height, 0, 0, that.width / numberOfFrames, that.height); }; return that; } // Get canvas canvas = document.getElementById("animated"); canvas.width = 105; canvas.height = 154; var canvas = document.getElementById('animated'); var context = canvas.getContext('2d'); // translate context to center of canvas context.translate(canvas.width / 1000, canvas.height / 1); // rotate 270 degrees clockwise context.rotate(Math.PI*3/2); // Create sprite sheet coinImage = new Image(); // Create sprite coin = sprite({ context: canvas.getContext("2d"), width: 2309, height: 105, image: coinImage, numberOfFrames: 15, ticksPerFrame: 1 }); // Load sprite sheet coinImage.addEventListener("load", gameLoop); coinImage.src = "http://i.imgur.com/YV2kdhZ.png"; } ());
Tức là khi tìm được nguồn sprite (có 3 dạng, một là xếp theo nhiều hàng nhiều cột, hai là xếp theo 1 hàng nhiều cột, ba là xếp theo nhiều hàng 1 cột), dùng html code thì chỉ cần down ảnh về, sửa sử kích thước trong source, sửa tên file, xong là có thể preview animation ngay lập tức (mất chưa đầy 1 phút). Còn nếu tạo ảnh gif thì phải down ảnh về, cắt ra thành từng ảnh nhỏ, ráp lại thành gif, sẽ mất rất nhiều thời gian trong khi không phải lúc nào cũng có sprite đẹp (nhiều khi nhìn sprite thấy được nhưng đến lúc tạo thành ảnh động mới thấy nó xấu). Ở đây tôi đang phải xử lý số lượng rất lớn, tới mấy ngàn ảnh, không thể ngồi tạo gif được. Đặc biệt nhất là với những ảnh kích thước lớn 600x800 mà chuyển thành gif thì sẽ rất nặng đồng thời chất lượng ảnh sẽ bị giảm, còn chạy trên html nó vẫn giữ nguyên chất lượng ảnh gốc.
Làm biếng coi, để hiểu đoạn code làm gì thì trong function để chữ "debugger;" trước đoạn code đó, xong vào chrome bật trình duyệt bấm f12 rồi chạy, nó sẽ dừng ngay chỗ debugger rồi nghiền ngẫm Ta nghĩ cái chỗ nhiều row 1 column nó nằm ở đây và ở đây
Js này còn dễ đọc chán, ngâm tý là ra mà. Đọc js của bọn jap viết mới to đầu. Rảnh thì sẽ ngồi giúp, cơ mà méo rảnh :v
Phần trên đ hiểu gì nhưng có vẻ là đ chỉnh sửa gì được. Còn cái dưới, width/height là kích thước file gốc. number of frame là số khung hình (15 hình nhỏ), ticksperframe là thời gian (ở đây là 1 tick chuyển 1 hình nhưng không rõ chính xác 1 tick là bao lâu). Tất nhiên cái đoạn code trên kia chỉ là ví dụ cho biết cái mục đích đang làm thôi, chứ không nhất thiết phải chỉnh sửa cái code đó là gì cả, nếu tự viết code mới thì sẽ dễ dàng hơn. Yêu cầu là 3 câu hỏi màu đỏ ấy. 1) Chuyển animation từ sprite gốc mà không cần chỉnh sửa. 2) Chuyển hướng cuộn sprite (từ trái qua phải, từ phải qua trái, từ trên xuống dưới, từ dưới lên trên). 3) Lật hình, vì một số sprite nó để nằm ngang nên phải lật cho nó đứng lên. Như cái clip này nó viết code rất đơn giản (xem từ 9:50), chỉ có vài chục dòng thôi, nhưng mà do đ có kiến thức lập trình nên đ hiểu nó nói gì cả, còn viết lại y chang nó thì không hoạt động (có thể do tự gõ nên gõ sai).
Sao không dùng photoshop, có nhiều plug in hỗ trợ mà. VD: https://www.johnwordsworth.com/projects/photoshop-sprite-sheet-generator-script/ Chứ viết code ông cũng phải nhập tay kích cỡ các kiểu mà. Trừ khi tất cả đều chung một tỷ lệ.
Tranh thủ vừa làm vừa học luôn mà, chứ cái gì cũng nhờ plugin hỗ trợ thì cuối cùng chẳng biết gì cả. Ngoài ra còn có một số kiểu sprite nó tách nhiều phần, có thể dùng code để ráp lại, cái này chắc plugin không làm được (hoặc phải có programer lập trình cái plugin đó). Ví dụ: Nhưng mà cái này có vẻ khó nên để sau tính.
code trong clip kia chạy được ok mà , chắc chủ thớt chưa thay thông số ảnh của mình vào. Chỉ cần thay dòng thứ 10 thành: row = 5; col = 3; dòng 21 thành: ctx.drawImage(sprite,sX, sY, w, h, 154,106, w*2, h*2); là chạy ngon.
Sửa được hết, ta chỉ gợi ý, mi từ từ nghiên cứu. Mấy cái đó cộng trừ nhân chia thôi, đọc kỹ mấy cái biến là biết nó đang làm gì.
Có thay mà không chạy, sợ lúc gõ code sai chính tả thôi: Đ có tí kiến thức gì về lập trình thì đọc hiểu rồi sửa mấy cái đó bằng niềm tin à?
oạch, ở dưới bác chưa tạo thằng canvas kìa nhét đoạn sau vào giữa </head></html> <body onload='init()'> <canvas id='animated' width='500' height='500'></canvas> </body> hình như bác chưa có kiến thức cơ bản về html, js với css thì phải? Chưa học bò đã lo học chạy thế thì sao học được
Hồi trước cũng tính copy mấy cái emo động này về forum, inspect mới thấy nó nguyên 1 đống thế này, bối rối vl.
Ta đang hướng dẫn mi mà, có thằng nào sinh ra đã có kiến thức sẵn, cũng tập tọe từng dòng code mà biết thôi
ông dùng chrome đi nhìn debug sẽ dễ hơn :v P/s: còn code không chạy do ông dùng trình duyệt thấp quá, k xài đc html5