I created a simple memory game in Java Applet. I have a problem with cards. Images need some extra load time during the first appearance. How to fix that? I need to show a image instantly after card flip.
I display loading screen until application isn't in AppStates.READY or AppStates.WAIT_FOR_START state but it dosen't help.
Memo.cs - main class with images loading
public class Memo extends JApplet {
//...
public void init() {
//...
try {
SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createGUI(); }});
}
catch(Exception e) {
e.printStackTrace();
}
}
private void createGUI() {
final Model model = new Model(...);
final View view = new View(model);
getContentPane().add(view, BorderLayout.CENTER);
setBackground(backgroundColor);
setPreferredSize(new Dimension(width, height));
model.setLoading(loadImages(loadingPath, format, 1));
model.setCardsImages(loadImages(cardImagePath, format, 13));
//...
model.setAppState(AppStates.PROCESS);
model.startNewGame();
view.repaint();
}
private Image[] loadImages(String path1, String path2, int count) {
Image[] imgs = new Image[count];
for(int i = 0; i < count; ++i) {
imgs[i] = getImage(getCodeBase(), path1 + i + path2);
}
return imgs;
}
}
Model.cs - hold images and application state, init board
public class Model {
//...
private AppStates appState;
private Image[] cardsImages;
public Model(...) {
//...
appState = AppStates.INIT;
}
public void startNewGame() {
setAppState(AppStates.PROCESS);
//... - init board - table with images' id
setAppState(AppStates.WAIT_FOR_START);
}
public void setCardsImages(Image[] cardsImages) {
this.cardsImages = cardsImages;
}
public Image getCardsImage(int v) {
return cardsImages[v];
}
public AppStates getAppState() {
return appState;
}
public void setAppState(AppStates appState) {
this.appState = appState;
//...
}
//...
}
View.cs - display board
public class View extends JPanel {
//...
private Model model;
public View(Model model) {
this.model = model;
//...
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if(model != null) {
switch (model.getAppState()) {
//...
case WAIT_FOR_START:
case READY:
//...
drawBoard(g2d, model.getBoard(), model.getStates(), model.getFrontTypes());
break;
}
}
repaint();
}
private void drawBoard(Graphics2D g2d, int[][] board, int[][] states, int[][] frontTypes) {
if(board != null && states != null && board.length > 0 && states.length > 0) {
for(int x = 0; x < board.length; x++) {
for(int y = 0; y < board[x].length; y++) {
if(states[x][y] != Model.HIDE) {
Image img = null;
//...
img = model.getCardsImage(board[x][y]);
g2d.drawImage(
img,
model.getFirstCardX() + x * model.getCardDistance() + x * model.getCardWidth(),
model.getFirstCardY() + y * model.getCardDistance() + y * model.getCardHeight(),
model.getCardWidth(),
model.getCardHeight(),
null);
//...
}
}
}
}
}
}
From the JavaDocs..
public Image getImage(URL url)..
This method always returns immediately, whether or not the image exists. When this applet attempts to draw the image on the screen, the data will be loaded.
Use ImageIO.read(URL) instead. This method will 'block' (it will stop at that code line) until the image is read. So when the app. goes to use the image, it has already been completely loaded.
Another way to get around the problem (not quite the way you wanted) is to change..
g2d.drawImage(
img,
model.getFirstCardX() + x * model.getCardDistance() + x * model.getCardWidth(),
model.getFirstCardY() + y * model.getCardDistance() + y * model.getCardHeight(),
model.getCardWidth(),
model.getCardHeight(),
null);
To..
g2d.drawImage(
img,
model.getFirstCardX() + x * model.getCardDistance() + x * model.getCardWidth(),
model.getFirstCardY() + y * model.getCardDistance() + y * model.getCardHeight(),
model.getCardWidth(),
model.getCardHeight(),
this);
If the image is loaded asynchronously (e.g. using Applet.getImage(URL)) the GUI will be notified to repaint as more becomes available.
you can take the advantage of double buffering in Swing and displaying at once when everything is ready.
If you need to do it inbetween you can keep a pre-developed copy and displaying it when required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With