top of page
SmallWorld_Map.png
SmallWorld_Carte.png

Small World est une carte multijoueur de taille moyenne conçue pour des combats intenses et tactiques en 6v6.
Située sur un
plateau de tournage, les joueurs s’affrontent à travers des reconstitutions miniatures de lieux emblématiques tels que Paris, Tokyo, New York, Los Angeles et même Londres !

Le design équilibre habilement des zones avec des styles de jeu prédéfinis tout en permettant aux joueurs d’adapter leur propre style. Ils peuvent engager des
combats rapprochés à Los Angeles et New York, ou opter pour des affrontements tactiques à moyenne portée à Paris et Tokyo.

L’une des fonctionnalités phares de la carte sont les 
portes interactive du hangar, qui, une fois activées, plonge la carte dans l’obscurité pendant quelques secondes. Cette mécanique oblige les joueurs à adapter leur gameplay tout en introduisant un objectif secondaire pendant le match. Cependant, contrôler cette zone ne sera pas chose facile : elle est très ouverte, et le danger peut venir de n’importe quelle direction !

SmallWorld_MapLayout.png

POI Overview

Explorez les points d’intérêt suivants basés sur les zones clés de Small World.

POI_SmallWorld_OpFor incursion.png
SmallWorld_MapSheet.png

Engine Overview

Map_InEngine_2DView

Ici, vous pouvez voir la vue 2D de la carte depuis le moteur. Bien qu’il y ait beaucoup de bruit en raison de la géométrie de la carte et des nombreux modèles 3D, il est tout de même possible de distinguer les cinq POI ainsi que les deux spawns principaux.

In-Engine

Et voici la vue 3D de la carte, toujours depuis le moteur.

In-Engine
Map_InEngine
In-Engine
In-Engine

Map Scripting

main()

{

    maps\mp\_load::main();

 

    ambientPlay("ambient_backlot_ext");

 

    game["allies"] = "sas";

    game["axis"] = "opfor";

    game["attackers"] = "axis";

    game["defenders"] = "allies";

    game["allies_soldiertype"] = "woodland";

    game["axis_soldiertype"] = "woodland";

 

    setdvar("r_specularcolorscale", "1");

 

    setdvar("r_glowbloomintensity0", ".25");

    setdvar("r_glowbloomintensity1", ".25");

    setdvar("r_glowskybleedintensity0", ".3");

    setdvar("compassmaxrange", "1800");

 

    // ALL THREAD FOR THIS LEVEL

    thread leftDoor();  

    thread rightDoor();  

    thread bigben();

 

    // Handle areas' automatic doors closing/opening

    thread areaDoors();

}

Cette partie du script sert à configurer les paramètres globaux du jeu (son d'ambiance, noms des équipes, skins des soldats, luminosité globale de la carte, etc.).

À la fin, vous trouverez les trois threads que j'ai utilisés pour le bouton permettant d’interagir avec les portes du hangar, ainsi que le bouton coulissant qui le dissimule.
À savoir : leftDoor (gérant la porte gauche du hangar), rightDoor (gérant la porte droite du hangar) et bigben (gérant le bouton caché situé sur Big Ben à Londres).

Cette partie du script gère le bouton caché sur la tour de Big Ben. C’est un script simple mais efficace.
Lorsqu’un joueur ou une IA s’en approche suffisamment, le bouton se déplace de 50 unités vers le haut sur l’axe Z pendant 4 secondes.
Ensuite, le script empêche toute nouvelle activation du bouton, car il n’y a pas de fonctionnalité de « retour en arrière ». Cela est géré à l’aide du booléen level.bigbenActivated.

// Handle the big ben's hidden hangar's door button

bigben()

{

    level.bigbenActivated = 0; // Set bool as false

    bigben = getent("bigben_button", "targetname"); // Retrieve the button for big ben

    bigben_trigger = getent("trigger_bigben_button", "targetname"); // Retrieve the trigger for the big ben's button


 

    while (1)

    {

        if (level.bigbenActivated == 0)  // Check if it hasn't been activated yet

        {

            bigben_trigger waittill("trigger");  // Wait for the trigger event

 

            level.bigbenActivated = 1;  // Set the bool as true for ever as I want the trigger to be activated only once

 

            // Move 50 units along the Z-axis over 4 seconds

            bigben movez(50, 4, 1, 1);

            wait(2);  // Wait for movement to finish

 

        }

        else

        {

            wait(0.1);  // Avoid hogging CPU if nothing is happening

        }

    }

}

Ces deux threads gèrent le mouvement des portes gauche et droite du hangar sur l’axe X.

// Handle the left hangar's door​

leftDoor()

{

    leftdoor = getent("leftdoor", "targetname"); // Retrieve the left door

    leftdoor_trigger = getent("left_trigger", "targetname"); // Retrieve the trigger for the left door


 

    while (1)

    {

        leftdoor_trigger waittill("trigger");  // Wait for the trigger event

 

    iprintlnbold("Moving Hangar's Doors"); // Feedback for hangar's door

 

        // Move 440 units along the X-axis over 10 seconds

        leftdoor movex(440, 10, 1, 1);

        wait(30);  // Wait duration before closing the left door

 

        leftdoor movex(-440, 10, 1, 1);

        wait(2);  // Wait for movement to finish

    }

}

// Handle the right hangar's door

rightDoor()

{

    rightdoor = getent("rightdoor", "targetname"); // Retrieve the right door

    rightdoor_trigger = getent("right_trigger", "targetname"); // Retrieve the trigger for the right door


 

    while (1)

    {

        rightdoor_trigger waittill("trigger");  // Wait for the trigger event

 

        // Move -440 units along the X-axis over 10 seconds

        rightdoor movex(-440, 10, 1, 1);

        wait(30);  // Wait duration before closing the right door

 

        rightdoor movex(440, 10, 1, 1);

        wait(2);  // Wait for movement to finish

    }

}

Ce thread gère le mouvement des portes de chaque zones, qui sont déclenchées lorsqu'elles sont touchées par un tir.
Chaque thread gère les portes d'une zone spécifique afin de garantir qu'elles puissent toutes être activées simultanément si nécessaire.

// THE FOLLOWING HANDLES THE AREA'S DOOR CLOSING WHEN SHOOTING AT THE ACTIVATOR

​

shootableDoorsActivatorParis()

{

    doorsInteractableParis_trigger = getent("doorInteractableParis_trigger", "targetname");

    level.ParisCanBeActivated = 1; // PARIS CAN BE ACTIVATED ON START

    // Paris' doors

    leftsmalldoorParis = getent("leftsmalldoorParis","targetname");

    rightsmalldoorParis = getent("rightsmalldoorParis","targetname");


 

    // Constantly check

    while (1)

    {

        // ONLY PARIS WORKS, FOR SURE JUST A LOGIC PROBLEM, TO CHECK

 

        // PARIS DOORS

        doorsInteractableParis_trigger waittill("trigger");  // Wait for the trigger event

        if(level.ParisCanBeActivated == 1)

        {

            iprintlnbold("Moving Paris");

            level.ParisCanBeActivated = 0;

            leftsmalldoorParis movex(200,5,1,1);

            rightsmalldoorParis movex(-200,5,1,1);

 

            wait(10);

            leftsmalldoorParis movex(-200,5,1,1);

            rightsmalldoorParis movex(200,5,1,1);

 

            wait(5);

            level.ParisCanBeActivated = 1;

        }    

    }

}

 

shootableDoorsActivatorTokyo()

{

    doorsInteractableTokyo_trigger = getent("doorInteractableTokyo_trigger", "targetname");

    level.TokyoCanBeActivated = 1;

    // Tokyo's doors

    leftsmalldoorTokyo = getent("leftsmalldoorTokyo","targetname");

    rightsmalldoorTokyo = getent("rightsmalldoorTokyo","targetname");


 

    // Constantly check

    while (1)

    {

        // TOKYO DOORS

        doorsInteractableTokyo_trigger waittill("trigger");  // Wait for the trigger event

        if(level.TokoyCanBeActivated == 1)

        {

            iprintlnbold("Moving Tokyo");

            level.TokyoCanBeActivated = 0;

            leftsmalldoorTokyo movex(200,5,1,1);

            rightsmalldoorTokyo movex(-200,5,1,1);

 

            wait(10);

            leftsmalldoorTokyo movex(-200,5,1,1);

            rightsmalldoorTokyo movex(200,5,1,1);

 

            wait(5);

            level.TokyoCanBeActivated = 1;

        }  

    }

}

 

shootableDoorsActivatorNY()

{

    doorsInteractableNY_trigger = getent("doorInteractableNY_trigger", "targetname");

    level.NYCanBeActivated = 1;

    // NY's doors

    leftsmalldoorNY = getent("leftsmalldoorNY","targetname");

    rightsmalldoorNY = getent("rightsmalldoorNY","targetname");


 

    // Constantly check

    while (1)

    {

        // NY DOORS

        doorsInteractableNY_trigger waittill("trigger");  // Wait for the trigger event

        if(level.NYCanBeActivated == 1)

        {

            iprintlnbold("Moving NY");

            level.NYCanBeActivated = 0;

            leftsmalldoorNY movex(200,5,1,1);

            rightsmalldoorNY movex(-200,5,1,1);

 

            wait(10);

            leftsmalldoorNY movex(-200,5,1,1);

            rightsmalldoorNY movex(200,5,1,1);

 

            wait(5);

            level.NYCanBeActivated = 1;

        }        

    }

}

 

shootableDoorsActivatorLA()

{

    doorsInteractableLA_trigger = getent("doorInteractableLA_trigger", "targetname");

    level.LACanBeActivated = 1;

    // LA' doors

    leftsmalldoorLA = getent("leftsmalldoorLA","targetname");

    rightsmalldoorLA = getent("rightsmalldoorLA","targetname");


 

    // Constantly check

    while (1)

    {

        // LA DOORS

        doorsInteractableLA_trigger waittill("trigger");  // Wait for the trigger event

        if(level.LACanBeActivated == 1)

        {

            iprintlnbold("Moving LA");

            level.LACanBeActivated = 0;

            leftsmalldoorLA movex(200,5,1,1);

            rightsmalldoorLA movex(-200,5,1,1);

 

            wait(10);

            leftsmalldoorLA movex(-200,5,1,1);

            rightsmalldoorLA movex(200,5,1,1);

 

            wait(5);

            level.LACanBeActivated = 1;

        }      

    }

}

Améliorations et prochaines étapes :

- Effectuer des tests de jeu fermés : Réaliser des tests multijoueurs pour collecter des données de gameplay, évaluer l’équilibre et affiner la conception pour améliorer l'expérience des joueurs.

- Optimiser l'éclairage : Ajuster l'éclairage en moteur pour une meilleure visibilité et pour renforcer l'atmosphère de la carte.

- Peaufiner les visuels : Appliquer les textures et modèles finaux pour compléter l’esthétique de la carte.

- Réfléchir sur le flux des joueurs : Documenter les retours des tests de jeu concernant le flux de mouvement et les points de congestion, en les utilisant pour affiner la conception de futures cartes.

bottom of page