You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

314 lines
12 KiB
Python

# Imports
from engineio.payload import Payload
from AesEverywhere import aes256
import flask_socketio
import threading
import requests
import random
import pygame
import flask
import time
import math
import os
from dotenv import load_dotenv
load_dotenv()
# Config
Payload.max_decode_packets = 500
webserver_address = "http://localhost:3000"
cryptography_password = os.environ.get("CRYPTOGRAPHY_PASSWORD")
clock = pygame.time.Clock()
tile_map = [[8, 80, 80, 160, 160], [1, 160, 80, 240, 160], [1, 240, 80, 320, 160], [1, 320, 80, 400, 160], [1, 400, 80, 480, 160], [1, 480, 80, 560, 160], [1, 560, 80, 640, 160], [1, 640, 80, 720, 160], [1, 720, 80, 800, 160], [1, 800, 80, 880, 160], [1, 880, 80, 960, 160], [1, 960, 80, 1040, 160], [1, 1040, 80, 1120, 160], [1, 1120, 80, 1200, 160], [1, 1200, 80, 1280, 160], [1, 1280, 80, 1360, 160], [1, 1360, 80, 1440, 160], [1, 1440, 80, 1520, 160], [1, 1520, 80, 1600, 160], [1, 1600, 80, 1680, 160], [1, 1680, 80, 1760, 160], [1, 1760, 80, 1840, 160], [1, 1840, 80, 1920, 160], [1, 1920, 80, 2000, 160], [1, 2000, 80, 2080, 160], [2, 2080, 80, 2160, 160], [7, 80, 160, 160, 240], [3, 2080, 160, 2160, 240], [7, 80, 240, 160, 320], [3, 2080, 240, 2160, 320], [7, 80, 320, 160, 400], [3, 2080, 320, 2160, 400], [7, 80, 400, 160, 480], [3, 2080, 400, 2160, 480], [7, 80, 480, 160, 560], [5, 160, 480, 240, 560], [5, 240, 480, 320, 560], [5, 320, 480, 400, 560], [5, 400, 480, 480, 560], [5, 480, 480, 560, 560], [3, 2080, 480, 2160, 560], [7, 80, 560, 160, 640], [5, 880, 560, 960, 640], [5, 1520, 560, 1600, 640], [5, 1600, 560, 1680, 640], [5, 1680, 560, 1760, 640], [5, 1760, 560, 1840, 640], [3, 2080, 560, 2160, 640], [7, 80, 640, 160, 720], [3, 2080, 640, 2160, 720], [7, 80, 720, 160, 800], [5, 800, 720, 880, 800], [5, 1200, 720, 1280, 800], [3, 2080, 720, 2160, 800], [7, 80, 800, 160, 880], [3, 2080, 800, 2160, 880], [7, 80, 880, 160, 960], [3, 560, 880, 640, 960], [5, 1040, 880, 1120, 960], [5, 1360, 880, 1440, 960], [3, 2080, 880, 2160, 960], [7, 80, 960, 160, 1040], [3, 560, 960, 640, 1040], [5, 1280, 960, 1360, 1040], [5, 1440, 960, 1520, 1040], [5, 1520, 960, 1600, 1040], [5, 1600, 960, 1680, 1040], [5, 1680, 960, 1760, 1040], [3, 2080, 960, 2160, 1040], [7, 80, 1040, 160, 1120], [5, 480, 1040, 560, 1120], [5, 1760, 1040, 1840, 1120], [3, 2080, 1040, 2160, 1120], [7, 80, 1120, 160, 1200], [5, 1120, 1120, 1200, 1200], [3, 2080, 1120, 2160, 1200], [6, 80, 1200, 160, 1280], [5, 160, 1200, 240, 1280], [5, 240, 1200, 320, 1280], [5, 320, 1200, 400, 1280], [5, 400, 1200, 480, 1280], [5, 480, 1200, 560, 1280], [5, 560, 1200, 640, 1280], [5, 640, 1200, 720, 1280], [5, 720, 1200, 800, 1280], [5, 800, 1200, 880, 1280], [5, 880, 1200, 960, 1280], [5, 960, 1200, 1040, 1280], [5, 1040, 1200, 1120, 1280], [5, 1120, 1200, 1200, 1280], [5, 1200, 1200, 1280, 1280], [5, 1280, 1200, 1360, 1280], [5, 1360, 1200, 1440, 1280], [5, 1440, 1200, 1520, 1280], [5, 1520, 1200, 1600, 1280], [5, 1600, 1200, 1680, 1280], [5, 1680, 1200, 1760, 1280], [5, 1760, 1200, 1840, 1280], [5, 1840, 1200, 1920, 1280], [5, 1920, 1200, 2000, 1280], [5, 2000, 1200, 2080, 1280], [4, 2080, 1200, 2160, 1280]]
users = []
user_positions = [0, 0, 0, 0, 0, 0]
tiles = []
bullets = []
health = []
directions = []
# Cryptography
class Cryptography ():
# Encrypt
@staticmethod
def encrypt ( data, password ):
return aes256.encrypt(data, password)
# Decrypt
@staticmethod
def decrypt ( data, password ):
return aes256.decrypt(data, password)
# Register Server
requests.post(webserver_address + "/api/registerServer", data = Cryptography.encrypt(f"{requests.get('https://api.ipify.org').text},6", cryptography_password))
# Get Bullet Vector
def getBulletVector ( playerX, playerY, clickX, clickY ):
return [ clickX - playerX, clickY - playerY ]
# Get Bullet Normalisation Value
def getBulletNormalisationValue ( distanceX, distanceY ):
return 1 / math.sqrt((distanceX ** 2) + (distanceY ** 2))
# Get Normalised Bullet Vector
def getNormalisedBulletVector ( bulletVector, bulletNormalisationValue ):
return [ bulletVector[0] * bulletNormalisationValue, bulletVector[1] * bulletNormalisationValue ]
# Creates Tiles
for tile in tile_map:
tiles.append(pygame.Rect(tile[1], tile[2],80, 80))
# User
class User ():
# Constructor
def __init__ ( self, socketId, user, gameRank, elo, kills, deaths, player ):
self.socketId = socketId
self.user = user
self.gameRank = gameRank
self.elo = elo
self.kills = kills
self.deaths = deaths
self.new_kills = 0;
self.new_deaths = 0;
self.angle = 0;
self.inputs = []
self.player = player
# Player
class Player(object):
# Constructor
def __init__ ( self ):
self.reset(random.randint(160, 1760), 160)
self.game_over = False
self.image_index = 0
# Update
def update( self, inputs, tiles, dt ):
# Move
dx = 0
dy = 0
# Jump
self.landed = False
if self.jl == True:
self.jl = False
if inputs[0] and self.jumped == False and self.in_air == False:
self.vel_y = -22
self.jumped = True
self.jl = True
self.touchfloor = False
elif inputs[0] == False:
self.jumped = False
# Left
if inputs[1]:
dx -= 7 * dt
self.direction = "left"
# Right
if inputs[3]:
dx += 7 *dt
self.direction = "right"
# Collisions
self.in_air = True
# Direction
if dx < 0:
self.dir = -1
elif dx > 0:
self.dir = 1
# Gravity
self.vel_y += 1 * dt
if self.vel_y > 10:
self.vel_y = 10 *dt
dy += self.vel_y
for tile in tiles:
# Vertical Collisions
if tile.colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
if self.vel_y >= 0:
dy = tile.top - self.rect.bottom
self.in_air = False
if self.touchfloor == False:
self.touchfloor = True
self.landed = True
elif self.vel_y < 0:
dy = tile.bottom - self.rect.top
self.vel_y = 0
self.rect.y += dy
for tile in tiles:
# X and Y
if tile.colliderect(self.rect.x + dx, self.rect.y + 1, self.width, self.height - 2):
print("true")
if dx >= 0:
dx = tile.left - self.rect.right
elif dx < 0:
dx = tile.right - self.rect.left
self.rect.x += dx
# Update Cords
self.ht = dy
# Return Cords
return self.rect.x, self.rect.y
# Reset
def reset(self, x,y):
self.width = 80
self.height = 80
self.rect = pygame.Rect(x,y,80,80)
self.direction = 0
self.vel_y = 0
self.jumped = False
self.in_air = True
self.health = 8
self.dir = 1
self.touchfloor = False
self.jl = False
self.landed = False
self.ht = 0
# App
app = flask.Flask(__name__)
socketio = flask_socketio.SocketIO(app, cors_allowed_origins = webserver_address)
# Socketio Authentication
@socketio.on("authentication")
def authentication(code):
code = str(Cryptography.decrypt(code.split("ShootyArenaGame=")[1], cryptography_password))[2:-1]
code = code.split(",")
for user in users:
if user.user == code[0]:
socketio.emit("disc", to = flask.request.sid)
return
users.append(User(flask.request.sid, code[0], code[1], int(code[2]), int(code[3]), int(code[4]), Player()))
socketio.emit("map", tile_map)
socketio.emit("player", code[0], to = flask.request.sid)
# Move
@socketio.on("move")
def move(movement):
for user in users:
if flask.request.sid == user.socketId:
user.inputs = movement
# MMove
@socketio.on("mmove")
def mmove(angle):
for user in users:
if flask.request.sid == user.socketId:
try:
user.angle = int(angle["angle"])
except:
user.angle = 0
# Click
@socketio.on("click")
def cli(inputs):
for user in users:
if flask.request.sid == user.socketId:
vec = [inputs["dx"], inputs["dy"]]
nvec = getBulletNormalisationValue(vec[0], vec[1])
fvec = getNormalisedBulletVector(vec, nvec)
inputs["px"] += fvec[0] * 72
inputs["py"] += fvec[1] * 72
hit = False
for tile in tile_map:
if (inputs["px"] + 5 > tile[1] and inputs["px"] + 5 < tile[3]) and (inputs["py"] + 5 > tile[2] and inputs["py"] + 5 < tile[4]):
hit = True
if hit == False:
bullets.append([user.user, inputs["px"], inputs["py"], fvec[0], fvec[1]])
# Game Loop
last_time = time.time()
def game (last_time):
while True:
dt = time.time() - last_time
dt *= 60
last_time = time.time()
health = []
# Bullets
for bulletnum, bullet in enumerate(bullets):
bullet[1] += bullet[3] * 12 * dt
bullet[2] += bullet[4] * 12 * dt
for tile in tile_map:
if (bullet[1] + 5 > tile[1] and bullet[1] + 5 < tile[3]) and (bullet[2] + 5 > tile[2] and bullet[2] + 5 < tile[4]):
del bullets[bulletnum]
# Users
for user in users:
if (bullet[1] + 5 > user.player.rect.x and bullet[1] +5 < user.player.rect.x + 80) and (bullet[2] +5 > user.player.rect.y and bullet[2] +5 < user.player.rect.y + 80):
if bullet[0] != user.user:
del bullets[bulletnum]
user.player.health -= 1
if user.player.health == 0:
user.new_deaths += 1
socketio.emit("die", to = user.socketId)
user.player.reset(random.randint(160, 1760), 160)
for user2 in users:
if bullet[0] == user2.user:
user2.new_kills += 1
directions = []
angles = []
# Users
for usernum, user in enumerate(users):
if len(user.inputs) != 0:
user_positions[usernum] = [user.user, user.player.update(user.inputs, tiles, dt)]
if user.player.jl == True:
socketio.emit("ju", to = user.socketId)
if user.player.landed == True:
socketio.emit("la", to = user.socketId)
directions.append([user.user, user.player.dir])
health.append([user.user, user.player.health])
angles.append([user.user, user.angle])
socketio.emit("users", user_positions)
socketio.emit("directions", directions)
socketio.emit("health", health)
socketio.emit("bullets", bullets)
socketio.emit("ang", angles)
clock.tick(60)
# Run Game Loop
thread = threading.Thread(target=game, args = (last_time,))
thread.start()
# Factorial
def factorial ( number ):
if number == 0:
return 1
else:
return number * factorial(number - 1)
# Calculate Elo Change
def calculateEloChange ( kills, deaths ):
sc = kills - deaths
if sc >= 2:
return factorial(sc) // factorial(sc - 2)
else:
return ( kills - deaths ) * 10
# Calculate Rank
def calculateRank ( elo ):
if elo < 0:
return "Unranked"
elif elo < 1000:
return "Shitty Shooty"
elif elo < 2000:
return "Cutey Shooty"
elif elo < 3000:
return "Beauty Shooty"
else:
return "Snooty Shooty"
# Dissconnect
@socketio.on("disconnect")
def dissconnect ():
for usernum, user in enumerate(users):
if flask.request.sid == user.socketId:
data = aes256.encrypt(f"{user.user},{user.elo+calculateEloChange(user.new_kills, user.new_deaths)},{calculateRank(user.elo + calculateEloChange(user.new_kills, user.new_deaths))},{user.kills + user.new_kills},{user.deaths + user.new_deaths}" , cryptography_password)
requests.post(f"{webserver_address}/api/updateStats", data = data)
del users[usernum]
user_positions[usernum] = 0
# Run Socketio
if __name__ == "__main__":
socketio.run(app, debug = False)