├── .gitattributes ├── .gitignore ├── README.md ├── index.html ├── init.js ├── load.js ├── log.js ├── mouse.js ├── render.js └── resize.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## responsiveTouchGameFramework v2 2 | 3 | A tiny boilerplate for HTML5 games featuring a responsive, centered, fixed-ratio canvas, and unified pointer events (mouse + touch). 4 | 5 | **Demo:** 6 | 7 | http://xem.github.io/responsiveTouchGameFramework 8 | 9 | **How to use:** 10 | 11 | - Clone this repo 12 | - Edit the page title and global CSS (index.html) 13 | - Set your canvas size (ex: 480 x 270) and game variables in init.js 14 | - Write your game's code in the render loop (render.js) - the demo draws a square movable with the mouse/finger. 15 | - At any moment you have access to the variables ````click_x````, ````click_y````, ````down_x````, ````down_y````, ````move_x````, ````move_y````, ````up_x```` and ````up_y```` (adapted to your canvas dimensions), and ````pointer_down```` (to tell if the mouse/finger is currently down) 16 | - Log stuff on screen using the ````log()```` function -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | TITLE 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /init.js: -------------------------------------------------------------------------------- 1 | /* Customizable canvas size */ 2 | canvas_width = 480; 3 | canvas_height = 270; 4 | 5 | 6 | /* Game variables */ 7 | x = 100; 8 | y = 100; 9 | grab = false; 10 | grab_x = 0; 11 | grab_y = 0; -------------------------------------------------------------------------------- /load.js: -------------------------------------------------------------------------------- 1 | /* Load */ 2 | onload = e => { 3 | logz.value = ""; 4 | a.width = canvas_width; 5 | a.height = canvas_height; 6 | c = a.getContext("2d"); 7 | canvas_ratio = canvas_width / canvas_height; 8 | onresize(); 9 | setInterval(render, 16); 10 | } -------------------------------------------------------------------------------- /log.js: -------------------------------------------------------------------------------- 1 | log = e => { 2 | logz.value += e + "\n"; 3 | logz.scrollTop = log.scrollHeight; 4 | } -------------------------------------------------------------------------------- /mouse.js: -------------------------------------------------------------------------------- 1 | /* Compute mouse / touch coordinates on the canvas */ 2 | 3 | pointer_down = false; 4 | 5 | update_mouse = e => { 6 | 7 | pointer = {}; 8 | if(e.changedTouches){ 9 | pointer = e.changedTouches[0]; 10 | } 11 | else { 12 | pointer = e; 13 | } 14 | 15 | return [ 16 | ~~(((pointer.pageX) - canvas_left) * canvas_width / canvas_real_width), 17 | ~~(((pointer.pageY) - canvas_top) * canvas_height / canvas_real_height) 18 | ]; 19 | } 20 | 21 | /* Click */ 22 | onclick = e => { 23 | e.preventDefault(); 24 | [click_x, click_y] = update_mouse(e); 25 | 26 | }; 27 | 28 | /* Mousedown / touchstart */ 29 | onmousedown = ontouchstart = e => { 30 | e.preventDefault(); 31 | pointer_down = true; 32 | [down_x, down_y] = update_mouse(e); 33 | }; 34 | 35 | /* Mousemove / touchmove */ 36 | onmousemove = ontouchmove = e => { 37 | e.preventDefault(); 38 | [move_x, move_y] = update_mouse(e); 39 | }; 40 | 41 | /* Mouseup / touchend */ 42 | onmouseup = ontouchend = e => { 43 | e.preventDefault(); 44 | pointer_down = false; 45 | [up_x, up_y] = update_mouse(e); 46 | 47 | /* Add click on mobile */ 48 | if(e.changedTouches){ 49 | onclick(); 50 | } 51 | }; 52 | 53 | /* Right click */ 54 | oncontextmenu = e => { 55 | e.preventDefault(); 56 | }; -------------------------------------------------------------------------------- /render.js: -------------------------------------------------------------------------------- 1 | /* Render */ 2 | render = e => { 3 | 4 | // Reset 5 | a.width = a.width; 6 | 7 | // Drax square 8 | c.rect(x,y,30,30) 9 | c.fill(); 10 | 11 | // Grab 12 | if(!grab && pointer_down && c.isPointInPath(down_x, down_y)){ 13 | grab = true; 14 | grab_x = down_x - x; 15 | grab_y = down_y - y; 16 | log("grab"); 17 | } 18 | 19 | // Let go 20 | if(grab && !pointer_down){ 21 | grab = false; 22 | log("let go"); 23 | } 24 | 25 | // Follow mouse / finger 26 | if(grab){ 27 | x = move_x - grab_x; 28 | y = move_y - grab_y; 29 | } 30 | } -------------------------------------------------------------------------------- /resize.js: -------------------------------------------------------------------------------- 1 | /* Canvas offsets (changed onresize) */ 2 | canvas_left = 0; 3 | canvas_top = 0; 4 | 5 | /* Canvas "real" size (changed onresize) */ 6 | canvas_real_width = 0; 7 | canvas_real_height = 0; 8 | 9 | /* Resize */ 10 | onresize = onrotate = b => { 11 | 12 | 13 | screen_ratio = innerWidth / innerHeight; 14 | 15 | /* Full width */ 16 | if(canvas_ratio > screen_ratio){ 17 | canvas_real_width = innerWidth; 18 | canvas_real_height = innerWidth / canvas_ratio; 19 | canvas_left = 0; 20 | canvas_top = (innerHeight - canvas_real_height) / 2; 21 | logz.style.width = "200px"; 22 | logz.style.height = (canvas_top - 20) + "px"; 23 | } 24 | 25 | /* Full height */ 26 | else { 27 | canvas_real_width = innerHeight * canvas_ratio; 28 | canvas_real_height = innerHeight; 29 | canvas_left = (innerWidth - canvas_real_width) / 2; 30 | canvas_top = 0; 31 | logz.style.width = (canvas_left - 20) + "px"; 32 | logz.style.height = "100px"; 33 | } 34 | a.style.width = canvas_real_width + "px"; 35 | a.style.height = canvas_real_height + "px"; 36 | 37 | logz.style.height = (canvas_top - 20) + "px"; 38 | 39 | }; 40 | --------------------------------------------------------------------------------