Java 对于一个简单的2D游戏,是否有一种有效的方法将纹理加载为.PNG图像
我正在编写一个简单的基于2D块的游戏(类似于Minecraft)来开始使用Java。我有很多游戏机制,比如world generation,但加载纹理既笨重又低效。基本上,我使用加载函数分别加载所有纹理(纹理是16x16.PNG文件)。游戏中的每个块都有一个名称(例如“石头”、“泥土”),当游戏渲染瓷砖时,它会从textureManager类加载纹理。这是可行的,但我必须硬编码每个纹理加载和返回。我想做的是让纹理自动加载,但仍然有它们的字符串索引。例如,我希望游戏加载纹理文件夹中的所有.PNG文件,但保留它们的名称,这样我就可以说loadTexture(“石头”) 这是我当前的纹理管理器代码。当游戏开始时,它简单地加载每个文件,并为背景瓷砖使每个文件变暗。这是一个痛苦的添加新的纹理,只是没有效率Java 对于一个简单的2D游戏,是否有一种有效的方法将纹理加载为.PNG图像,java,file,textures,Java,File,Textures,我正在编写一个简单的基于2D块的游戏(类似于Minecraft)来开始使用Java。我有很多游戏机制,比如world generation,但加载纹理既笨重又低效。基本上,我使用加载函数分别加载所有纹理(纹理是16x16.PNG文件)。游戏中的每个块都有一个名称(例如“石头”、“泥土”),当游戏渲染瓷砖时,它会从textureManager类加载纹理。这是可行的,但我必须硬编码每个纹理加载和返回。我想做的是让纹理自动加载,但仍然有它们的字符串索引。例如,我希望游戏加载纹理文件夹中的所有.PNG文
package graphics;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
public class textureManager {
private static final BufferedImage darken(BufferedImage image) {
return new RescaleOp(.7f, 0, null).filter(image, null);
}
private static final String path = "/assets/textures/";
// textures
public static final BufferedImage unknown = renderer.loadImage(path + "unknown.png");
private static final BufferedImage stone = renderer.loadImage(path + "stone.png");
private static final BufferedImage grass = renderer.loadImage(path + "grass.png");
private static final BufferedImage dirt = renderer.loadImage(path + "dirt.png");
private static final BufferedImage iron_ore = renderer.loadImage(path + "iron_ore.png");
private static final BufferedImage coal_ore = renderer.loadImage(path + "coal_ore.png");
private static final BufferedImage diamond_ore = renderer.loadImage(path + "diamond_ore.png");
private static final BufferedImage bedrock = renderer.loadImage(path + "bedrock.png");
private static final BufferedImage andesite = renderer.loadImage(path + "andesite.png");
private static final BufferedImage granite = renderer.loadImage(path + "granite.png");
private static final BufferedImage marble = renderer.loadImage(path + "marble.png");
// darkened textures
private static final BufferedImage dark_stone = darken(stone);
private static final BufferedImage dark_grass = darken(grass);
private static final BufferedImage dark_dirt = darken(dirt);
private static final BufferedImage dark_iron_ore = darken(iron_ore);
private static final BufferedImage dark_coal_ore = darken(coal_ore);
private static final BufferedImage dark_diamond_ore = darken(diamond_ore);
private static final BufferedImage dark_andesite = darken(andesite);
private static final BufferedImage dark_granite = darken(granite);
private static final BufferedImage dark_marble = darken(marble);
// animations
private static Animation player = new Animation("player");
private static Animation lava = new Animation("lava");
private static Animation plant_01 = new Animation("plant_01");
/** returns the textures of the name provided */
public static BufferedImage getTexture(String name, boolean darken) {
if(name.equals("air")) return null;
if(name.equals("stone")) if(!darken) return stone; else return dark_stone;
if(name.equals("grass")) if(!darken) return grass; else return dark_grass;
if(name.equals("dirt")) if(!darken) return dirt; else return dark_dirt;
if(name.equals("iron_ore")) if(!darken) return iron_ore; else return dark_iron_ore;
if(name.equals("coal_ore")) if(!darken) return coal_ore; else return dark_coal_ore;
if(name.equals("diamond_ore")) if(!darken) return diamond_ore; else return dark_diamond_ore;
if(name.equals("bedrock")) return bedrock;
if(name.equals("andesite")) if(!darken) return andesite; else return dark_andesite;
if(name.equals("granite")) if(!darken) return granite; else return dark_granite;
if(name.equals("marble")) if(!darken) return marble; else return dark_marble;
return unknown;
}
/** returns the animation of the name provided */
public static Animation getAnimation(String name) {
if(name.equals("player")) return player;
if(name.equals("lava")) return lava;
if(name.equals("plant_01")) return plant_01;
return null;
}
}
虽然这段代码有效,但我想添加一种更有效的方法,但我不知道如何添加。我曾考虑使用数组列表来存储图像,但它不接受字符串索引。也许是一个可以管理数组列表和名称索引的自定义类
注意:动画是一个自定义类,用于设置从文件夹加载的纹理的动画。这些文件可以忽略。我的方法是不列出所有要加载的文件。加载该路径中的所有文件。将它们放入贴图
map textures=new HashMap()
然后根据文件名创建密钥。然后可以生成并添加深色纹理,将“深色”或“d”添加到键
。然后在“获取纹理”(get texture)中,您需要做的就是if(变暗)纹理。get('d'+name)else纹理。get(name)
一旦从文件中加载了所有纹理,就可以获得黑色版本
textures.putAll(textures.entrySet().stream().collect(Collectors.toMap(entry->"d"+entry.getKey(),entry->darken(entry.getValue()))));
你想要一个
Map的一个常见(可能是最常见)实现是:
我目前正在将文件加载到哈希映射中。我将结合您的响应和之前的另一个代码,并制作一个纹理加载函数。谢谢你的第二个例子效果很好。我得到了渲染纹理时要加载的枚举列表。唯一的问题是,如果找不到块而不是返回未知值(只是一个空白纹理),枚举将导致游戏崩溃。我有一些代码来检查一个值是否有效,但由于渲染器每帧必须调用getTexture函数大约2400次,因此检查将帧速率降低得太多,无法播放。“找不到块”是什么意思?你是说纹理类型可以为空吗?如果它不是null,那么根据定义,它必须是枚举常量之一,并且必须有对应的映像。
private static final Map<String, Map<Boolean, BufferedImage>> textures;
static {
String[] baseNames = {
"unknown",
"stone",
"grass",
"dirt",
"iron_ore",
"coal_ore",
"diamond_ore",
"bedrock",
"andesite",
"granite",
"marble",
};
Map<String, Map<Boolean, BufferedImage>> map = new HashMap<>();
for (String baseName : baseNames) {
BufferedImage regular =
renderer.loadImage(path + baseName + ".png");
BufferedImage dark = darken(regular);
Map<Boolean, BufferedImage> regularAndDark = new HashMap<>(2);
regularAndDark.put(false, regular);
regularAndDark.put(true, dark);
map.put(baseName, Collections.unmodifiableMap(regularAndDark));
}
textures = Collections.unmodifiableMap(map);
}
/** returns the textures of the name provided */
public static BufferedImage getTexture(String name, boolean darken) {
Map<Boolean, BufferedImage>> matches = textures.get(name);
assert matches != null : "No textures for name \"" + name + "\"";
return matches.get(darken);
}
public enum TextureType {
UNKNOWN,
STONE,
GRASS,
DIRT,
IRON_ORE,
COAL_ORE,
DIAMOND_ORE,
BEDROCK,
ANDESITE,
GRANITE,
MARBLE,
}
private static class Textures {
final BufferedImage regular;
final BufferedImage dark;
Textures(BufferedImage regular) {
this.regular = Objects.requireNonNull(regular,
"Image cannot be null");
this.dark = darken(regular);
}
}
private static final Map<TextureType, Textures> textures;
static {
Map<TextureType, Textures> map = new EnumMap(TextureType.class);
for (TextureType type : TextureType.values()) {
map.put(type,
new Textures(renderer.loadImage(path + baseName + ".png")));
}
textures = Collections.unmodifiableMap(map);
}
/** returns the textures of the name provided */
public static BufferedImage getTexture(TextureType type, boolean darken) {
Objects.requireNonNull(type, "Texture type cannot be null");
Textures match = textures.get(type);
return darken ? match.dark : match.regular;
}