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>
|