src/server/utils/framesync.js
import { distanceBetween, isInBounds, GLOBAL } from '../../client/js/global'
import { deleteObject, getField, setField, incrementField } from '../server'
import { collisionDetect } from './collision'
import { tickCompound } from './compound'
import { Socket } from 'net'
import { smartEmit } from './serverutils'
/**
* Runs once a frame, per ROOM. Refactored 4/8/19 from player to room.
* @param {*} socket socket.io instance. INDEPENDENT OF PLAYER (any valid socket connection can go here!!!!!)
* @param {string} room The name of the room
*/
export function frameSync(socket, room) {
if (socket.connected) {
// Increment frame count in the room
incrementField(1, ['rooms', room, 'time', 'frames'])
let thisRoom = getField(['rooms', room])
if (thisRoom !== undefined) {
// Move compounds
for (let compound in thisRoom.compounds) {
let compoundRef = thisRoom.compounds[compound]
if (isInBounds(compoundRef)) {
setField(compoundRef.posX + compoundRef.vx, ['rooms', room, 'compounds', compound, 'posX'])
setField(compoundRef.posY + compoundRef.vy, ['rooms', room, 'compounds', compound, 'posY'])
tickCompound(getField(['rooms', room, 'compounds', compound]), room, socket)
// compoundRef.posX += compoundRef.vx;
// compoundRef.posY += compoundRef.vy;
}
else { // delete
deleteObject('compounds', compound, room, socket)
}
}
// Move atoms
for (let atom in thisRoom.atoms) {
// Atom slowing down. This will be overridden by the player attraction if a player is close enough
if (Math.abs(thisRoom.atoms[atom].vx) > GLOBAL.DEADZONE || Math.abs(thisRoom.atoms[atom].vy) > GLOBAL.DEADZONE) {
setField(thisRoom.atoms[atom].vx * GLOBAL.VELOCITY_STEP, ['rooms', room, 'atoms', atom, 'vx'])
setField(thisRoom.atoms[atom].vy * GLOBAL.VELOCITY_STEP, ['rooms', room, 'atoms', atom, 'vy'])
// thisRoom.atoms[atom].vx *= GLOBAL.VELOCITY_STEP;
// thisRoom.atoms[atom].vy *= GLOBAL.VELOCITY_STEP;
}
if (Math.abs(thisRoom.atoms[atom].vx) <= GLOBAL.DEADZONE) {
setField(0, ['rooms', room, 'atoms', atom, 'vx'])
}
if (Math.abs(thisRoom.atoms[atom].vy) <= GLOBAL.DEADZONE) {
setField(0, ['rooms', room, 'atoms', atom, 'vy'])
}
// Move atom
setField(thisRoom.atoms[atom].posX + thisRoom.atoms[atom].vx, ['rooms', room, 'atoms', atom, 'posX'])
setField(thisRoom.atoms[atom].posY + thisRoom.atoms[atom].vy, ['rooms', room, 'atoms', atom, 'posY'])
// thisRoom.atoms[atom].posX += thisRoom.atoms[atom].vx;
// thisRoom.atoms[atom].posY += thisRoom.atoms[atom].vy;
}
// Player specific actions
for (let playerI in thisRoom.players) {
// Distance checking for all objects
let tempObjects = {
players: {},
atoms: {},
compounds: {}
}
let thisPlayer = thisRoom.players[playerI]
// Populate tempObjects
for (let objType in tempObjects) {
for (let obj in thisRoom[objType]) {
if (distanceBetween(thisRoom[objType][obj], thisPlayer) < GLOBAL.DRAW_RADIUS) {
tempObjects[objType][obj] = thisRoom[objType][obj]
}
}
}
// Check for atom attraction
for (let atom in tempObjects.atoms) {
let distance = distanceBetween(
{ posX: thisRoom.atoms[atom].posX + GLOBAL.ATOM_RADIUS, posY: thisRoom.atoms[atom].posY - GLOBAL.ATOM_RADIUS },
{ posX: thisPlayer.posX + GLOBAL.PLAYER_RADIUS, posY: thisPlayer.posY - GLOBAL.PLAYER_RADIUS })
// Attractive force
if (!thisPlayer.spectating && distance < GLOBAL.ATTRACTION_RADIUS && (thisRoom.atoms[atom].team === 'all' || thisPlayer.team === thisRoom.atoms[atom].team)) {
let theta = Math.atan2((thisPlayer.posY - thisRoom.atoms[atom].posY), (thisPlayer.posX - thisRoom.atoms[atom].posX))
// Attraction is based on logarithmic function
setField(1 / distance * Math.cos(theta) * GLOBAL.ATTRACTION_COEFFICIENT, ['rooms', room, 'atoms', atom, 'vx'])
setField(1 / distance * Math.sin(theta) * GLOBAL.ATTRACTION_COEFFICIENT, ['rooms', room, 'atoms', atom, 'vy'])
// console.log(this.vx, this.vy, this.posX, this.posY);
}
}
// Collision detection
collisionDetect(socket, room, thisPlayer, tempObjects)
smartEmit(socket, room, 'objectSync', tempObjects, thisPlayer.id)
}
if (thisRoom.started) {
smartEmit(socket, room, 'time', { time: thisRoom.time.formattedTime })
}
if (thisRoom !== undefined && !thisRoom.started) {
// Send over the room player information
let roomInfo = {
players: thisRoom.players,
canStart: (thisRoom.type === '2v2' && Object.keys(thisRoom.players).length === 4) ||
((thisRoom.type === '4v4' || thisRoom.type === '2v2v2v2') && Object.keys(thisRoom.players).length === 8) ||
(thisRoom.type === '4v4v4v4' && Object.keys(thisRoom.players).length === 16) ||
thisRoom.type === 'private'
}
smartEmit(socket, room, 'roomInfo', roomInfo)
}
}
}
}