Added client socket

This commit is contained in:
Thomas
2020-08-21 15:53:16 +02:00
parent 861105eb92
commit e2e4495f02
17 changed files with 200 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
{ {
"name": "tronio", "name": "tron.io",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
@@ -11314,6 +11314,11 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true "dev": true
}, },
"vuex": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz",
"integrity": "sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw=="
},
"watchpack": { "watchpack": {
"version": "1.7.4", "version": "1.7.4",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz",

View File

@@ -11,13 +11,13 @@
"core-js": "^3.6.5", "core-js": "^3.6.5",
"register-service-worker": "^1.7.1", "register-service-worker": "^1.7.1",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-router": "^3.2.0" "vue-router": "^3.2.0",
"vuex": "^3.5.1"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "~4.4.0", "@vue/cli-plugin-babel": "~4.4.0",
"@vue/cli-plugin-eslint": "~4.4.0", "@vue/cli-plugin-eslint": "~4.4.0",
"@vue/cli-plugin-pwa": "~4.4.0", "@vue/cli-plugin-pwa": "~4.4.0",
"@vue/cli-plugin-router": "~4.4.0",
"@vue/cli-service": "~4.4.0", "@vue/cli-service": "~4.4.0",
"@vue/eslint-config-standard": "^5.1.2", "@vue/eslint-config-standard": "^5.1.2",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",

View File

@@ -1,9 +1,26 @@
<template> <template>
<div id="app"> <div id="app">
<router-view/> <Game v-if="isSocketConnected"/>
<div v-else>
<h1>Game loadin mate</h1>
</div>
</div> </div>
</template> </template>
<script>
import Game from './components/Game'
export default {
name: 'App',
components: {
Game
},
computed: {
isSocketConnected () {
return this.$store.state.game.socketConnected
}
}
}
</script>
<style> <style>
#app { #app {
font-family: Avenir, Helvetica, Arial, sans-serif; font-family: Avenir, Helvetica, Arial, sans-serif;

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="home"> <div class="game">
<canvas <canvas
class="game-canvas" class="game-canvas"
ref="canvas"> ref="canvas">
@@ -8,32 +8,16 @@
</template> </template>
<script> <script>
import { send } from '@/store/socketPlugin'
export default { export default {
name: 'Home', name: 'Game',
data () { data () {
return { return {
player: {
x: 100,
y: 100,
angle: 0,
targetAngle: 0,
walls: [],
lastWall: 0,
color: 'red'
},
players: [],
mouse: { mouse: {
x: 0, x: 0,
y: 0 y: 0
}, },
settings: { renderTimer: null
playerSize: 10,
playerSpeed: 2,
playerTurnSpeed: 10,
wallSize: 8,
wallUpdate: 5,
arenaSize: 1000
}
} }
}, },
computed: { computed: {
@@ -42,22 +26,30 @@ export default {
}, },
context () { context () {
return this.canvas.getContext('2d') return this.canvas.getContext('2d')
},
settings () {
return this.$store.state.game.settings
},
player () {
return this.$store.state.game.player
},
players () {
return this.$store.state.game.players
},
isPaused () {
return this.$store.state.game.paused
} }
}, },
mounted () { mounted () {
this.canvas.width = window.innerWidth this.canvas.width = window.innerWidth
this.canvas.height = window.innerHeight this.canvas.height = window.innerHeight
this.canvas.addEventListener('mousemove', this.mouseEvent) this.canvas.addEventListener('mousemove', this.mouseEvent)
// setInterval(this.render, 1000 / 60) this.renderTimer = setInterval(this.render, 1000 / 60)
setInterval(this.render, 1000 / 60)
setInterval(this.movePlayer, 100)
}, },
methods: { methods: {
render () { render () {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height) this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
this.renderBorders() this.renderBorders()
this.renderPlayer(this.player)
this.renderWalls(this.player.walls, this.player.color)
this.players.forEach(player => { this.players.forEach(player => {
this.renderPlayer(player) this.renderPlayer(player)
@@ -147,6 +139,7 @@ export default {
var dy = this.mouse.y - this.canvas.height / 2 var dy = this.mouse.y - this.canvas.height / 2
this.player.targetAngle = Math.atan2(dy, dx) this.player.targetAngle = Math.atan2(dy, dx)
send({ message: this.player, type: 'update' })
}, },
updatePlayer () { updatePlayer () {
this.player.lastWall++ this.player.lastWall++

View File

@@ -1,11 +1,11 @@
import Vue from 'vue' import Vue from 'vue'
import App from './App.vue' import App from './App.vue'
import store from './store'
import './registerServiceWorker' import './registerServiceWorker'
import router from './router'
Vue.config.productionTip = false Vue.config.productionTip = false
new Vue({ new Vue({
router, store,
render: h => h(App) render: h => h(App)
}).$mount('#app') }).$mount('#app')

View File

@@ -1,19 +0,0 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
}
]
const router = new VueRouter({
routes
})
export default router

View File

@@ -0,0 +1,69 @@
const state = {
player: {
x: 100,
y: 100,
angle: 0,
targetAngle: 0,
walls: [],
lastWall: 0,
color: 'red'
},
players: {
},
settings: {
playerSize: 10,
playerSpeed: 2,
playerTurnSpeed: 10,
wallSize: 8,
wallUpdate: 5,
arenaSize: 1000
},
paused: true,
socketConnected: false
}
const getters = {
}
const actions = {
socketConnected ({ commit }) {
commit('SET_CONNECTED')
},
login ({ commit }, player) {
commit('SET_PLAYER', player)
},
settings ({ commit }, settings) {
commit('SET_SETTINGS', settings)
},
update ({ commit }, update) {
},
dead ({ commit }) {
},
error ({ commit }, error) {
alert('Error: ' + error)
}
}
const mutations = {
SET_PLAYER (state, player) {
state.player = player
},
SET_SETTINGS (state, settings) {
state.settings = settings
},
SET_PAUSE (state) {
state.paused = !state.paused
},
SET_CONNECTED (state) {
state.socketConnected = !state.socketConnected
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}

15
client/src/store/index.js Normal file
View File

@@ -0,0 +1,15 @@
import Vue from 'vue'
import Vuex from 'vuex'
import socket from './socketPlugin'
import game from './gameModule'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
game
},
plugins: [
socket()
]
})

View File

@@ -0,0 +1,48 @@
const connection = new WebSocket('ws://localhost:8181/socket')
// const connection = new WebSocket('wss://tronio.gltronic.ovh/socket')
export default function createSocketPlugin () {
return store => {
connection.onopen = function () {
console.log('[WS] connected')
store.dispatch('game/socketConnected')
}
connection.onclose = function () {
console.log('[WS] closed')
}
connection.onerror = function (error) {
console.log('[WS] error ' + error.message)
store.dispatch('game/error', 'Connection problem')
}
connection.onmessage = function (message) {
console.log('[WS] message', message.data)
var data = JSON.parse(message.data)
switch (data.type) {
case 'login':
store.dispatch('game/login', data.message)
break
case 'gameSettings':
store.dispatch('game/settings', data.message)
break
case 'gameUpdate':
store.dispatch('game/update', data.message)
break
case 'gamePlayerDead':
store.dispatch('game/dead')
break
default:
break
}
}
}
}
export function send (message) {
console.log('[WS] send', message)
connection.send(JSON.stringify(message))
}

View File

@@ -6,7 +6,7 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
@SpringBootApplication @SpringBootApplication
@ComponentScan(basePackages = "gltronic.voozik") @ComponentScan(basePackages = "gltronic.tronio")
@PropertySource("classpath:application.properties") @PropertySource("classpath:application.properties")
public class TronIoApplication { public class TronIoApplication {

View File

@@ -6,12 +6,14 @@ import java.util.Random;
import org.json.JSONObject; import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import gltronic.tronio.model.Game; import gltronic.tronio.model.Game;
import gltronic.tronio.model.Player; import gltronic.tronio.model.Player;
import gltronic.tronio.model.Wall; import gltronic.tronio.model.Wall;
@Service
public class GameManager implements IGameManager { public class GameManager implements IGameManager {
@Autowired @Autowired
Game game; Game game;
@@ -29,6 +31,7 @@ public class GameManager implements IGameManager {
game.getPlayers().put(session.getId(), player); game.getPlayers().put(session.getId(), player);
SocketUtils.forwardMessage(session, "login", new JSONObject(player)); SocketUtils.forwardMessage(session, "login", new JSONObject(player));
SocketUtils.forwardMessage(session, "gameSettings", new JSONObject(game.getSettings()));
} }
@Override @Override
@@ -90,7 +93,7 @@ public class GameManager implements IGameManager {
private void killPlayer (String id) { private void killPlayer (String id) {
Player player = game.getPlayers().get(id); Player player = game.getPlayers().get(id);
initPlayer(player); initPlayer(player);
SocketUtils.sendMessage(game.getSessions().get(id), "dead", "yo dead"); SocketUtils.sendMessage(game.getSessions().get(id), "gamePlayerDead", "yo dead");
} }
private boolean isCloseToWall (double xa, double ya, double xb, double yb, double xc, double yc, double radius) { private boolean isCloseToWall (double xa, double ya, double xb, double yb, double xc, double yc, double radius) {

View File

@@ -1,18 +1,32 @@
package gltronic.tronio.model; package gltronic.tronio.model;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
@Getter @Getter
@Setter @Setter
@NoArgsConstructor @Component
public class Game { public class Game {
private Map<String, Player> players; private Map<String, Player> players;
private Map<String, WebSocketSession> sessions; private Map<String, WebSocketSession> sessions;
private GameSettings settings; private GameSettings settings;
public Game() {
this.players = new HashMap<>();
this.sessions = new HashMap<>();
this.settings = new GameSettings();
this.settings.setArenaSize(1000);
this.settings.setPlayerSize(10);
this.settings.setPlayerSpeed(2);
this.settings.setPlayerTurnSpeed(10);
this.settings.setWallSize(8);
this.settings.setWallUpdate(5);
}
} }

View File

@@ -31,7 +31,7 @@ public class SocketHandler extends TextWebSocketHandler {
String type = (String) jsonObject.get("type"); String type = (String) jsonObject.get("type");
switch (type) { switch (type) {
case "update": case "update":
gameManager.updatePlayer(session, (Player) jsonObject.get("update")); gameManager.updatePlayer(session, (Player) jsonObject.get("message"));
break; break;
default: default:
SocketUtils.sendMessage(session, "error", "unknow command"); SocketUtils.sendMessage(session, "error", "unknow command");