[JAVA] Ein beschissener Typ, der Layoutanpassungen bei der Entwicklung von libGDX nüchtern und effizient vornimmt

Einführung

Ich möchte meine eigenen Tipps schreiben, um die Layoutanpassung, die ich kürzlich begonnen habe, etwas effizienter zu gestalten. Es gibt keine Neuheit, also danke. Wenn es etwas Besseres oder Besseres gibt, wäre ich Ihnen dankbar, wenn Sie als Kommentar in diesem Artikel oder als Kommentar antworten könnten.

Annahme

Entwicklung unter Verwendung der folgenden

Problem

Bei Verwendung von Scene2d entspricht die Koordinatenposition in etwa den in der Gruppe begrenzten lokalen Koordinaten Aufgrund des Layouts des Bildschirms weicht die Einstellung der Position nicht so stark ab.

In der Phase der Feineinstellung der Position (z. B. in der Phase der Erstellung eines Bildschirmmodells) müssen jedoch die Koordinatenposition und die Größe der Bildschirmoberfläche mehrmals geändert werden. Mit anderen Worten, wenn Sie es einfach tun, müssen Sie Ihre Java-Klassen jedes Mal neu kompilieren. Obwohl ich heutzutage nicht mehr unter der Geschwindigkeit der Java-Kompilierung leide (Quelle), ist es lächerlich und zeitaufwändig, jedes Mal zu kompilieren und neu zu starten, um eine einfache Ausrichtung zu erreichen.

Lösung

Verwenden Sie PropertiesUtils, um layoutbezogene Werte in der Eigenschaftendatei zu haben. Dieses Util wurde bereits früher zusammengefasst. Hinweise zur Utils-Klasse von libGDX

Was ist in der Praxis zu tun?

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() {
        //Verschiedene Verarbeitung
        try{
            InputStreamReader reader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream("debugCache.properties"));
            PropertiesUtils.load(debugCache, reader);
            StreamUtils.closeQuietly(reader);
        } catch (IOException e) {
            //Ich drücke es mit aller Kraft, aber ahme kein gutes Mädchen nach
        }

        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);
    }
}

Und platzieren Sie die Eigenschaftendatei an einem Ort wie 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

Es ist etwas matschig, aber dies ermöglicht es Ihnen, das Layout mithilfe der Werte in der Eigenschaftendatei anzupassen.

Starten Sie dann die Spiel-App. Es soll die Desktop-Version starten.

Wir werden die Position von Akteuren wie a, b, c und d im Quellcode anpassen, den wir zuvor geschrieben haben. Insbesondere sollte eine Datei mit dem Namen debugCache.properties unter desktop / build / resources / main generiert worden sein, also werde ich damit spielen. Auf diese Weise kann die Position jedes Mal angepasst werden, wenn ein Akteur der Hoge-Klasse instanziiert wird. Was für ein Mist. Aber es ist schneller als jedes Mal zu kompilieren.

Was tun, nachdem die Positionseinstellung abgeschlossen ist?

Es gibt keinen Trick, diesen `` ObjectMap <String, String> `jedes Mal zu analysieren und in einen numerischen Typ zu konvertieren. Angenommen, die Koordinaten, der Maßstab und die Schriftgröße wurden festgelegt. Schreiben Sie den Code, um den Quellcode so umzuschreiben, dass die Werte in der Eigenschaftendatei angewendet werden. Bitte schließen Sie die Augen, um zu sehen, dass es Java SE 7 mit ein wenig Überspringen entspricht.

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;
    }
}

Wenn Sie dies tun, wird der Quellcode auf die in der Eigenschaftendatei festgelegten Werte umgeschrieben.

Zusammenfassung

Ich bin dankbar für statisches Tippen, aber es gibt einige Teile, die ich dynamisch machen möchte! Ich möchte mich wirklich schlauer fühlen.

Recommended Posts

Ein beschissener Typ, der Layoutanpassungen bei der Entwicklung von libGDX nüchtern und effizient vornimmt
Der Typ, der mit Kotlin mit Ressourcen versucht
Der Typ, der die Sitzungsreplikation mit Tomcat durchführt
[Grobe Erklärung] So trennen Sie den Betrieb der Produktionsumgebung und der Entwicklungsumgebung mit Rails
[Java] Schneiden Sie einen Teil der Zeichenfolge mit Matcher und regulären Ausdrücken aus