[JAVA] Un gars de merde qui fait des ajustements de mise en page sobres et efficaces avec le développement de libGDX

introduction

Je voudrais écrire mes propres conseils pour rendre l'ajustement de la mise en page que j'ai commencé récemment un peu plus efficace. Il n'y a pas de nouveauté, alors merci. S'il y a quelque chose de mieux ou de mieux, je vous serais reconnaissant de bien vouloir répondre en tant que commentaire dans cet article ou en tant que commentaire.

supposition

Développement utilisant les éléments suivants

problème

Lorsque vous utilisez Scene2d, la position des coordonnées correspond à peu près aux coordonnées locales confinées dans le groupe, donc En raison de la disposition de l'écran, le réglage de la position ne dévie pas tellement.

Cependant, au stade du réglage fin de la position (par exemple, au stade de la réalisation d'une maquette d'écran), il est nécessaire de modifier plusieurs fois la position des coordonnées et la taille de l'interface utilisateur de l'écran. En d'autres termes, si vous le faites simplement, vous devrez recompiler vos classes Java à chaque fois. Bien que je ne souffre plus des vitesses de compilation Java ces jours-ci (source), il est ridicule et prend du temps de compiler et de relancer à chaque fois pour un alignement simple.

Solution

Utilisez PropertiesUtils pour avoir des valeurs liées à la disposition dans le fichier de propriétés. Cet util a été résumé plus tôt. Notes sur la classe Utils de libGDX

Que faire en pratique

Hoge.java



import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.PropertiesUtils;
import com.badlogic.gdx.utils.StreamUtils;

import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Created by yy_yank on 2017/02/01.
 */
public class Hoge extends Group {


    ObjectMap<String, String> debugCache = new ObjectMap<>();

    public Hoge() {
        //Traitement divers
        try{
            InputStreamReader reader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream("debugCache.properties"));
            PropertiesUtils.load(debugCache, reader);
            StreamUtils.closeQuietly(reader);
        } catch (IOException e) {
            //Je le serre de toutes mes forces, mais n'imite pas une bonne fille
        }

        init();
    }
    
    private void init() {

        Actor a = new Actor();
        a.setScale(Float.parseFloat(debugCache.get("a.scale")));
        addActor(a);
        a.setPosition(Float.parseFloat(debugCache.get("a.x")), Float.parseFloat(debugCache.get("a.y")));
        Actor b = new Actor();
        b.setPosition(Float.parseFloat(debugCache.get("b.x")), Float.parseFloat(debugCache.get("b.y")));
        addActor(b);
        Actor c = new Actor();
        c.setPosition(Float.parseFloat(debugCache.get("c.x")), Float.parseFloat(debugCache.get("c.y")));
        addActor(c);
        Actor d = new Actor();
        d.setPosition(Float.parseFloat(debugCache.get("d.x")), Float.parseFloat(debugCache.get("d.y")));
        addActor(d);
    }
}

Et placez le fichier de propriété dans un endroit comme android / assets.

debugCache.properties


a.x=100
a.y=200
a.scale=1
b.x=100
b.y=300
c.x=100
c.y=400
d.x=100
d.y=500

C'est un peu flou, mais cela vous permet d'ajuster la mise en page en utilisant les valeurs du fichier de propriétés.

Ensuite, lancez l'application de jeu. Il est censé démarrer la version de bureau.

Nous ajusterons la position des acteurs tels que a, b, c et d dans le code source que nous avons écrit précédemment. Plus précisément, un fichier appelé debugCache.properties aurait dû être généré sous desktop / build / resources / main, donc je vais jouer avec ça. Ce faisant, la position peut être ajustée à chaque fois qu'un acteur de la classe Hoge est instancié. Quelle merde. Mais c'est plus rapide que de compiler à chaque fois.

Que faire une fois le réglage de la position terminé

Ce type ```Object Map <String, String> est analysé à chaque fois et converti en un type numérique, il n'y a donc pas d'astuce. En supposant que les coordonnées, l'échelle et la taille de la police ont été décidées, j'écrirai le code pour réécrire le code source afin que les valeurs du fichier de propriétés soient appliquées. Veuillez fermer les yeux pour voir que cela équivaut à Java SE 7 avec un petit saut.

import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.PropertiesUtils;
import com.badlogic.gdx.utils.StreamUtils;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.List;


public class DebugPropertiesConverter implements InternalConverter{


    private ObjectMap<String, String> debugCache;
    
    CacheConfigurationFactory factory = new CacheConfigurationFactory() {
        @Override
        public String createCacheVariableName() {
            return "debugCache";
        }

        @Override
        public String createCacheFileName() {
            return "debugCache.properties";
        }

        @Override
        public List<Pair<String, String>> cretateTargetStringPair(String between, String value) {
            return Arrays.asList(
                    new Pair<>("Integer.parseInt("+createCacheVariableName()+".get(\""+ between +"\"))", value),
                    new Pair<>("Double.parseDouble("+createCacheVariableName()+".get(\""+ between +"\"))", value),
                    new Pair<>("Float.parseFloat("+createCacheVariableName()+".get(\""+ between +"\"))", value + "f")
            );
        }
    };

    
    public static void main(String[] args) throws Exception {
        new DebugPropertiesConverter().run();
    }

    public void run() throws Exception {
        FileVisitor<Path> visitor = new InternalFileVisitor(this);
        Files.walkFileTree(Paths.get("/Users/yy_yank/work/projects/hogehoge/core/src/com/github/yyYank"
                ,"your"
                ,"package"
                ,"dir"
        ), visitor);
    }


    @Override
    public ObjectMap<String, String> readBetweenString() throws IOException {
        if(debugCache != null) {
            return debugCache;
        }
        InputStreamReader reader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream(factory.createCacheFileName()));
        this.debugCache = new ObjectMap<>();
        PropertiesUtils.load(debugCache, reader);
        System.out.println(debugCache);
        StreamUtils.closeQuietly(reader);
        return debugCache;
    }

    @Override
    public void executeOnFile(Path file, BasicFileAttributes attrs) throws IOException {
        ObjectMap<String, String> betweens = readBetweenString();
        List<String> lines = Files.readAllLines(file, Charset.forName("UTF-8"));

        boolean isRewrite = false;
        for (ObjectMap.Entry<String, String> between : betweens) {
            List<Pair<String, String>> targets = factory.cretateTargetStringPair(between.key, between.value);
            for (Pair<String, String> target : targets) {
                for (int i = 0; i < lines.size(); i++) {
                    String line = lines.get(i);
                    isRewrite = isRewrite ? isRewrite : line.contains(target.key);
                    lines.set(i, line.replace(target.key, target.value));
                }
            }
        }
        // rewrite
        if(isRewrite) {
            System.out.println("rewrite file.... -> " + file.getFileName());
            Files.write(file, lines, Charset.forName("UTF-8"));
        } else {
            System.out.println("[SKIP]" + file.getFileName());
        }
    }

    @Override
    public void executeOnDir(Path dir, BasicFileAttributes attrs) {
        // do nothing
    }

    @Override
    public boolean filterExtension(Path file) {
        return file.getFileName().toString().endsWith("java");
    }
}

interface CacheConfigurationFactory {
    String createCacheVariableName();
    String createCacheFileName();
    List<Pair<String, String>> cretateTargetStringPair(String between, String value);
}

interface InternalConverter {
    ObjectMap<String, String> readBetweenString() throws IOException;
    void executeOnFile(Path file, BasicFileAttributes attrs) throws IOException;
    void executeOnDir(Path dir, BasicFileAttributes attrs);
    boolean filterExtension(Path file);

}


class InternalFileVisitor implements FileVisitor<Path> {


    private final DebugPropertiesConverter converter;

    public InternalFileVisitor(DebugPropertiesConverter converter) {
        this.converter = converter;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        print("preVisitDirectory : " + dir.getFileName());
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        if(converter.filterExtension(file)) {
            print("visitFile : " + file.getFileName());
            converter.executeOnFile(file, attrs);
        } else {
            print("[SKIP]visitFile : " + file.getFileName());
        }
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
        String error = String.format(" [exception=%s, message=%s]", exc.getClass(), exc.getMessage());
        print("visitFileFailed : " + file.getFileName() + error);
        return FileVisitResult.CONTINUE;
    }

    protected void print(String message) {
        System.out.println(message);
    }
}

class Pair<K, V>{
    public final K key;
    public final V value;
    Pair(K k, V v) {
        this.key = k;
        this.value = v;
    }
}

Lorsque vous effectuez cette opération, le code source sera réécrit avec les valeurs définies dans le fichier de propriétés.

Résumé

Je suis reconnaissant pour la saisie statique, mais il y a certaines parties que je souhaite rendre dynamique! Je veux vraiment me sentir plus intelligent.

Recommended Posts

Un gars de merde qui fait des ajustements de mise en page sobres et efficaces avec le développement de libGDX
Le gars qui essaie avec des ressources avec Kotlin
Le gars qui fait la réplication de session avec Tomcat
[Explication approximative] Comment séparer le fonctionnement de l'environnement de production et de l'environnement de développement avec Rails
[Java] Découpez une partie de la chaîne de caractères avec Matcher et des expressions régulières