No description, website, or topics provided.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
docs
frontend
public
server
views
.gitignore
README.md
cursor.js
package.json
webpack.config.js

README.md

Tactical Warfare

preview

live version

Overview

Throw yourself into an epic tank battle with your friends! Tactical Warfare is a 3D online Tank game. The game is a turn-based strategy game between two opponents, with the goal to reduce the opponent's health to zero. Implemented almost entirely using JavaScript, the game allows a user to register, sign in, sign out, challenge other active players, accept challenges, position their tank tactfully, fire projectiles, compete and chat in real time.

Technology Overview

  • Node.js
  • Express.js
  • MongoDB / Mongoose
  • Socket.io
  • Cannon.js
  • Babylon.js

User Auth

  • User can register for an account
  • User can sign in
  • User stays signed in
  • Other players see the user if the user is online

user-auth

Password encryption with BCrypt

User.addUser = function(newUser, callback) {
  bcrypt.genSalt(10, (err, salt) => {
    bcrypt.hash(newUser.password, salt, (errors, hash) => {
      // ...
      newUser.password = hash;
      newUser.save(callback);
    });
  });
};

User.comparePassword = function(candidatePassword, hash, callback) {
  bcrypt.compare(candidatePassword, hash, (err, isMatch) => {
    // ...
    callback(null, isMatch);
  });
};

JSONWebToken

A token is sent to the front end on successful sign in or registration:

const token = jwt.sign({_id: user._id.toString()}, config.secret);

res.json({
  success: true,
  token,
  user: {
    username: user.username
  }
});

The front end then stores this token in its cookie

Cookie.set('auth-token', data.token);

On new connection, the server checks if the client has an auth-token in their cookie already, and automatically assign a username to the socket:

User.findByToken(token).then(user => {
  if (user) {
    currentSocket.displayName = user.username;
    io.to(socket.id).emit('signIn', currentSocket);
  }
  // emit to itself
  io.to(socket.id).emit('currentSocket', currentSocket);
  // emit to other sockets
  socket.broadcast.emit('newActiveSocket', currentSocket);
});

BABYLON Game Engine

We used BABYLON game engine for the game physics logics and setting up the arena environment.

this._sidewall0 = new BABYLON.Mesh.CreatePlane(
  "sidewall0",
  groundWidth,
  scene
);
this._sidewall1 = this._sidewall0.clone("sidewall1");
const matrix = BABYLON.Matrix.RotationAxis(BABYLON.Axis.Y, Math.PI);
this._sidewall1.position = BABYLON.Vector3.TransformCoordinates(
  this._sidewall1.position,
  matrix
);
this._sidewall1.rotation.y = Math.PI;

Dynamic Camera

camera-general camera-aim

2-Player Online Mode

challenge-sent challenge-received

Realistic Game Mechanics

health-loss timer

Live Chat

Using Socket.io, chat messages are relayed to the opponent in real time

live-chat

Future Implementation

  • Store game state in database for each user so users can reconnect back to the game
  • Add different kinds of battleground for users to choose
  • Players can adjust tank's impulse force