1 package nl.tudelft.jpacman.sprite;
2
3 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4
5 import java.awt.image.BufferedImage;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.util.HashMap;
9 import java.util.Map;
10
11 import javax.imageio.ImageIO;
12
13 /**
14 * Utility to load {@link Sprite}s.
15 *
16 * @author Jeroen Roosen
17 */
18 public class SpriteStore {
19
20 /**
21 * We only need to load images once, so we keep track
22 * of them in a hash map.
23 */
24 private final Map<String, Sprite> spriteMap;
25
26 /**
27 * Create a new sprite store.
28 */
29 public SpriteStore() {
30 spriteMap = new HashMap<>();
31 }
32
33 /**
34 * Loads a sprite from a resource on the class path.
35 * Sprites are loaded once, and then stored in the store
36 * so that they can be efficiently retrieved.
37 *
38 * @param resource
39 * The resource path.
40 * @return The sprite for the resource.
41 * @throws IOException
42 * When the resource could not be loaded.
43 */
44 public Sprite loadSprite(String resource) throws IOException {
45 Sprite result = spriteMap.get(resource);
46 if (result == null) {
47 result = loadSpriteFromResource(resource);
48 spriteMap.put(resource, result);
49 }
50 return result;
51 }
52
53 /**
54 * Loads a sprite from a resource on the class path.
55 *
56 * @param resource
57 * The resource path.
58 * @return A new sprite for the resource.
59 * @throws IOException
60 * When the resource could not be loaded.
61 */
62 @SuppressFBWarnings(
63 value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE",
64 justification = "false positive in java 11"
65 )
66 private Sprite loadSpriteFromResource(String resource) throws IOException {
67 try (InputStream input = SpriteStore.class.getResourceAsStream(resource)) {
68 if (input == null) {
69 throw new IOException("Unable to load " + resource + ", resource does not exist.");
70 }
71 BufferedImage image = ImageIO.read(input);
72 return new ImageSprite(image);
73 }
74 }
75
76 /**
77 * Creates a new {@link AnimatedSprite} from a base image.
78 *
79 * @param baseImage
80 * The base image to convert into an animation.
81 * @param frames
82 * The amount of frames of the animation.
83 * @param delay
84 * The delay between frames.
85 * @param loop
86 * Whether this sprite is a looping animation or not.
87 * @return The animated sprite.
88 */
89 public AnimatedSprite createAnimatedSprite(Sprite baseImage, int frames,
90 int delay, boolean loop) {
91 assert baseImage != null;
92 assert frames > 0;
93
94 int frameWidth = baseImage.getWidth() / frames;
95
96 Sprite[] animation = new Sprite[frames];
97 for (int i = 0; i < frames; i++) {
98 animation[i] = baseImage.split(i * frameWidth, 0, frameWidth,
99 baseImage.getHeight());
100 }
101
102 return new AnimatedSprite(animation, delay, loop);
103 }
104
105 }