Inital commit
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | |||
| node_modules/ | ||||
							
								
								
									
										2
									
								
								TODO.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,2 @@ | |||
| * Fix collision while in air | ||||
| * Fix jumping while in air (disallow) | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/block_dirt.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 18 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/block_dirt_x4.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/block_grass.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 19 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/block_grass_x4.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/char_luigi.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 18 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/char_luigi_x4.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/char_mario.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 18 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/char_mario_x4.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/luigi.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 71 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/mario.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 460 KiB | 
							
								
								
									
										4542
									
								
								package-lock.json
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										21
									
								
								package.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,21 @@ | |||
| { | ||||
|   "name": "mario", | ||||
|   "version": "1.0.0", | ||||
|   "description": "", | ||||
|   "main": "server.js", | ||||
|   "scripts": { | ||||
|     "dev": "nodemon server" | ||||
|   }, | ||||
|   "author": "Simon Giesel", | ||||
|   "license": "ISC", | ||||
|   "dependencies": { | ||||
|     "babel-polyfill": "^6.26.0", | ||||
|     "branded-qr-code": "^1.3.0", | ||||
|     "express": "^4.16.3", | ||||
|     "express-handlebars": "^3.0.0", | ||||
|     "socket.io": "^2.1.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "nodemon": "^1.17.3" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										157
									
								
								server.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,157 @@ | |||
| require('babel-polyfill'); | ||||
| const express = require('express'), | ||||
|     app = express(), | ||||
|     server = require('http').createServer(app), | ||||
|     io = require('socket.io')(server, { | ||||
|         // wsEngine: 'ws'
 | ||||
|     }), | ||||
|     exphbs = require('express-handlebars'), | ||||
|     qrCode = require('branded-qr-code'); | ||||
| 
 | ||||
| /** CONSTANTS */ | ||||
| const HOST = 'http://192.168.0.105:8080/client/'; | ||||
| 
 | ||||
| const players = [ | ||||
|     { | ||||
|         type: 'mario', | ||||
|         id: guid(), | ||||
|         points: 0 | ||||
|     }, | ||||
|     { | ||||
|         type: 'luigi', | ||||
|         id: guid(), | ||||
|         points: 0 | ||||
|     }, | ||||
| ] | ||||
| console.log(players); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| app.set('views', 'src/views'); | ||||
| app.engine('.hbs', exphbs({ | ||||
|     extname: '.hbs', | ||||
| })); | ||||
| app.set('view engine', '.hbs'); | ||||
| 
 | ||||
| server.listen(8080, function () { | ||||
|     console.log('Listening on *:' + this.address().port); | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| app.get('/assets*', (req, res) => { | ||||
|     if (req.originalUrl.includes('qr.png')) { | ||||
|         const isMario = req.originalUrl.includes('mario'); | ||||
|         qrCode.generate({ | ||||
|             text: HOST + players[isMario ? 0 : 1].id, | ||||
|             path: __dirname + '/assets/' + (isMario ? 'mario.png' : 'luigi.png'), | ||||
|             ratio: 4, | ||||
|             opt: { | ||||
|                 errorCorrectionLevel: 'H', | ||||
|                 width: 500, | ||||
|             }, | ||||
|         }).then(qr => { | ||||
|             res.send(qr); | ||||
|         }); | ||||
| 
 | ||||
|     } | ||||
|     else if (!req.originalUrl.includes('.map')) | ||||
|         res.sendFile(__dirname + req.originalUrl.split('?')[0]); | ||||
| }); | ||||
| 
 | ||||
| app.get(['/', '/index.html'], (req, res) => { | ||||
|     res.render('server', { | ||||
|         layout: false, | ||||
|         marioURL: HOST + players[0].id, | ||||
|         luigiURL: HOST + players[1].id, | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| app.get('/client/:id', (req, res) => { | ||||
|     console.log(req.params.id); | ||||
|     if (req.params.id == players[0].id || req.params.id == players[1].id) | ||||
|         res.render('client', { | ||||
|             layout: false, | ||||
|             id: getPlayerFromId(req.params.id).id, | ||||
|             type: getPlayerFromId(req.params.id).type, | ||||
|         }); | ||||
|     else | ||||
|         res.render('client', { layout: false }); //TODO change to error
 | ||||
| }); | ||||
| 
 | ||||
| const monitorNSP = io.of('/monitor'); | ||||
| const clientNSP = io.of('/client'); | ||||
| 
 | ||||
| clientNSP.on('connection', socket => { | ||||
|     let id = socket.request.headers.referer.split('/').slice(-1)[0]; | ||||
|     if (!getPlayerFromId(id)) { console.error('Wrong ID'); return; } | ||||
|     console.log('Client connected.'); | ||||
|     monitorNSP.emit('clientConnect', getPlayerFromId(id).type); | ||||
| 
 | ||||
|     // monitorNSP.emit('updateGameState', 1);
 | ||||
| 
 | ||||
|     socket.on('moveStart_left', () => { | ||||
|         let pl = getPlayerFromId(socket.request.headers.referer.split('/').slice(-1)[0]); | ||||
|         console.log('moveStart_left: ' + pl.type); | ||||
|         monitorNSP.emit('moveStart_left', pl.type); | ||||
|     }); | ||||
|     socket.on('moveStart_right', () => { | ||||
|         let pl = getPlayerFromId(socket.request.headers.referer.split('/').slice(-1)[0]); | ||||
|         console.log('moveStart_right: ' + pl.type); | ||||
|         monitorNSP.emit('moveStart_right', pl.type); | ||||
|     }); | ||||
|     socket.on('moveStart_jump', () => { | ||||
|         let pl = getPlayerFromId(socket.request.headers.referer.split('/').slice(-1)[0]); | ||||
|         console.log('moveStart_jump: ' + pl.type); | ||||
|         monitorNSP.emit('moveStart_jump', pl.type) | ||||
|     }); | ||||
|     socket.on('moveStart_crouch', () => { | ||||
|         let pl = getPlayerFromId(socket.request.headers.referer.split('/').slice(-1)[0]); | ||||
|         console.log('moveStart_crouch: ' + pl.type); | ||||
|     }); | ||||
|     socket.on('moveEnd_left', () => { | ||||
|         let pl = getPlayerFromId(socket.request.headers.referer.split('/').slice(-1)[0]); | ||||
|         console.log('moveEnd_left: ' + pl.type); | ||||
|         monitorNSP.emit('moveEnd_left', pl.type); | ||||
|     }); | ||||
|     socket.on('moveEnd_right', () => { | ||||
|         let pl = getPlayerFromId(socket.request.headers.referer.split('/').slice(-1)[0]); | ||||
|         console.log('moveEnd_right: ' + pl.type); | ||||
|         monitorNSP.emit('moveEnd_right', pl.type); | ||||
|     }); | ||||
|     socket.on('moveEnd_jump', () => { | ||||
|         let pl = getPlayerFromId(socket.request.headers.referer.split('/').slice(-1)[0]); | ||||
|         console.log('moveEnd_jump: ' + pl.type); | ||||
|     }); | ||||
|     socket.on('moveEnd_crouch', () => { | ||||
|         let pl = getPlayerFromId(socket.request.headers.referer.split('/').slice(-1)[0]); | ||||
|         console.log('moveEnd_crouch: ' + pl.type); | ||||
|     }); | ||||
| 
 | ||||
| 
 | ||||
|     socket.on('disconnect', () => { | ||||
|         console.log('Client disconnected.'); | ||||
|         monitorNSP.emit('clientDisconnect', getPlayerFromId(id).type); | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| monitorNSP.on('connection', socket => { | ||||
|     console.log('Monitor connected.'); | ||||
| 
 | ||||
|     socket.on('disconnect', () => { | ||||
|         console.log('Monitor disconnected.'); | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| function guid() { | ||||
|     function s4() { | ||||
|         return Math.floor((1 + Math.random()) * 0x10000) | ||||
|             .toString(16) | ||||
|             .substring(1); | ||||
|     } | ||||
|     return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); | ||||
| } | ||||
| 
 | ||||
| function getPlayerFromId(id) { | ||||
|     return players.filter(el => el.id == id)[0]; | ||||
| } | ||||
							
								
								
									
										107
									
								
								src/views/client.hbs
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,107 @@ | |||
| <head> | ||||
|     <title>MARIO Controller</title> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
|     <script src="/socket.io/socket.io.js"></script> | ||||
|     <style> | ||||
|         * { | ||||
|             margin: 0; | ||||
|             padding: 0; | ||||
|             -webkit-touch-callout: none; | ||||
|             -webkit-user-select: none; | ||||
|             -khtml-user-select: none; | ||||
|             -moz-user-select: none; | ||||
|             -ms-user-select: none; | ||||
|             user-select: none; | ||||
|         } | ||||
| 
 | ||||
|         html, | ||||
|         body { | ||||
|             height: 100%; | ||||
|             width: 100%; | ||||
|             overflow: hidden; | ||||
|         } | ||||
| 
 | ||||
|         button { | ||||
|             display: inline-block; | ||||
|             position: absolute; | ||||
|             bottom: 35%; | ||||
|             width: 20%; | ||||
|             height: 30%; | ||||
|         } | ||||
| 
 | ||||
|         button#left { | ||||
|             left: 5%; | ||||
|         } | ||||
| 
 | ||||
|         button#right { | ||||
|             left: 30%; | ||||
|         } | ||||
| 
 | ||||
|         button#crouch, | ||||
|         button#jump { | ||||
|             right: 5%; | ||||
|         } | ||||
| 
 | ||||
|         button#jump { | ||||
|             top: calc(40% / 3); | ||||
|         } | ||||
| 
 | ||||
|         button#crouch { | ||||
|             bottom: calc(40% / 3); | ||||
|         } | ||||
| 
 | ||||
|         warning { | ||||
|             display: none; | ||||
|         } | ||||
| 
 | ||||
|         @media screen and (orientation:portrait) { | ||||
|             warning { | ||||
|                 display: block; | ||||
|                 position: absolute; | ||||
|                 width: 100%; | ||||
|                 height: 100%; | ||||
|                 background-color: black; | ||||
|                 color: white; | ||||
|                 top: 0; | ||||
|                 left: 0; | ||||
|                 z-index: 100; | ||||
|                 font-size: 400%; | ||||
|                 padding: 2%; | ||||
|             } | ||||
|             warning span { | ||||
|                 position: absolute; | ||||
|                 top: 50%; | ||||
|                 left: 50%; | ||||
|                 transform: translate(-50%, -50%); | ||||
|             } | ||||
|         } | ||||
|     </style> | ||||
| </head> | ||||
| {{!-- | ||||
| <img src="/assets/{{type}}.png"> ID: '{{id}}' --}} | ||||
| 
 | ||||
| <body> | ||||
|     <warning> | ||||
|         <span>Bitte das Smartphone drehen!</span> | ||||
|     </warning> | ||||
|     <button id="left">Left</button> | ||||
|     <button id="right">Right</button> | ||||
|     <button id="jump">Jump</button> | ||||
|     <button id="crouch" disabled>Crouch</button> | ||||
|     <script> | ||||
|         document.body.addEventListener("contextmenu", e => e.preventDefault()); | ||||
| 
 | ||||
|         var socket = io('/client'); | ||||
|         Array.from(document.querySelectorAll('button')).forEach(el => { | ||||
|             console.log(el.id); | ||||
|             el.addEventListener('touchstart', event => { | ||||
|                 console.log('moveStart_' + el.id); | ||||
|                 socket.emit('moveStart_' + el.id); | ||||
|             }); | ||||
|             el.addEventListener('touchend', event => { | ||||
|                 console.log('moveEnd_' + el.id); | ||||
|                 socket.emit('moveEnd_' + el.id); | ||||
|             }); | ||||
|         }); | ||||
|     </script> | ||||
| </body> | ||||
							
								
								
									
										1
									
								
								src/views/error.hbs
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | |||
| <h1>Fehler</h1> | ||||
							
								
								
									
										213
									
								
								src/views/server.hbs
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,213 @@ | |||
| <head> | ||||
|     <title>MARIO</title> | ||||
|     <script src="/socket.io/socket.io.js"></script> | ||||
|     <style> | ||||
|         * { | ||||
|             margin: 0; | ||||
|             padding: 0; | ||||
|         } | ||||
| 
 | ||||
|         body {} | ||||
| 
 | ||||
|         img.check { | ||||
|             filter: blur(10px); | ||||
|         } | ||||
| 
 | ||||
|         img.checkmark { | ||||
|             content: ""; | ||||
|             display: block; | ||||
|             position: absolute; | ||||
|             width: 200px; | ||||
|             top: 180px; | ||||
|             left: 680px; | ||||
|             height: 200px; | ||||
|             z-index: 1; | ||||
|         } | ||||
| 
 | ||||
|         img.checkmark.left { | ||||
|             left: 140px; | ||||
|         } | ||||
| 
 | ||||
|         img.checkmark.hidden { | ||||
|             display: none; | ||||
|         } | ||||
| 
 | ||||
|         game img { | ||||
|             image-rendering: pixelated; | ||||
|             image-rendering: -moz-crisp-edges; | ||||
|         } | ||||
|     </style> | ||||
| </head> | ||||
| <lobby> | ||||
|     <mario> | ||||
|         <img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI5NnB4IiBoZWlnaHQ9Ijk2cHgiIHZpZXdCb3g9IjAgMCA5NiA5NiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgOTYgOTYiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGZpbGw9IiMyNkE5NjQiIGQ9Ik00OS44NDQsNjguMzI1Yy0xLjQxNiwwLTIuNzQ4LTAuNTU0LTMuNzUtMS41NTdMMjcuNTIzLDQ4LjE5MWMtMS4wMDMtMS4wMDItMS41NTUtMi4zMzQtMS41NTUtMy43NXMwLjU1Mi0yLjc0OSwxLjU1NS0zLjc1YzEuMDAxLTEuMDAxLDIuMzMzLTEuNTUyLDMuNzUtMS41NTJzMi43NSwwLjU1MSwzLjc1MywxLjU1M2wxNC4wMTksMTQuMDE3TDgyLjE0LDUuNTA0YzAuOTg5LTEuNDY4LDIuNjM5LTIuMzQ1LDQuNDEyLTIuMzQ1YzEuMDU0LDAsMi4wNzUsMC4zMTIsMi45NTYsMC45MDJjMi40MjQsMS42MzEsMy4wNyw0LjkzNCwxLjQzOSw3LjM2MUw1NC4yNSw2NS45OGMtMC44OTIsMS4zMTYtMi4zMTIsMi4xNjItMy44OTUsMi4zMTRDNTAuMTcsNjguMzE1LDUwLjAxLDY4LjMyNSw0OS44NDQsNjguMzI1eiIvPjwvZz48L3N2Zz4=" | ||||
|             class="checkmark left hidden"> | ||||
|         <img src="assets/mario.qr.png"> | ||||
|         <a href="{{marioURL}}">Mario</a> | ||||
|     </mario> | ||||
|     <luigi> | ||||
|         <img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI5NnB4IiBoZWlnaHQ9Ijk2cHgiIHZpZXdCb3g9IjAgMCA5NiA5NiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgOTYgOTYiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGZpbGw9IiMyNkE5NjQiIGQ9Ik00OS44NDQsNjguMzI1Yy0xLjQxNiwwLTIuNzQ4LTAuNTU0LTMuNzUtMS41NTdMMjcuNTIzLDQ4LjE5MWMtMS4wMDMtMS4wMDItMS41NTUtMi4zMzQtMS41NTUtMy43NXMwLjU1Mi0yLjc0OSwxLjU1NS0zLjc1YzEuMDAxLTEuMDAxLDIuMzMzLTEuNTUyLDMuNzUtMS41NTJzMi43NSwwLjU1MSwzLjc1MywxLjU1M2wxNC4wMTksMTQuMDE3TDgyLjE0LDUuNTA0YzAuOTg5LTEuNDY4LDIuNjM5LTIuMzQ1LDQuNDEyLTIuMzQ1YzEuMDU0LDAsMi4wNzUsMC4zMTIsMi45NTYsMC45MDJjMi40MjQsMS42MzEsMy4wNyw0LjkzNCwxLjQzOSw3LjM2MUw1NC4yNSw2NS45OGMtMC44OTIsMS4zMTYtMi4zMTIsMi4xNjItMy44OTUsMi4zMTRDNTAuMTcsNjguMzE1LDUwLjAxLDY4LjMyNSw0OS44NDQsNjguMzI1eiIvPjwvZz48L3N2Zz4=" | ||||
|             class="checkmark hidden"> | ||||
|         <img src="assets/luigi.qr.png"> | ||||
|         <a href="{{luigiURL}}">Luigi</a> | ||||
|     </luigi> | ||||
| </lobby> | ||||
| 
 | ||||
| <game> | ||||
|     <assets style="display:none;"> | ||||
|         <img id="char_mario" src="/assets/char_mario_x4.png"> | ||||
|         <img id="char_luigi" src="/assets/char_luigi_x4.png"> | ||||
|         <img id="block_dirt" src="/assets/block_dirt_x4.png"> | ||||
|         <img id="block_grass" src="/assets/block_grass_x4.png"> | ||||
|     </assets> | ||||
|     <canvas id="canvas"></canvas> | ||||
| </game> | ||||
| 
 | ||||
| <script> | ||||
|     const lobbyDOM = document.querySelector('lobby'), | ||||
|         gameDOM = document.querySelector('game'); | ||||
|     let gameState = 0; | ||||
|     var socket = io('/monitor'); | ||||
| 
 | ||||
|     socket.on('updateGameState', gs => { | ||||
|         gameState = gs; | ||||
|         switch (gameState) { | ||||
|             case 0: lobbyDOM.style.display = 'inline'; gameDOM.style.display = 'none'; break; | ||||
|             case 1: lobbyDOM.style.display = 'none'; gameDOM.style.display = 'inline'; initGame(); break; | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     socket.on('clientConnect', type => { | ||||
|         if (type == 'mario') { | ||||
|             document.querySelector('mario img.checkmark').classList.remove('hidden'); | ||||
|             document.querySelector('mario img:not(.checkmark)').classList.add('check'); | ||||
|         } else if (type == 'luigi') { | ||||
|             document.querySelector('luigi img.checkmark').classList.remove('hidden'); | ||||
|             document.querySelector('luigi img:not(.checkmark)').classList.add('check'); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     socket.on('clientDisconnect', type => { | ||||
|         if (type == 'mario') { | ||||
|             document.querySelector('mario img.checkmark').classList.add('hidden'); | ||||
|             document.querySelector('mario img:not(.checkmark)').classList.remove('check'); | ||||
|         } else if (type == 'luigi') { | ||||
|             document.querySelector('luigi img.checkmark').classList.add('hidden'); | ||||
|             document.querySelector('luigi img:not(.checkmark)').classList.remove('check'); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     let lastBtn; | ||||
|     socket.on('moveStart_right', type => { | ||||
|         if (type == 'mario') { | ||||
|             player.vel = 3; | ||||
|             lastBtn = 'right'; | ||||
|         } | ||||
|     }) | ||||
|     socket.on('moveEnd_right', type => { | ||||
|         if (type == 'mario' && lastBtn == 'right') { | ||||
|             player.vel = 0; | ||||
|         } | ||||
|     }) | ||||
|     socket.on('moveStart_left', type => { | ||||
|         if (type == 'mario') { | ||||
|             player.vel = -3; | ||||
|             lastBtn = 'left'; | ||||
|         } | ||||
|     }) | ||||
|     socket.on('moveEnd_left', type => { | ||||
|         if (type == 'mario' && lastBtn == 'left') { | ||||
|             player.vel = 0; | ||||
|         } | ||||
|     }) | ||||
|     socket.on('moveStart_jump', type => { | ||||
|         if (type == 'mario') { | ||||
|             if (player.velUp == 0) | ||||
|                 player.velUp = 14; | ||||
|             console.log(player.velUp) | ||||
|         } | ||||
|     }) | ||||
| 
 | ||||
|     /** CANVAS VARS **/ | ||||
|     const BLOCK_SIZE = 128, | ||||
|         canvas = document.getElementById('canvas'), | ||||
|         ctx = canvas.getContext('2d'), | ||||
|         right = window.innerWidth, | ||||
|         bottom = window.innerHeight, | ||||
|         char_mario = document.getElementById('char_mario'), | ||||
|         char_luigi = document.getElementById('char_luigi'), | ||||
|         block_dirt = document.getElementById('block_dirt'), | ||||
|         block_grass = document.getElementById('block_grass'); | ||||
|     initGame(); | ||||
|     function initGame() { | ||||
|         canvas.width = window.innerWidth; | ||||
|         canvas.height = window.innerHeight; | ||||
| 
 | ||||
|         window.requestAnimationFrame(draw); | ||||
|     } | ||||
| 
 | ||||
|     let player = new Player('char_mario'); | ||||
|     let colliders = []; | ||||
|     const grav = 5; | ||||
|     function draw() { | ||||
|         colliders = []; | ||||
|         ctx.clearRect(0, 0, right, bottom); | ||||
|         for (let y = bottom / BLOCK_SIZE - 2; y < bottom / BLOCK_SIZE; y++) | ||||
|             for (let x = 0; x < right / BLOCK_SIZE; x++) { | ||||
|                 ctx.drawImage(block_dirt, x * BLOCK_SIZE, y * BLOCK_SIZE); | ||||
|                 colliders.push({ x: x * BLOCK_SIZE, y: y * BLOCK_SIZE }); | ||||
| 
 | ||||
|             } | ||||
|         for (let x = 0; x < right / BLOCK_SIZE; x++) { | ||||
|             if (x === 4 || x === 5) continue; | ||||
|             ctx.drawImage(block_grass, x * BLOCK_SIZE, bottom - 3 * BLOCK_SIZE); | ||||
|             colliders.push({ x: x * BLOCK_SIZE, y: bottom - 3 * BLOCK_SIZE }); | ||||
|         } | ||||
| 
 | ||||
|         //   ctx.drawImage(char_mario, 6 * BLOCK_SIZE, bottom - 5 * BLOCK_SIZE + 76); // 76 == offest to full block | ||||
|         //   ctx.drawImage(char_luigi, 5 * BLOCK_SIZE, bottom - 5 * BLOCK_SIZE + 48); // 48 == offest to full block | ||||
|         ctx.drawImage(char_mario, player.x, player.y); | ||||
| 
 | ||||
|         player.move(); | ||||
|         player.gravity(); | ||||
| 
 | ||||
| 
 | ||||
|         window.requestAnimationFrame(draw); | ||||
|     } | ||||
| 
 | ||||
|     function Player(type) { | ||||
|         this.x = 4 * BLOCK_SIZE; | ||||
|         this.y = 300; | ||||
|         this.vel = 0; | ||||
|         this.height = 180; | ||||
|         this.width = 72; | ||||
|         this.type = type; | ||||
|         this.velUp = 0; | ||||
| 
 | ||||
|         Player.prototype.gravity = () => { | ||||
|             if (this.y >= bottom - this.height) return; | ||||
|             if (this.velUp > 0) return; | ||||
|             if (this.vel >= 0 && colliders.filter(el => this.y + this.height >= el.y && this.y + this.height <= el.y + BLOCK_SIZE && this.x >= el.x && this.x <= el.x + BLOCK_SIZE).length) | ||||
|                 return; | ||||
|             if (this.vel < 0 && colliders.filter(el => this.y + this.height >= el.y && this.y + this.height <= el.y + BLOCK_SIZE && this.x + this.width >= el.x && this.x + this.width <= el.x + BLOCK_SIZE).length) | ||||
|                 return; | ||||
|             this.y = this.y + grav; | ||||
|         }; | ||||
| 
 | ||||
|         Player.prototype.move = () => { | ||||
|             if (this.velUp > 5) | ||||
|                 this.y = this.y - 20; | ||||
|             if (this.velUp > 0) | ||||
|                 this.velUp--; | ||||
|             if (this.x <= 0 && this.vel < 0) | ||||
|                 return; | ||||
|             if (this.x >= right - this.width) | ||||
|                 return; | ||||
|             if (this.vel >= 0 && colliders.filter(el => this.x + this.width >= el.x && this.x + this.width <= el.x + BLOCK_SIZE && this.y + this.height - 10 >= el.y && this.y + this.height - 10 <= el.y + BLOCK_SIZE).length) | ||||
|                 return; | ||||
|             if (this.vel < 0 && colliders.filter(el => this.x >= el.x && this.x <= el.x + BLOCK_SIZE && this.y + this.height - 10 >= el.y && this.y + this.height - 10 <= el.y + BLOCK_SIZE).length) | ||||
|                 return; | ||||
|             this.x = this.x + this.vel; | ||||
|         } | ||||
|     } | ||||
| </script> | ||||