transform this pygame game into js game use pixijs and nodejs typescript give me full code
client.py
import time
import pygame
import socket
import pickle
import threading
import struct
import sys

# Initialize Pygame
pygame.init()

# Set up the screen
screen = pygame.display.set_mode((1280, 720))
pygame.display.set_caption('2dFight Game')

# Constants
tile_size = 72  # Tile size after scaling
GRAVITY = 1
JUMP_STRENGTH = 15
SPEED = 11
FRICTION = 0.0001
FONT = pygame.font.Font(None, 48)
SMALL_FONT = pygame.font.Font(None, 36)
WHITE = (255, 255, 255)
BLACK = (46, 46, 46)
BLUE = (135, 206, 235)

# Input boxes
player_name_input_box = pygame.Rect(400, 200, 400, 50)
server_ip_input_box = pygame.Rect(400, 300, 400, 50)

# Text variables
player_name = 'Player'
server_ip = 'localhost'
input_active = None

# Connecting flag
connecting = False

# Function to display text
def draw_text(text, font, color, surface, x, y):
    textobj = font.render(text, True, color)
    textrect = textobj.get_rect(center=(x, y))
    surface.blit(textobj, textrect)

# Connecting screen
def show_connecting_screen():
    screen.fill(BLUE)
    draw_text("Connecting...", FONT, BLACK, screen, 640, 360)
    pygame.display.flip()

# Function to handle user input for name and server IP in Pygame
def get_user_input_pygame():
    global player_name, server_ip, input_active, connecting
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if player_name_input_box.collidepoint(event.pos):
                    input_active = 'name'
                elif server_ip_input_box.collidepoint(event.pos):
                    input_active = 'server_ip'
                else:
                    input_active = None
            if event.type == pygame.KEYDOWN:
                if input_active == 'name':
                    if event.key == pygame.K_RETURN:
                        input_active = 'server_ip'
                    elif event.key == pygame.K_BACKSPACE:
                        player_name = player_name[:-1]
                    else:
                        player_name += event.unicode
                elif input_active == 'server_ip':
                    if event.key == pygame.K_RETURN:
                        connecting = True
                        show_connecting_screen()
                        return player_name, server_ip
                    elif event.key == pygame.K_BACKSPACE:
                        server_ip = server_ip[:-1]
                    else:
                        server_ip += event.unicode

        screen.fill(BLUE)
        draw_text("Enter Player Name:", FONT, BLACK, screen, 640, 160)
        draw_text("Enter Server IP:", FONT, BLACK, screen, 640, 260)
        
        pygame.draw.rect(screen, WHITE, player_name_input_box, 2)
        pygame.draw.rect(screen, WHITE, server_ip_input_box, 2)
        
        draw_text(player_name, SMALL_FONT, BLACK, screen, 640, 225)
        draw_text(server_ip, SMALL_FONT, BLACK, screen, 640, 325)

        pygame.display.flip()

# Function to send data
def send_data(data):
    serialized_data = pickle.dumps(data)
    length = len(serialized_data)
    client.sendall(struct.pack('>I', length) + serialized_data)

# Function to receive messages
def receive_message(conn):
    length_data = conn.recv(4)
    if len(length_data) < 4:
        raise Exception("Received incomplete length data")
    
    data_length = struct.unpack('>I', length_data)[0]
    data = b''
    while len(data) < data_length:
        packet = conn.recv(data_length - len(data))
        if not packet:
            raise Exception("Received incomplete data")
        data += packet
    return pickle.loads(data)

# Set up the character
character = pygame.Rect(375, 375, 50, 50)  # Initial position
character_velocity_x = 0
character_velocity_y = 0
is_jumping = False

# Initialize player data and map layout
players = {}
map_layout = []
# Load tile images
tile_images = {
    0: pygame.Surface((tile_size, tile_size)),  # Empty space
    1: pygame.image.load('./assets/grass.png').convert_alpha(),  # Grass tile (solid)
    2: pygame.image.load('./assets/grass.png').convert_alpha(),  # Grass tile (jump-through)
}

# Scale the grass tile image
tile_images[1] = pygame.transform.scale(tile_images[1], (tile_size, tile_size))
tile_images[2] = pygame.transform.scale(tile_images[2], (tile_size, tile_size))

# Set color for transparent tile (matching the screen background)
tile_images[0].fill(BLUE)  # Light blue to blend with background

# Function to check if the character is on the ground (on a grass tile)
def is_on_ground(rect):
    rect.bottom += 1  # Temporarily move the rect down by 1 pixel
    for y in range(max(0, rect.bottom // tile_size), min(len(map_layout), (rect.bottom // tile_size) + 1)):
        for x in range(max(0, rect.left // tile_size), min(len(map_layout[y]), (rect.right // tile_size) + 1)):
            if map_layout[y][x] == 1 or map_layout[y][x] == 2:
                tile_rect = pygame.Rect(x * tile_size, y * tile_size, tile_size, tile_size)
                if rect.colliderect(tile_rect):
                    rect.bottom -= 1  # Move the rect back up
                    return True
    rect.bottom -= 1  # Move the rect back up
    return False

# Function to check and handle general collision with tiles
# Function to check and handle general collision with tiles
def handle_tile_collisions(rect):
    global character_velocity_y, character_velocity_x, is_jumping

    # Check vertical collisions first (falling or jumping)
    for y in range(max(0, rect.top // tile_size), min(len(map_layout), (rect.bottom // tile_size) + 1)):
        for x in range(max(0, rect.left // tile_size), min(len(map_layout[y]), (rect.right // tile_size) + 1)):
            tile_id = map_layout[y][x]
            tile_rect = pygame.Rect(x * tile_size, y * tile_size, tile_size, tile_size)

            if rect.colliderect(tile_rect):
                if tile_id == 1:  # Solid tile
                    # Handle vertical collisions
                    if character_velocity_y > 0:  # Falling down
                        if rect.bottom > tile_rect.top and rect.bottom <= tile_rect.bottom:
                            rect.bottom = tile_rect.top
                            character_velocity_y = 0
                            is_jumping = False
                    elif character_velocity_y < 0:  # Jumping up
                        if rect.top < tile_rect.bottom and rect.top >= tile_rect.top:
                            rect.top = tile_rect.bottom
                            character_velocity_y = 0

                elif tile_id == 2:  # Jump-through tile
                    # Handle collision if falling onto the tile
                    if character_velocity_y > 0 and rect.bottom > tile_rect.top and rect.bottom <= tile_rect.bottom:
                        rect.bottom = tile_rect.top
                        character_velocity_y = 0
                        is_jumping = False

    # Check horizontal collisions after vertical collisions are resolved
    for y in range(max(0, rect.top // tile_size), min(len(map_layout), (rect.bottom // tile_size) + 1)):
        for x in range(max(0, rect.left // tile_size), min(len(map_layout[y]), (rect.right // tile_size) + 1)):
            tile_id = map_layout[y][x]
            tile_rect = pygame.Rect(x * tile_size, y * tile_size, tile_size, tile_size)

            if rect.colliderect(tile_rect):
                if tile_id == 1:  # Solid tile
                    # Handle horizontal collisions
                    if character_velocity_x > 0:  # Moving right
                        if rect.right > tile_rect.left and rect.right <= tile_rect.right:
                            rect.right = tile_rect.left
                            character_velocity_x = 0
                    elif character_velocity_x < 0:  # Moving left
                        if rect.left < tile_rect.right and rect.left >= tile_rect.left:
                            rect.left = tile_rect.right

# Main game loop (unchanged)

# Networking setup
player_name, server_ip = get_user_input_pygame()

try:
    HOST, PORT = server_ip.split(':')
    PORT = int(PORT) if PORT else 25566
except ValueError:
    HOST = server_ip
    PORT = 25566
except TypeError:
    HOST = 'localhost'
    PORT = 25566
except Exception as e:
    print(f"An error occurred: {e}")
    HOST = 'localhost'
    PORT = 25566

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    client.connect((HOST, PORT))
    # Send initial player data to the server
    send_data({'name': player_name, 'position': (character.x, character.y)})
except socket.error as e:
    print(f"Unable to connect to the server: {e}")
    sys.exit()

def receive_data():
    global players, map_layout, running
    while running:
        try:
            data = receive_message(client)
            players = data.get('players', {})
            map_layout = data.get('map_layout', [])
        except Exception as e:
            print(f"Disconnected from server: {e}")
            running = False
            break

# Start a thread to receive data from the server
running = True
threading.Thread(target=receive_data, daemon=True).start()

# Main game loop
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # Get keys pressed
    keys = pygame.key.get_pressed()

    # Handle horizontal movement
    if keys[pygame.K_LEFT]:
        character_velocity_x = -SPEED
    elif keys[pygame.K_RIGHT]:
        character_velocity_x = SPEED
    else:
        character_velocity_x *= FRICTION  # Apply friction when no key is pressed

    # Handle jumping
    if (keys[pygame.K_SPACE] or keys[pygame.K_UP] or keys[pygame.K_w]) and not is_jumping and is_on_ground(character):
        character_velocity_y = -JUMP_STRENGTH
        is_jumping = True

    # Apply gravity
    character_velocity_y += GRAVITY
    character.x += character_velocity_x
    character.y += character_velocity_y

    # Check and handle collisions with tiles
    handle_tile_collisions(character)

    # Ensure character stays within screen bounds
    if character.left < 0:
        character.left = 0
    if character.right > 1280:
        character.right = 1280
    if character.top < 0:
        character.top = 0
    if character.bottom > 720:
        character.bottom = 720

    # Check for collisions with other players
    for addr, info in players.items():
        if addr != (client.getsockname()[0], client.getsockname()[1]):
            other_rect = pygame.Rect(info['position'][0], info['position'][1], 50, 50)
            if character.colliderect(other_rect):
                # Simple collision response
                if keys[pygame.K_LEFT]:
                    character.x += SPEED
                if keys[pygame.K_RIGHT]:
                    character.x -= SPEED
                if keys[pygame.K_UP]:
                    character.y += SPEED
                if keys[pygame.K_DOWN]:
                    character.y -= SPEED

    # Send character position to server
    try:
        send_data({'name': player_name, 'position': (character.x, character.y)})
    except socket.error as e:
        print(f"Failed to send data to server: {e}")
        running = False

    # Light blue background
    screen.fill(BLUE)

    # Draw the map layout
    for y, row in enumerate(map_layout):
        for x, tile_id in enumerate(row):
            tile_image = tile_images.get(tile_id)
            if tile_image:
                screen.blit(tile_image, (x * tile_size, y * tile_size))

    # Draw all players
    for addr, info in players.items():
        pos = info['position']
        color = info['color']
        pygame.draw.rect(screen, color, (pos[0], pos[1], 50, 50))
        font = pygame.font.Font(None, 24)
        text_surface = font.render(info['name'], True, BLACK)
        screen.blit(text_surface, (pos[0], pos[1] - 20))  # Display name above player

    # Update the display
    pygame.display.flip()

    # Cap the frame rate
    pygame.time.Clock().tick(60)

pygame.quit()


server.py
import random
import socket
import threading
import pickle
import struct
import time

# Server settings
HOST = 'localhost'
PORT = 25566

# Store player positions and colors
players = {}

# Tile size
tile_size = 18

# Define the map layouts
map_layouts = [
    [
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 1, 1, 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 1, 1, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]  # Ground layer
    ],
    # Add additional predefined map layouts here
    [
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 1, 1, 0, 1, 0, 0, 0, 0, 2, 0, 2, 0, 1, 1, 1, 0, 0, 1, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]  # Ground layer
    ]
]

def send_data(conn, data):
    try:
        serialized_data = pickle.dumps(data)
        length = len(serialized_data)
        conn.sendall(struct.pack('>I', length) + serialized_data)
    except Exception as e:
        print(f"Error sending data: {e}")
        if conn.fileno() != -1:
            conn.close()

def receive_message(conn):
    try:
        length_data = conn.recv(4)
        if len(length_data) < 4:
            raise Exception("Received incomplete length data")
        
        data_length = struct.unpack('>I', length_data)[0]
        data = b''
        while len(data) < data_length:
            packet = conn.recv(data_length - len(data))
            if not packet:
                raise Exception("Received incomplete data")
            data += packet
        return pickle.loads(data)
    except Exception as e:
        print(f"Error receiving message: {e}")
        if conn.fileno() != -1:
            conn.close()
        raise

def handle_client(conn, addr):
    global connections
    print(f"Connected by {addr}")
    try:
        initial_data = receive_message(conn)
        player_name = initial_data['name']
        
        # Generate a unique spawn position
        spawn_position = get_random_spawn_position()

        # Initialize new player with a unique color and position
        players[addr] = {'name': player_name, 'position': spawn_position, 'color': generate_color()}

        # Send initial positions and map layout to the new client
        send_data(conn, {'players': players, 'map_layout': current_map_layout})

        while True:
            try:
                data = receive_message(conn)
                if not data:
                    break

                players[addr]['position'] = data['position']

                # Send updated positions and map layout to all clients
                for player_conn in connections:
                    if player_conn != conn:
                        send_data(player_conn, {'players': players, 'map_layout': current_map_layout})

            except Exception as e:
                print(f"Exception in handle_client loop: {e}")
                break

    except Exception as e:
        print(f"Exception in handle_client: {e}")

    print(f"Disconnected by {addr}")
    if conn in connections:
        del players[addr]
        connections.remove(conn)
        if conn.fileno() != -1:
            conn.close()

        # Inform remaining clients about the disconnected player
        for player_conn in connections:
            try:
                send_data(player_conn, {'players': players, 'map_layout': current_map_layout})
            except Exception as e:
                print(f"Exception sending data to remaining clients: {e}")
                connections.remove(player_conn)
                if player_conn.fileno() != -1:
                    player_conn.close()

def get_random_spawn_position():
    x = random.randint(0, len(current_map_layout[0]) - 1)
    y = random.randint(0, len(current_map_layout) - 1)
    return x * tile_size, y * tile_size

def generate_color():
    return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

def change_map_layout_periodically():
    global current_map_layout
    map_index = 0
    while True:
        time.sleep(60)  # Change map layout every 20 seconds
        current_map_layout = map_layouts[map_index]
        map_index = (map_index + 1) % len(map_layouts)
        
        print("Map layout changed.")

        # Send the new map layout to all connected clients
        for player_conn in connections:
            try:
                send_data(player_conn, {'players': players, 'map_layout': current_map_layout})
            except Exception as e:
                print(f"Error sending new map layout: {e}")
                connections.remove(player_conn)
                if player_conn.fileno() != -1:
                    player_conn.close()

# Set up the server socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen()
print("Server started, waiting for connections...")

connections = []
current_map_layout = map_layouts[0]  # Start with the first map layout

# Start the thread that changes the map layout periodically
threading.Thread(target=change_map_layout_periodically, daemon=True).start()

while True:
    conn, addr = server.accept()
    connections.append(conn)
    threading.Thread(target=handle_client, args=(conn, addr)).start()