-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add graphical user interface (GUI) for brick game
- Loading branch information
Showing
34 changed files
with
960 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,30 @@ | ||
package com.github.vitalibo.brickgame; | ||
|
||
|
||
import com.github.vitalibo.brickgame.core.ui.BrickGameFrame; | ||
|
||
public class Run { | ||
|
||
public static void main(String[] args) { | ||
public static void main(String[] args) throws InterruptedException { | ||
BrickGameFrame frame = new BrickGameFrame(); | ||
boolean[][] canvas = new boolean[20][10]; | ||
int x = 0, y = -1; | ||
|
||
while (true) { | ||
if (++y >= 20) { | ||
y = 0; | ||
if (++x >= 10) { | ||
x = 0; | ||
} | ||
} | ||
|
||
canvas[y][x] = true; | ||
frame.getFrame().draw(canvas); | ||
canvas[y][x] = false; | ||
frame.getScore().inc(); | ||
|
||
Thread.sleep(50); | ||
} | ||
} | ||
|
||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
src/main/java/com/github/vitalibo/brickgame/core/Builder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.github.vitalibo.brickgame.core; | ||
|
||
import java.util.function.Consumer; | ||
import java.util.function.Function; | ||
|
||
public class Builder<T> { | ||
|
||
private final T o; | ||
|
||
private Builder(T o) { | ||
this.o = o; | ||
} | ||
|
||
public Builder<T> with(Consumer<T> consumer) { | ||
consumer.accept(o); | ||
return this; | ||
} | ||
|
||
public <M> Builder<M> map(Function<T, M> function) { | ||
return Builder.of(function.apply(o)); | ||
} | ||
|
||
public T get() { | ||
return o; | ||
} | ||
|
||
public static <T> Builder<T> of(T o) { | ||
return new Builder<>(o); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.github.vitalibo.brickgame.core; | ||
|
||
@FunctionalInterface | ||
public interface Grid { | ||
|
||
void draw(boolean[][] src); | ||
|
||
} |
31 changes: 31 additions & 0 deletions
31
src/main/java/com/github/vitalibo/brickgame/core/Number.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.github.vitalibo.brickgame.core; | ||
|
||
public interface Number { | ||
|
||
int get(); | ||
|
||
void set(int value); | ||
|
||
default int inc() { | ||
return inc(1); | ||
} | ||
|
||
default int inc(int h) { | ||
return Builder.of(get()) | ||
.map(v -> v + h) | ||
.with(this::set) | ||
.get(); | ||
} | ||
|
||
default int dec() { | ||
return dec(1); | ||
} | ||
|
||
default int dec(int h) { | ||
return Builder.of(get()) | ||
.map(v -> v - h) | ||
.with(this::set) | ||
.get(); | ||
} | ||
|
||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/com/github/vitalibo/brickgame/core/State.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.github.vitalibo.brickgame.core; | ||
|
||
public interface State { | ||
|
||
default boolean change() { | ||
return Builder.of(get()) | ||
.map(s -> !s) | ||
.with(this::set) | ||
.get(); | ||
} | ||
|
||
boolean get(); | ||
|
||
void set(boolean state); | ||
|
||
} |
105 changes: 105 additions & 0 deletions
105
src/main/java/com/github/vitalibo/brickgame/core/ui/BrickGameFrame.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package com.github.vitalibo.brickgame.core.ui; | ||
|
||
import com.github.vitalibo.brickgame.core.Builder; | ||
import lombok.Getter; | ||
|
||
import javax.swing.*; | ||
import javax.swing.border.LineBorder; | ||
import java.awt.*; | ||
|
||
public class BrickGameFrame extends JFrame { | ||
|
||
@Getter | ||
private final BrickPanel frame; | ||
@Getter | ||
private final BrickPanel support; | ||
@Getter | ||
private final NumberPanel score; | ||
@Getter | ||
private final NumberPanel speed; | ||
@Getter | ||
private final NumberPanel level; | ||
@Getter | ||
private final IconPanel sound; | ||
@Getter | ||
private final IconPanel pause; | ||
|
||
public BrickGameFrame() { | ||
super("Brick Game"); | ||
this.frame = new BrickPanel(10, 20); | ||
this.support = new BrickPanel(4, 4); | ||
this.score = new NumberPanel(6); | ||
this.speed = new NumberPanel(2, 18); | ||
this.level = new NumberPanel(2, 18); | ||
this.sound = Builder.of(new IconPanel("sound_on", "sound_off", true)) | ||
.with(i -> i.setPreferredSize(new Dimension(16, 16))) | ||
.get(); | ||
this.pause = Builder.of(new IconPanel("pause_on", "pause_off")) | ||
.with(i -> i.setPreferredSize(new Dimension(40, 13))) | ||
.get(); | ||
this.init(); | ||
} | ||
|
||
private void init() { | ||
this.setBackground(new Color(0x6D785C)); | ||
this.setContentPane(root()); | ||
this.pack(); | ||
try { | ||
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); | ||
SwingUtilities.updateComponentTreeUI(this); | ||
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
|
||
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); | ||
this.setSize(new Dimension(190, 260)); | ||
this.setResizable(false); | ||
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize(); | ||
this.setLocation((int) ((dimension.getWidth() - this.getWidth()) / 2), | ||
(int) ((dimension.getHeight() - this.getHeight()) / 2)); | ||
this.setVisible(true); | ||
} | ||
|
||
private JPanel root() { | ||
return Builder.of(new JPanel()) | ||
.with(root -> root.setOpaque(false)) | ||
.with(root -> Builder.of(frame) | ||
.with(frame -> frame.setBorder(new LineBorder(new Color(0x0), 1))) | ||
.with(root::add)) | ||
.with(root -> panel(new GridLayout(0, 1)) | ||
.with(panel -> panel(new GridLayout(0, 1)) | ||
.with(o -> o.add(label("Score", JLabel.RIGHT))) | ||
.with(o -> o.add(score)) | ||
.with(panel::add)) | ||
.with(panel -> panel(new FlowLayout(FlowLayout.CENTER, 0, 0)) | ||
.with(o -> o.add(support)) | ||
.with(panel::add)) | ||
.with(panel -> panel(new GridLayout(0, 1)) | ||
.with(o -> o.add(label("Speed", JLabel.CENTER))) | ||
.with(o -> o.add(speed)) | ||
.with(panel::add)) | ||
.with(panel -> panel(new GridLayout(0, 1)) | ||
.with(o -> o.add(level)) | ||
.with(o -> o.add(label("Level", JLabel.CENTER))) | ||
.with(panel::add)) | ||
.with(panel -> panel(new GridLayout(0, 1)) | ||
.with(o -> o.add(sound)) | ||
.with(o -> o.add(pause)) | ||
.with(panel::add)) | ||
.with(root::add)) | ||
.get(); | ||
} | ||
|
||
private static JLabel label(String text, int alignment) { | ||
return Builder.of(new JLabel(text)) | ||
.with(l -> l.setFont(new Font("Consolas", Font.BOLD, 11))) | ||
.with(l -> l.setHorizontalAlignment(alignment)) | ||
.get(); | ||
} | ||
|
||
private static Builder<JPanel> panel(LayoutManager layout) { | ||
return Builder.of(new JPanel(layout)) | ||
.with(p -> p.setOpaque(false)); | ||
} | ||
|
||
} |
77 changes: 77 additions & 0 deletions
77
src/main/java/com/github/vitalibo/brickgame/core/ui/BrickPanel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.github.vitalibo.brickgame.core.ui; | ||
|
||
import com.github.vitalibo.brickgame.core.Builder; | ||
import com.github.vitalibo.brickgame.core.Grid; | ||
import com.github.vitalibo.brickgame.core.State; | ||
|
||
import javax.swing.*; | ||
import java.awt.*; | ||
import java.util.stream.IntStream; | ||
|
||
public class BrickPanel extends JPanel implements Grid { | ||
|
||
private static final Color ON = new Color(0x000000); | ||
private static final Color OFF = new Color(0x61705B); | ||
|
||
private final Brick[][] bricks; | ||
|
||
private final int width; | ||
private final int height; | ||
|
||
BrickPanel(final int width, final int height) { | ||
this.width = width; | ||
this.height = height; | ||
this.bricks = IntStream.range(0, height) | ||
.mapToObj(h -> IntStream.range(0, width) | ||
.mapToObj(w -> new Brick()) | ||
.peek(this::add) | ||
.toArray(Brick[]::new)) | ||
.toArray(v -> new Brick[height][width]); | ||
this.setLayout(Builder.of(new GridLayout(0, width)) | ||
.with(l -> l.setHgap(1)) | ||
.with(l -> l.setVgap(1)) | ||
.get()); | ||
this.setOpaque(false); | ||
} | ||
|
||
@Override | ||
public synchronized void draw(boolean[][] src) { | ||
IntStream.range(0, height) | ||
.forEach(h -> IntStream.range(0, width) | ||
.forEach(w -> bricks[h][w].set(src[h][w]))); | ||
} | ||
|
||
static class Brick extends JPanel implements State { | ||
|
||
private boolean state; | ||
|
||
Brick() { | ||
this.setOpaque(false); | ||
} | ||
|
||
@Override | ||
public boolean get() { | ||
return state; | ||
} | ||
|
||
@Override | ||
public void set(boolean state) { | ||
if (this.state != state) { | ||
this.state = state; | ||
repaint(); | ||
} | ||
} | ||
|
||
@Override | ||
protected void paintComponent(Graphics g) { | ||
super.paintComponent(g); | ||
Color color = state ? ON : OFF; | ||
g.setColor(color); | ||
g.drawRect(0, 0, 9, 9); | ||
g.setColor(color); | ||
g.fillRect(3, 3, 4, 4); | ||
} | ||
|
||
} | ||
|
||
} |
70 changes: 70 additions & 0 deletions
70
src/main/java/com/github/vitalibo/brickgame/core/ui/IconPanel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package com.github.vitalibo.brickgame.core.ui; | ||
|
||
import com.github.vitalibo.brickgame.core.State; | ||
|
||
import javax.imageio.ImageIO; | ||
import javax.swing.*; | ||
import java.awt.*; | ||
import java.io.IOException; | ||
|
||
public class IconPanel extends JPanel implements State { | ||
|
||
private boolean state; | ||
|
||
IconPanel(String on, String off) { | ||
this(on, off, false); | ||
} | ||
|
||
IconPanel(String on, String off, boolean state) { | ||
this.state = state; | ||
this.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); | ||
this.setOpaque(false); | ||
this.add(new Canvas(IconPanel.resourceAsImage(on), IconPanel.resourceAsImage(off))); | ||
} | ||
|
||
@Override | ||
public boolean get() { | ||
return state; | ||
} | ||
|
||
@Override | ||
public synchronized void set(boolean state) { | ||
if (this.state != state) { | ||
this.state = state; | ||
repaint(); | ||
} | ||
} | ||
|
||
@Override | ||
public void setPreferredSize(Dimension preferredSize) { | ||
super.setPreferredSize(preferredSize); | ||
this.getComponent(0).setPreferredSize(preferredSize); | ||
} | ||
|
||
private static Image resourceAsImage(String resource) { | ||
try { | ||
return ImageIO.read(ClassLoader.getSystemResourceAsStream(String.format("ui/%s.bmp", resource))); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private class Canvas extends JPanel { | ||
|
||
private final Image ON; | ||
private final Image OFF; | ||
|
||
private Canvas(Image ON, Image OFF) { | ||
this.ON = ON; | ||
this.OFF = OFF; | ||
} | ||
|
||
@Override | ||
protected void paintComponent(Graphics g) { | ||
super.paintComponent(g); | ||
g.drawImage(state ? ON : OFF, 0, 0, null); | ||
} | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.