[DOWNLOAD] New Save States + Save / Load All Variable + Object Culling Script v5.0 - Project File! A Cluster of Awesome and Helptful Tools!

Iv finished working on the new version on the Culling Script!

It still works about the same, the difference being i added a suit of awesome events and Scripts to compliment it!

Link down bellow, 100% Free, you can simply Download, open the project and Copy / Paste into your own project!

It will work with nothing else needed to be done.

But heres some basic instructions…

This is what youll find in the Project:

Whats included:

  • An Easy and Simple way of having “Save States”, with a push of a Button, the game will Save, then if you want to Load simply press another button and the game will Reload.

  • When the game Saves and Reloads, it will also Save and Load all of your Variables, Global, Scene and Objects.

  • …and you also get the fine tunned Version of my Object Culling Script.

So how do i use this thing?
Simply Copy and Paste the whole thing into your Project, put it at the Bottom of your event sheet for better results.

The save state Keys by Default are:

  • Numpad1 to Save
  • Numpad9 to Load
  • Numpad7 to Delete Save

You can change these keys by simply opening the Event groups and changing them…

Just make sure 03 - Save Objects and 04 - Save Variables have the exact same Key to trigger the events… or the same condition is you customize it.

You can Adjust the Culling Buffer in the 02 - Cull Script Options > Cull Buffer Size

To Exclude Culling or Permanently Cull Objects, make two Object Groups:

  • ExcludeObjects for objects you dont want to be culled
  • StayCulled for objects you want to stay deleted

DISCLAIMER This whole thing only works on the Base Layer for now.

Itch Download Link

Check out the YouTube Channel if you like stuff like this!

7 Likes

Here’s the code to apply to several layers, it’s been tested!

runtimeScene.setBackgroundColor(100,100,240);
// Liste des calques à traiter pour le culling
const layersToCull = ["", "layer1", "layer2"]; // Ajouter ici les noms des calques sur lesquels appliquer le culling

// Initialiser l'objet deletedObjects pour chaque calque si nécessaire
if (!runtimeScene.deletedObjects) {
    runtimeScene.deletedObjects = {};
}

// Obtenir la valeur de la variable CullBuffer une seule fois
const cullBuffer = runtimeScene.getVariables().get("CullBuffer").getAsNumber();

// Processus de culling pour chaque calque
layersToCull.forEach(layerName => {
    // Initialiser deletedObjects pour le calque courant
    if (!runtimeScene.deletedObjects[layerName]) {
        runtimeScene.deletedObjects[layerName] = {};
    }

    // Obtenir la position de la caméra et la taille du calque actuel
    const cameraLayer = runtimeScene.getLayer(layerName);
    const cameraX = cameraLayer.getCameraX();
    const cameraY = cameraLayer.getCameraY();
    const cameraWidth = cameraLayer.getCameraWidth();
    const cameraHeight = cameraLayer.getCameraHeight();

    // Calculer les limites de culling basées sur CullBuffer
    const leftBoundary = cameraX - cameraWidth / 2 - cullBuffer;
    const rightBoundary = cameraX + cameraWidth / 2 + cullBuffer;
    const topBoundary = cameraY - cameraHeight / 2 - cullBuffer;
    const bottomBoundary = cameraY + cameraHeight / 2 + cullBuffer;

    // Récupérer tous les objets de la scène
    const allObjectsInstances = runtimeScene.getAdhocListOfAllInstances();

    // Créer des tableaux pour stocker les objets à supprimer et recréer
    const objectsToDelete = [];
    const objectsToStoreAndDelete = [];

    // Limiter le nombre d'objets traités par frame pour éviter les pics d'usage CPU
    const maxObjectsPerFrame = 50; // Ajustez cette valeur pour optimiser les performances
    const startIndex = runtimeScene.getVariables().has("CullStartIndex_" + layerName)
        ? runtimeScene.getVariables().get("CullStartIndex_" + layerName).getAsNumber()
        : 0;
    const endIndex = Math.min(startIndex + maxObjectsPerFrame, allObjectsInstances.length);

    runtimeScene.getVariables().get("CullStartIndex_" + layerName).setNumber(endIndex === allObjectsInstances.length ? 0 : endIndex);

    // Obtenir le temps actuel de la scène pour les objets restaurés
    const currentTime = runtimeScene.getTimeManager().getTimeFromStart() / 1000;

    // Parcourir les objets du sous-ensemble sélectionné
    for (let i = startIndex; i < endIndex; i++) {
        const object = allObjectsInstances[i];
        const objectName = object.getName();
        const objectLayer = object.getLayer();

        // Ne traiter que les objets du calque en cours
        if (objectLayer !== layerName) continue;

        const variables = object.getVariables();

        // Vérifier si l'objet a une variable "ExcludeCull" définie à true
        if (variables.has("ExcludeCull") && variables.get("ExcludeCull").getAsBoolean()) {
            continue; // Exclure cet objet du culling
        }

        // Obtenir la boîte englobante de l'objet
        const aabb = object.getAABB();
        const objectLeft = aabb.min[0];
        const objectRight = aabb.max[0];
        const objectTop = aabb.min[1];
        const objectBottom = aabb.max[1];

        // Vérifier si l'objet est en dehors des limites du culling
        if (objectRight < leftBoundary || objectLeft > rightBoundary || objectBottom < topBoundary || objectTop > bottomBoundary) {
            // Vérifier si l'objet a une variable "Cull" définie à true
            if (variables.has("Cull") && variables.get("Cull").getAsBoolean()) {
                objectsToDelete.push(object); // Ajouter l'objet pour suppression immédiate
            } else {
                // Stocker les propriétés de l'objet pour recréation future
                if (!runtimeScene.deletedObjects[layerName][objectName]) {
                    runtimeScene.deletedObjects[layerName][objectName] = [];
                }

                const objectProperties = {
                    x: object.getX(),
                    y: object.getY(),
                    zOrder: object.getZOrder(),
                    angle: object.getAngle(),
                    layer: objectLayer,
                    hidden: object.isHidden(),
                    variables: {},
                    timers: {},
                    cullTime: currentTime
                };

                // Enregistrer les variables de l'objet
                const objectVariablesList = variables._variables.items;
                for (const variableName in objectVariablesList) {
                    if (objectVariablesList.hasOwnProperty(variableName)) {
                        objectProperties.variables[variableName] = objectVariablesList[variableName].getAsString();
                    }
                }

                // Enregistrer les propriétés optionnelles
                if (object.getWidth) objectProperties.width = object.getWidth();
                if (object.getHeight) objectProperties.height = object.getHeight();
                if (object.getOpacity) objectProperties.opacity = object.getOpacity();

                // Enregistrer les timers de l'objet
                if (object._timers && object._timers.items) {
                    const timerItems = object._timers.items;
                    for (const timerName in timerItems) {
                        if (timerItems.hasOwnProperty(timerName)) {
                            objectProperties.timers[timerName] = timerItems[timerName].getTime() / 1000.0;
                        }
                    }
                }

                runtimeScene.deletedObjects[layerName][objectName].push(objectProperties);
                objectsToStoreAndDelete.push(object);
            }
        }
    }

    // Supprimer les objets complètement hors champ
    objectsToDelete.forEach(obj => obj.deleteFromScene(runtimeScene));
    objectsToStoreAndDelete.forEach(obj => obj.deleteFromScene(runtimeScene));

    // Récupérer le temps actuel de la scène pour restaurer les objets
    const restoreTime = runtimeScene.getTimeManager().getTimeFromStart() / 1000;

    // Recréer les objets dans les limites
    const deletedObjects = runtimeScene.deletedObjects[layerName];
    for (let objectName in deletedObjects) {
        const objectList = deletedObjects[objectName];
        for (let i = objectList.length - 1; i >= 0; i--) {
            const data = objectList[i];
            const objectLeft = data.x;
            const objectRight = data.x + (data.width || 0);
            const objectTop = data.y;
            const objectBottom = data.y + (data.height || 0);

            // Vérifier si la position est dans les limites de recréation
            if (objectRight >= leftBoundary && objectLeft <= rightBoundary && objectBottom >= topBoundary && objectTop <= bottomBoundary) {
                const elapsedTime = restoreTime - data.cullTime;

                // Recréer l'objet
                const newObject = runtimeScene.createObject(objectName);
                newObject.setPosition(data.x, data.y);
                newObject.setZOrder(data.zOrder);
                newObject.setAngle(data.angle);
                newObject.setLayer(data.layer);

                if (data.width !== undefined && newObject.setWidth) newObject.setWidth(data.width);
                if (data.height !== undefined && newObject.setHeight) newObject.setHeight(data.height);
                if (data.opacity !== undefined && newObject.setOpacity) newObject.setOpacity(data.opacity);

                if (data.hidden !== undefined) newObject.hide(data.hidden);

                const targetVariables = newObject.getVariables();
                const sourceVariables = data.variables;
                for (const variableName in sourceVariables) {
                    if (sourceVariables.hasOwnProperty(variableName)) {
                        targetVariables.get(variableName).setString(sourceVariables[variableName]);
                    }
                }

                const objectTimers = data.timers;
                for (const timerName in objectTimers) {
                    const timerValue = objectTimers[timerName];
                    newObject.resetTimer(timerName);
                    newObject._timers.get(timerName).setTime((timerValue + elapsedTime) * 1000);
                }

                objectList.splice(i, 1);
            }
        }
    }

    for (let objectName in deletedObjects) {
        if (deletedObjects[objectName].length === 0) {
            delete deletedObjects[objectName];
        }
    }
});

3 Likes