├── src
├── icons
│ ├── circle.png
│ ├── polygon.png
│ ├── polygon1.png
│ ├── polygon2.png
│ ├── rectangle.png
│ └── triangle.png
├── main
│ ├── MyLabel.java
│ ├── Window.java
│ ├── MyShape.java
│ └── MainPanel.java
├── shapes
│ ├── Poly.java
│ ├── Rect.java
│ ├── Circle.java
│ └── Triangle.java
└── panels
│ ├── ShapePanel.java
│ ├── ScenePanel.java
│ └── FeaturesPanel.java
├── .classpath
├── .gitignore
├── .project
├── README.md
└── LICENSE
/src/icons/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cbozan/simple-game-engine/HEAD/src/icons/circle.png
--------------------------------------------------------------------------------
/src/icons/polygon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cbozan/simple-game-engine/HEAD/src/icons/polygon.png
--------------------------------------------------------------------------------
/src/icons/polygon1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cbozan/simple-game-engine/HEAD/src/icons/polygon1.png
--------------------------------------------------------------------------------
/src/icons/polygon2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cbozan/simple-game-engine/HEAD/src/icons/polygon2.png
--------------------------------------------------------------------------------
/src/icons/rectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cbozan/simple-game-engine/HEAD/src/icons/rectangle.png
--------------------------------------------------------------------------------
/src/icons/triangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cbozan/simple-game-engine/HEAD/src/icons/triangle.png
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 | /bin/
25 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | simple-game-engine
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/MyLabel.java:
--------------------------------------------------------------------------------
1 | package main;
2 |
3 | import java.awt.Rectangle;
4 |
5 | import javax.swing.ImageIcon;
6 | import javax.swing.JLabel;
7 |
8 | public class MyLabel extends JLabel implements Cloneable{
9 |
10 | public MyLabel(ImageIcon imageIcon) {
11 | super(imageIcon);
12 |
13 | }
14 |
15 |
16 |
17 | @Override
18 | public Object clone() throws CloneNotSupportedException {
19 | return super.clone();
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/shapes/Poly.java:
--------------------------------------------------------------------------------
1 | package shapes;
2 |
3 | import java.awt.Color;
4 |
5 | import main.MyShape;
6 |
7 | public class Poly extends MyShape{
8 |
9 | public Poly(double x, double y, double width, double height, Color borderColor, Color insiderColor, double mass) {
10 | super(x, y, width, height, borderColor, insiderColor, mass);
11 | }
12 |
13 | public Poly(double x, double y, double width, double height, Color borderColor, Color insiderColor) {
14 | super(x, y, width, height, borderColor, insiderColor);
15 | }
16 |
17 | public Poly(double x, double y, double width, double height, Color borderColor) {
18 | super(x, y, width, height, borderColor);
19 | }
20 |
21 | public Poly(double x, double y, double width, double height, double mass) {
22 | super(x, y, width, height, mass);
23 | }
24 |
25 | public Poly(double x, double y, double width, double height) {
26 | super(x, y, width, height);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/shapes/Rect.java:
--------------------------------------------------------------------------------
1 | package shapes;
2 |
3 | import java.awt.Color;
4 |
5 | import main.MyShape;
6 |
7 | public class Rect extends MyShape{
8 |
9 | public Rect(double x, double y, double width, double height, Color borderColor, Color insiderColor, double mass) {
10 | super(x, y, width, height, borderColor, insiderColor, mass);
11 | }
12 |
13 | public Rect(double x, double y, double width, double height, Color borderColor, Color insiderColor) {
14 | super(x, y, width, height, borderColor, insiderColor);
15 | }
16 |
17 | public Rect(double x, double y, double width, double height, Color borderColor) {
18 | super(x, y, width, height, borderColor);
19 | }
20 |
21 | public Rect(double x, double y, double width, double height, double mass) {
22 | super(x, y, width, height, mass);
23 | }
24 |
25 | public Rect(double x, double y, double width, double height) {
26 | super(x, y, width, height);
27 | }
28 |
29 |
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # simple-game-engine
2 | A simple game engine written in java swing, where shapes can be added, their properties (color, position, speed, bounce) can be changed and movement features can be added to certain shapes with real physics rules.
3 |
4 | ---
5 | ## GIFs
6 |
DRAG AND DROP
7 | 
8 |
9 |
10 |
11 | | **CHANGE COLOR** | **CHANGE GRAVITY**|
12 | :------------------------:|:------------------------:|
13 |  | 
14 |
15 |
16 |
17 | FPS
18 | 
19 |
20 |
--------------------------------------------------------------------------------
/src/main/Window.java:
--------------------------------------------------------------------------------
1 | package main;
2 |
3 | import java.awt.EventQueue;
4 | import java.awt.Insets;
5 |
6 | import javax.swing.JFrame;
7 |
8 | public class Window extends JFrame{
9 |
10 |
11 | public static Insets WINDOW_INSETS;
12 | public static final int WINDOW_WIDTH = 800;
13 | public static final int WINDOW_HEIGHT = 500;
14 |
15 | public Window() {
16 | super("cbozan/simple-game-engine");
17 | setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
18 | setDefaultCloseOperation(EXIT_ON_CLOSE);
19 | setResizable(false);
20 | setLocationRelativeTo(null);
21 | setUndecorated(false);
22 | setLayout(null);
23 | setVisible(true);
24 | WINDOW_INSETS = this.getInsets();
25 |
26 | setSize(getWidth() + WINDOW_INSETS.left + WINDOW_INSETS.right, getHeight() + WINDOW_INSETS.top + WINDOW_INSETS.bottom);
27 | setLocationRelativeTo(null);
28 |
29 | this.add(new MainPanel());
30 |
31 | }
32 |
33 |
34 | public static void main(String args[]) {
35 | EventQueue.invokeLater(new Runnable() {
36 | @Override
37 | public void run() {
38 | new Window();
39 | }
40 | });
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 cbozan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/shapes/Circle.java:
--------------------------------------------------------------------------------
1 | package shapes;
2 |
3 | import java.awt.BasicStroke;
4 | import java.awt.Color;
5 | import java.awt.Font;
6 | import java.awt.GradientPaint;
7 | import java.awt.Graphics;
8 | import java.awt.Graphics2D;
9 | import java.io.Serializable;
10 |
11 | import javax.swing.ImageIcon;
12 |
13 | import main.MyShape;
14 |
15 | public class Circle extends MyShape {
16 |
17 | public Circle(double x, double y, double width, double height, Color borderColor, Color insiderColor, double mass) {
18 | super(x, y, width, height, borderColor, insiderColor, mass);
19 | }
20 |
21 | public Circle(double x, double y, double width, double height, Color borderColor, Color insiderColor) {
22 | super(x, y, width, height, borderColor, insiderColor);
23 | }
24 |
25 | public Circle(double x, double y, double width, double height, Color borderColor) {
26 | super(x, y, width, height, borderColor);
27 | }
28 |
29 | public Circle(double x, double y, double width, double height, double mass) {
30 | super(x, y, width, height, mass);
31 | }
32 |
33 | public Circle(double x, double y, double width, double height) {
34 | super(x, y, width, height);
35 | }
36 |
37 | @Override
38 | public void draw(Graphics g) {
39 |
40 | int borderThickness = getBorderWidth() == 1 ? 2 : getBorderWidth();
41 |
42 | Graphics2D g2 = (Graphics2D) g;
43 | g2.setStroke(new BasicStroke(borderThickness));
44 |
45 | g2.setColor(getBorderColor());
46 | g2.drawOval((int) getX(), (int) getY(), (int) getWidth(), (int) getHeight());
47 | g2.setColor(getInsiderColor());
48 | g2.fillOval((int) getX() + (int) (borderThickness / 2), (int) getY() + (int) (borderThickness / 2),
49 | (int) getWidth() - (int) (borderThickness), (int) getHeight() - (int) (borderThickness));
50 |
51 | }
52 |
53 | @Override
54 | public double getArea() {
55 | return Math.PI * getWidth();
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/shapes/Triangle.java:
--------------------------------------------------------------------------------
1 | package shapes;
2 |
3 | import java.awt.BasicStroke;
4 | import java.awt.Color;
5 | import java.awt.GradientPaint;
6 | import java.awt.Graphics;
7 | import java.awt.Graphics2D;
8 |
9 | import main.MyShape;
10 |
11 | public class Triangle extends MyShape{
12 |
13 | public Triangle(double x, double y, double width, double height, Color borderColor, Color insiderColor, double mass) {
14 | super(x, y, width, height, borderColor, insiderColor, mass);
15 | }
16 |
17 | public Triangle(double x, double y, double width, double height, Color borderColor, Color insiderColor) {
18 | super(x, y, width, height, borderColor, insiderColor);
19 | }
20 |
21 | public Triangle(double x, double y, double width, double height, Color borderColor) {
22 | super(x, y, width, height, borderColor);
23 | }
24 |
25 | public Triangle(double x, double y, double width, double height, double mass) {
26 | super(x, y, width, height, mass);
27 | }
28 |
29 | public Triangle(double x, double y, double width, double height) {
30 | super(x, y, width, height);
31 | }
32 |
33 |
34 | @Override
35 | public void draw(Graphics g) {
36 |
37 | int borderThickness = getBorderWidth() == 1 ? 2 : getBorderWidth();
38 | Graphics2D g2 = (Graphics2D) g;
39 | g2.setStroke(new BasicStroke(borderThickness));
40 |
41 | int[] xPoints = new int[] {(int)((this.getX() + this.getWidth()) / 2), (int)(this.getX() + this.getWidth()), (int)this.getX()};
42 | int[] yPoints = new int[] {(int)(this.getY()), (int)(this.getY() + this.getHeight()), (int)(this.getY() + this.getHeight())};
43 |
44 | g2.setColor(getBorderColor());
45 | g2.drawPolygon(xPoints, yPoints, 3);
46 |
47 | // xPoints[1] = (int)(xPoints[1] - borderThickness / 2);
48 | // xPoints[2] = (int)(xPoints[2] + borderThickness / 2);
49 | //
50 | // yPoints[0] = (int)(yPoints[0] + borderThickness / 2);
51 | // yPoints[1] = (int)(yPoints[1] - borderThickness / 2);
52 | // yPoints[2] = (int)(yPoints[2] - borderThickness / 2);
53 |
54 | // xPoints = new int[] {(int)((getWidth()) / 2 + getX()), (int)(getX() + 1), (int)(getX() + getWidth() - 1)};
55 | // yPoints = new int[] {(int)(getY() + 1), (int)(getY() + getHeight() - 1), (int)(getY() + getHeight() - 1)};
56 |
57 | g2.setColor(getInsiderColor());
58 | g.fillPolygon(xPoints, yPoints, 3);
59 |
60 |
61 | }
62 |
63 |
64 | @Override
65 | public double getArea() {
66 | return 0;
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/panels/ShapePanel.java:
--------------------------------------------------------------------------------
1 | package panels;
2 |
3 | import java.awt.Color;
4 | import java.awt.Dimension;
5 |
6 | import javax.swing.ImageIcon;
7 | import javax.swing.JLabel;
8 | import javax.swing.JPanel;
9 | import javax.swing.JSlider;
10 | import javax.swing.SwingConstants;
11 | import javax.swing.event.ChangeEvent;
12 | import javax.swing.event.ChangeListener;
13 | import javax.swing.plaf.DimensionUIResource;
14 |
15 | import main.MainPanel;
16 | import main.MyLabel;
17 |
18 | public class ShapePanel extends JPanel {
19 |
20 | private MyLabel circle_label, rectangle_label, triangle_label, polygon_label;
21 | private JLabel shapes_label, fps_label;
22 | private JSlider fps_slider;
23 | private String fps_text = "FPS : ";
24 |
25 | public ShapePanel() {
26 |
27 | setBackground(Color.WHITE);
28 |
29 | shapes_label = new JLabel("SHAPES") {
30 | @Override
31 | public Dimension getPreferredSize() {
32 | return new Dimension(ShapePanel.this.getWidth(), 50);
33 | }
34 | };
35 | shapes_label.setHorizontalAlignment(JLabel.CENTER);
36 |
37 | this.add(shapes_label);
38 |
39 | circle_label = new MyLabel(new ImageIcon("src\\icons\\circle.png"));
40 | circle_label.setName("circle");
41 | //circle_label.setBounds(13, 50, 124, 124);
42 | this.add(circle_label);
43 |
44 | rectangle_label = new MyLabel(new ImageIcon("src\\icons\\rectangle.png"));
45 | //rectangle_label.setBounds(13, 50, 124, 124);
46 | rectangle_label.setName("rectangle");
47 | this.add(rectangle_label);
48 |
49 | triangle_label = new MyLabel(new ImageIcon("src\\icons\\triangle.png"));
50 | //triangle_label.setBounds(13, 50, 124, 124);
51 | triangle_label.setName("triangle");
52 | this.add(triangle_label);
53 |
54 | polygon_label = new MyLabel(new ImageIcon("src\\icons\\polygon2.png"));
55 | //polygon_label.setBounds(13, 50, 124, 124);
56 | polygon_label.setName("polygon");
57 | this.add(polygon_label);
58 |
59 | JPanel sliderPanel = new JPanel();
60 | sliderPanel.setLayout(null);
61 | sliderPanel.setPreferredSize(new Dimension(150, 200));
62 | sliderPanel.setBackground(getBackground());
63 | this.add(sliderPanel);
64 |
65 | fps_label = new JLabel(fps_text + "24");
66 | fps_label.setBounds(0, 20, 150, 70);
67 | fps_label.setHorizontalAlignment(SwingConstants.CENTER);
68 | fps_label.setVerticalAlignment(SwingConstants.CENTER);
69 | sliderPanel.add(fps_label);
70 |
71 | fps_slider = new JSlider();
72 | fps_slider.setValue(25);
73 | fps_slider.setBackground(this.getBackground());
74 | fps_slider.setPaintLabels(true);
75 | fps_slider.setPaintTicks(true);
76 | fps_slider.setPaintTrack(true);
77 | fps_slider.setMaximum(80);
78 | fps_slider.setMinimum(5);
79 | fps_slider.setMinorTickSpacing(10);
80 | fps_slider.setMajorTickSpacing(20);
81 | fps_slider.setBounds(10, 70, 130, 60);
82 | fps_slider.addChangeListener(new ChangeListener() {
83 | @Override
84 | public void stateChanged(ChangeEvent e) {
85 | fps_label.setText(fps_text + fps_slider.getValue());
86 | MainPanel.FPS = fps_slider.getValue();
87 | }
88 | });
89 | sliderPanel.add(fps_slider);
90 |
91 | }
92 |
93 | public MyLabel getCircle_label() {
94 | return circle_label;
95 | }
96 |
97 | public MyLabel getRectangle_label() {
98 | return rectangle_label;
99 | }
100 |
101 | public MyLabel getTriangle_label() {
102 | return triangle_label;
103 | }
104 |
105 | public MyLabel getPolygon_label() {
106 | return polygon_label;
107 | }
108 |
109 | public JLabel getShapes_label() {
110 | return shapes_label;
111 | }
112 |
113 |
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/panels/ScenePanel.java:
--------------------------------------------------------------------------------
1 | package panels;
2 |
3 | import java.awt.Color;
4 | import java.awt.Component;
5 | import java.awt.Container;
6 | import java.awt.Dimension;
7 | import java.awt.EventQueue;
8 | import java.awt.Graphics;
9 | import java.awt.GridLayout;
10 | import java.awt.event.MouseEvent;
11 | import java.awt.event.MouseListener;
12 | import java.util.ArrayList;
13 | import java.util.TimerTask;
14 |
15 | import javax.swing.JButton;
16 | import javax.swing.JLabel;
17 | import javax.swing.JPanel;
18 | import javax.swing.JScrollPane;
19 | import javax.swing.JTextField;
20 | import javax.swing.JViewport;
21 |
22 | import main.MainPanel;
23 | import main.MyShape;
24 |
25 | public class ScenePanel extends JPanel implements MouseListener{
26 |
27 | private int x;
28 | private int y;
29 | private int width;
30 | private int height;
31 | private ArrayList shapes;
32 | private int currentShape;
33 | Long waitTime;
34 |
35 | public ScenePanel(int x, int y, int width, int height, ArrayList shapes) {
36 | super();
37 | this.x = x;
38 | this.y = y;
39 | this.width = width;
40 | this.height = height;
41 | this.shapes = shapes;
42 |
43 | this.setBackground(new Color(210, 210, 210));
44 | this.setBounds(x, y, width, height);
45 |
46 | this.addMouseListener(this);
47 |
48 | init();
49 |
50 | }
51 |
52 |
53 | public void init() {
54 |
55 | new Thread(new Runnable() {
56 |
57 | @Override
58 | public void run() {
59 |
60 | Long firstTime, lastTime, waitTime;
61 | int fps = MainPanel.FPS;
62 | int i = fps;
63 |
64 | while(i-- > 0) {
65 |
66 | firstTime = System.currentTimeMillis();
67 | for(MyShape shape : getShapes()) {
68 | shape.g(fps);
69 | }
70 |
71 | lastTime = System.currentTimeMillis();
72 |
73 | try {
74 | waitTime = ((1000 / fps) - (lastTime - firstTime));
75 | Thread.sleep(waitTime < 0L ? 0L : waitTime);
76 | } catch (InterruptedException e) {}
77 |
78 | if(fps != MainPanel.FPS)
79 | break;
80 | }
81 |
82 | this.run();
83 |
84 | }
85 | }).start();
86 |
87 | }
88 |
89 |
90 | public void paint(Graphics g) {
91 | super.paint(g);
92 | for(MyShape shape : getShapes()) {
93 | shape.draw(g);
94 | }
95 |
96 |
97 |
98 | getParent().revalidate();
99 | getParent().repaint();
100 |
101 | }
102 |
103 | public void paintComponent(Graphics g) {
104 | super.paintComponent(g);
105 |
106 |
107 | }
108 |
109 |
110 |
111 | public int getCurrentShape() {
112 | if(getShapes().size() < currentShape) {
113 | System.out.println("Index out of bounds getCurrentShape Method");
114 | return getShapes().size();
115 | }
116 | return currentShape;
117 | }
118 |
119 | public void setCurrentShape(int currentShape) {
120 | this.currentShape = currentShape;
121 |
122 | }
123 |
124 |
125 |
126 | public ArrayList getShapes() {
127 | if(shapes == null)
128 | shapes = new ArrayList<>();
129 | return shapes;
130 | }
131 |
132 | public int getX() {
133 | return x;
134 | }
135 | public int getY() {
136 | return y;
137 | }
138 | public int getWidth() {
139 | return width;
140 | }
141 | public int getHeight() {
142 | return height;
143 | }
144 |
145 | @Override
146 | public void mouseClicked(MouseEvent e) {
147 | if(shapes.size() > getCurrentShape()) {
148 | shapes.get(getCurrentShape()).setSelected(false);
149 | }
150 |
151 | for(int i = 0; i < shapes.size(); i++) {
152 | if(getShapes().get(i).intersects(e.getX(), e.getY(), 1, 1)) {
153 | getShapes().get(i).setSelected(true);
154 | this.setCurrentShape(i);
155 | //FeaturesPanel.setCurrentShape(getCurrentShape());
156 | ((MainPanel)getParent()).getFeaturesPanel().setCurrentShape(getCurrentShape());
157 | getParent().revalidate();
158 | getParent().repaint();
159 |
160 | break;
161 | }
162 |
163 | }
164 |
165 | }
166 |
167 | @Override
168 | public void mousePressed(MouseEvent e) {
169 | // TODO Auto-generated method stub
170 |
171 | }
172 |
173 | @Override
174 | public void mouseReleased(MouseEvent e) {
175 | // TODO Auto-generated method stub
176 |
177 | }
178 |
179 | @Override
180 | public void mouseEntered(MouseEvent e) {
181 | // TODO Auto-generated method stub
182 |
183 | }
184 |
185 | @Override
186 | public void mouseExited(MouseEvent e) {
187 | // TODO Auto-generated method stub
188 |
189 | }
190 |
191 |
192 |
193 |
194 |
195 |
196 | }
197 |
--------------------------------------------------------------------------------
/src/main/MyShape.java:
--------------------------------------------------------------------------------
1 | package main;
2 |
3 | import java.awt.BasicStroke;
4 | import java.awt.Color;
5 | import java.awt.Component;
6 | import java.awt.Dimension;
7 | import java.awt.Graphics;
8 | import java.awt.Graphics2D;
9 | import java.awt.Polygon;
10 | import java.awt.Rectangle;
11 | import java.awt.event.MouseEvent;
12 | import java.awt.event.MouseListener;
13 |
14 | public class MyShape extends Rectangle {
15 |
16 | private static final long serialVersionUID = 1L;
17 | private double x;
18 | private double y;
19 | private double width;
20 | private double height;
21 | private Color borderColor;
22 | private int borderWidth;
23 | private Color insiderColor;
24 | private double mass;
25 | private double area;
26 | private double gravity;
27 | private boolean selected;
28 | private double bounce;
29 | private double v = 0;
30 | private double energy;
31 |
32 | public MyShape(double x, double y, double width, double height) {
33 | this(x, y, width, height, 1);
34 | }
35 |
36 | public MyShape(double x, double y, double width, double height, double mass) {
37 | this(x, y, width, height, Color.WHITE, Color.WHITE, mass);
38 |
39 | }
40 |
41 | public MyShape(double x, double y, double width, double height, Color borderColor) {
42 | this(x, y, width, height, borderColor, Color.WHITE);
43 | }
44 |
45 | public MyShape(double x, double y, double width, double height, Color borderColor, Color insiderColor) {
46 | this(x, y, width, height, borderColor, insiderColor, 1);
47 | }
48 |
49 | public MyShape(double x, double y, double width, double height, Color borderColor, Color insiderColor,
50 | double mass) {
51 | super();
52 | this.x = x;
53 | this.y = y;
54 | this.width = this.width < width ? width : this.width;
55 | this.height = this.height < height ? height : this.height;
56 | this.borderColor = borderColor;
57 | this.insiderColor = insiderColor;
58 | this.mass = mass;
59 | this.selected = false;
60 | this.borderWidth = 2;
61 | this.gravity = 0;
62 | this.bounce = 50;
63 | this.energy = (Window.WINDOW_HEIGHT - this.y - this.height);
64 | }
65 |
66 | public void g(double x) {
67 |
68 | v += (this.getGravity() / x);
69 |
70 | if(v < 0) {
71 | this.setY(this.getY() + (v / x));
72 | } else {
73 | if((this.getY() + this.getHeight() + (v / x) < Window.WINDOW_HEIGHT) )
74 | this.setY(this.getY() + (v / x));
75 | else {
76 | this.setY(Window.WINDOW_HEIGHT - this.getHeight());
77 | energy = (bounce * (energy / 100));
78 | v = 0 - ((this.getGravity()) * Math.sqrt((2 * energy) / (this.getGravity())));
79 | }
80 | }
81 | }
82 |
83 | public void draw(Graphics g) {
84 |
85 | int borderThickness = getBorderWidth() == 1 ? 2 : getBorderWidth();
86 |
87 | Graphics2D g2 = (Graphics2D) g;
88 | g2.setStroke(new BasicStroke(borderThickness));
89 |
90 | g2.setColor(getBorderColor());
91 | g2.drawRect((int) getX(), (int) getY(), (int) getWidth(), (int) getHeight());
92 | g2.setColor(getInsiderColor());
93 | g2.fillRect((int) getX() + (int) (borderThickness / 2), (int) getY() + (int) (borderThickness / 2),
94 | (int) getWidth() - (int) (borderThickness), (int) getHeight() - (int) (borderThickness));
95 |
96 | }
97 |
98 | @Override
99 | public boolean intersects(double x, double y, double w, double h) {
100 | if (w <= 0 || h <= 0)
101 | return false;
102 | double x0 = getX();
103 | double y0 = getY();
104 | return (x + w > x0 && y + h > y0 && x < x0 + getWidth() && y < y0 + getHeight());
105 | }
106 |
107 | public int getBorderWidth() {
108 | return borderWidth;
109 | }
110 |
111 | public void setBorderWidth(int borderWidth) {
112 | this.borderWidth = borderWidth;
113 | }
114 |
115 | public double getX() {
116 | return x;
117 | }
118 |
119 | public void setX(double x) {
120 | this.x = x;
121 | }
122 |
123 | public double getY() {
124 | return y;
125 | }
126 |
127 | public void setY(double y) {
128 | this.y = y;
129 | }
130 |
131 | public double getWidth() {
132 | return width;
133 | }
134 |
135 | public void setWidth(double width) {
136 | this.width = width;
137 | }
138 |
139 | public double getHeight() {
140 | return height;
141 | }
142 |
143 | public void setHeight(double height) {
144 | this.height = height;
145 | }
146 |
147 | public boolean getSelected() {
148 | return this.selected;
149 | }
150 |
151 | public void setSelected(boolean selected) {
152 | this.selected = selected;
153 | }
154 |
155 | public Color getBorderColor() {
156 | if (getSelected())
157 | return Color.green;
158 | return borderColor;
159 | }
160 |
161 | public void setBorderColor(Color borderColor) {
162 | this.borderColor = borderColor;
163 | }
164 |
165 | public Color getInsiderColor() {
166 | return insiderColor;
167 | }
168 |
169 | public void setInsiderColor(Color insiderColor) {
170 | this.insiderColor = insiderColor;
171 | }
172 |
173 | public double getMass() {
174 | return mass;
175 | }
176 |
177 | public void setMass(double mass) {
178 | this.mass = mass;
179 | }
180 |
181 | public double getArea() {
182 | return (getWidth() * getHeight());
183 | }
184 |
185 | public double getGravity() {
186 | return gravity;
187 | }
188 |
189 | public void setGravity(double gravity) {
190 | this.gravity = gravity;
191 | }
192 |
193 | public void setArea(double area) {
194 | this.area = area;
195 | }
196 |
197 | public double getBounce() {
198 | return bounce;
199 | }
200 |
201 | public void setBounce(int bounce) {
202 | this.bounce = bounce;
203 | }
204 |
205 |
206 | }
207 |
--------------------------------------------------------------------------------
/src/main/MainPanel.java:
--------------------------------------------------------------------------------
1 | package main;
2 |
3 | import java.awt.Color;
4 | import java.awt.Container;
5 | import java.awt.Dimension;
6 | import java.awt.Graphics;
7 | import java.awt.Image;
8 | import java.awt.Polygon;
9 | import java.awt.event.MouseEvent;
10 | import java.awt.event.MouseListener;
11 | import java.awt.event.MouseMotionListener;
12 | import java.util.ArrayList;
13 | import java.util.concurrent.ArrayBlockingQueue;
14 |
15 | import javax.swing.ImageIcon;
16 | import javax.swing.JLabel;
17 | import javax.swing.JPanel;
18 | import javax.swing.JScrollPane;
19 |
20 | import panels.*;
21 | import shapes.*;
22 |
23 | public class MainPanel extends JPanel implements MouseMotionListener, MouseListener{
24 |
25 | private static final long serialVersionUID = 1L;
26 | public static int FPS = 25;
27 | private ShapePanel shapePanel;
28 | private ScenePanel scenePanel;
29 | private FeaturesPanel featuresPanel;
30 |
31 | int sceneX, sceneY, sceneWidth, sceneHeight;
32 |
33 | Image dragImage;
34 | ArrayList shapes = new ArrayList();
35 |
36 |
37 | int rX, rY, newX, newY;
38 |
39 |
40 | double x = 0, y = 0;
41 |
42 | public MainPanel() {
43 |
44 | setBounds(0, 0, Window.WINDOW_WIDTH, Window.WINDOW_HEIGHT);
45 | this.setBackground(Color.red);
46 | setLayout(null);
47 | addMouseListener(this);
48 | addPanel();
49 |
50 | }
51 |
52 | public void addPanel() {
53 |
54 | shapePanel = new ShapePanel();
55 | shapePanel.setBounds(0, 0, 150, Window.WINDOW_HEIGHT);
56 |
57 | shapePanel.getCircle_label().addMouseListener(this);
58 | shapePanel.getPolygon_label().addMouseListener(this);
59 | shapePanel.getRectangle_label().addMouseListener(this);
60 | shapePanel.getTriangle_label().addMouseListener(this);
61 |
62 | shapePanel.getCircle_label().addMouseMotionListener(this);
63 | shapePanel.getPolygon_label().addMouseMotionListener(this);
64 | shapePanel.getRectangle_label().addMouseMotionListener(this);
65 | shapePanel.getTriangle_label().addMouseMotionListener(this);
66 |
67 | this.add(shapePanel);
68 |
69 |
70 |
71 | featuresPanel = new FeaturesPanel(shapes);
72 | featuresPanel.setBounds(Window.WINDOW_WIDTH - shapePanel.getWidth(), 0, 150, Window.WINDOW_HEIGHT);
73 | this.add(featuresPanel);
74 |
75 | sceneX = shapePanel.getWidth();
76 | sceneY = this.getY();
77 | sceneWidth = Window.WINDOW_WIDTH - (shapePanel.getWidth() + featuresPanel.getWidth());
78 | sceneHeight = this.getHeight();
79 |
80 | scenePanel = new ScenePanel(sceneX, sceneY, sceneWidth, sceneHeight, shapes);
81 | this.add(scenePanel);
82 |
83 | }
84 |
85 | public void paint(Graphics g) {
86 | super.paint(g);
87 | if(dragImage != null)
88 | g.drawImage(dragImage, newX, newY, null);
89 |
90 | //g.drawRect(shapePanel.getWidth() + 2, shapePanel.getY() + 2, Window1.WINDOW_WIDTH - shapePanel.getWidth() - 4, Window1.WINDOW_HEIGHT - 4);
91 | }
92 |
93 |
94 | @Override
95 | public void paintComponent(Graphics g) {
96 | super.paintComponent(g);
97 | // for(MyShape shape : shapes)
98 | // shape.draw(g);
99 |
100 | }
101 |
102 |
103 | @Override
104 | public void mouseDragged(MouseEvent e) {
105 | newX = ((JLabel)e.getSource()).getX() - (rX - e.getX());
106 | newY = ((JLabel)e.getSource()).getY() - (rY - e.getY());
107 |
108 | repaint();
109 | }
110 |
111 |
112 | @Override
113 | public void mouseMoved(MouseEvent e) {}
114 |
115 | @Override
116 | public void mouseClicked(MouseEvent e) {}
117 |
118 | @Override
119 | public void mousePressed(MouseEvent e) {
120 |
121 | rX = e.getX();
122 | rY = e.getY();
123 |
124 | if((e.getSource().getClass().equals(MyLabel.class)))
125 | dragImage = ((ImageIcon)((MyLabel)e.getSource()).getIcon()).getImage();
126 |
127 | }
128 |
129 | @Override
130 | public void mouseReleased(MouseEvent e) {
131 | if(e.getSource().getClass().equals(MyLabel.class)
132 | && e.getX() > scenePanel.getX() && e.getY() > scenePanel.getY() //
133 | && e.getX() < scenePanel.getX() + scenePanel.getWidth() // not enough
134 | && e.getY() < scenePanel.getY() + scenePanel.getHeight() ) { //
135 |
136 | int x = e.getX() - scenePanel.getX();
137 | int y = e.getY() - scenePanel.getY();
138 |
139 |
140 |
141 | switch(((MyLabel)e.getSource()).getName()) {
142 |
143 | // !!!!!! NOTE !!!!!!!
144 | /*accurately detect the relationship between the
145 | dropped point and the held point, and set the x and y position correctly */
146 |
147 | case "circle":
148 | shapes.add(new Circle(x, y, 64, 64));
149 | break;
150 | case "rectangle":
151 | shapes.add(new Rect(x, y, 64, 64));
152 | break;
153 | case "triangle":
154 | shapes.add(new Triangle(x, y, 64, 64));
155 | break;
156 | case "polygon":
157 | shapes.add(new Poly(x, y, 64, 64));
158 | break;
159 | }
160 |
161 | shapes.get(scenePanel.getCurrentShape()).setSelected(false);
162 | scenePanel.setCurrentShape(shapes.size() - 1);
163 | shapes.get(scenePanel.getCurrentShape()).setSelected(true);
164 | featuresPanel.setCurrentShape(scenePanel.getCurrentShape());
165 |
166 | }
167 |
168 | dragImage = null;
169 | revalidate();
170 | repaint();
171 | }
172 |
173 | @Override
174 | public void mouseEntered(MouseEvent e) {
175 | // TODO Auto-generated method stub
176 |
177 | }
178 |
179 | @Override
180 | public void mouseExited(MouseEvent e) {
181 | // TODO Auto-generated method stub
182 |
183 | }
184 |
185 | public ShapePanel getShapePanel() {
186 | return shapePanel;
187 | }
188 |
189 | public ScenePanel getScenePanel() {
190 | return scenePanel;
191 | }
192 |
193 | public FeaturesPanel getFeaturesPanel() {
194 | return featuresPanel;
195 | }
196 |
197 |
198 |
199 |
200 | }
201 |
--------------------------------------------------------------------------------
/src/panels/FeaturesPanel.java:
--------------------------------------------------------------------------------
1 | package panels;
2 |
3 | import main.MyShape;
4 | import java.awt.Color;
5 | import java.awt.Container;
6 | import java.awt.Dimension;
7 | import java.awt.Graphics;
8 | import java.awt.GridLayout;
9 | import java.util.ArrayList;
10 |
11 | import javax.swing.BoxLayout;
12 | import javax.swing.JLabel;
13 | import javax.swing.JPanel;
14 | import javax.swing.JScrollPane;
15 | import javax.swing.JTextField;
16 | import javax.swing.event.CaretEvent;
17 | import javax.swing.event.CaretListener;
18 |
19 | import main.Window;
20 |
21 | public class FeaturesPanel extends JPanel implements CaretListener{
22 |
23 | private ArrayList shapes;
24 | private int currentShape;
25 | private boolean state = false;
26 |
27 | private JTextField x_textField, y_textField, width_textField, height_textField, borderColor_textField;
28 | private JTextField borderWidth_textField, insiderColor_textField, mass_textField, gravity_textField, bounce_textField;
29 |
30 | private JLabel x_label, y_label, width_label, height_label, borderColor_label;
31 | private JLabel borderWidth_label, insiderColor_label, mass_label, gravity_label, bounce_label;
32 |
33 | public FeaturesPanel(ArrayList shapes) {
34 | setBackground(Color.white);
35 | this.shapes = shapes;
36 | addUtils();
37 | }
38 |
39 | public void addUtils() {
40 |
41 |
42 | x_label = new JLabel("X Position") {@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight());}};
43 | x_label.setHorizontalAlignment(JLabel.CENTER);
44 | this.add(x_label);
45 |
46 | x_textField = new JTextField(String.valueOf((int)getCurrentShape().getX()), 10);
47 | x_textField.setHorizontalAlignment(JLabel.CENTER);
48 | this.add(x_textField);
49 |
50 | y_label = new JLabel("Y Position") {@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight() + 3);}};
51 | y_label.setHorizontalAlignment(JLabel.CENTER);
52 | y_label.setVerticalAlignment(JLabel.BOTTOM);
53 | this.add(y_label);
54 |
55 | y_textField = new JTextField(String.valueOf((int)getCurrentShape().getY()), 10);
56 | y_textField.setHorizontalAlignment(JLabel.CENTER);
57 | this.add(y_textField);
58 |
59 | width_label = new JLabel("Shape Width"){@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight() + 3);}};
60 | width_label.setHorizontalAlignment(JLabel.CENTER);
61 | width_label.setVerticalAlignment(JLabel.BOTTOM);
62 | this.add(width_label);
63 |
64 | width_textField = new JTextField(String.valueOf((int)getCurrentShape().getWidth()), 10);
65 | width_textField.setHorizontalAlignment(JLabel.CENTER);
66 | this.add(width_textField);
67 |
68 | height_label = new JLabel("Shape Height"){@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight() + 3);}};
69 | height_label.setHorizontalAlignment(JLabel.CENTER);
70 | height_label.setVerticalAlignment(JLabel.BOTTOM);
71 | this.add(height_label);
72 |
73 | height_textField = new JTextField(String.valueOf((int)getCurrentShape().getHeight()), 10);
74 | height_textField.setHorizontalAlignment(JLabel.CENTER);
75 | this.add(height_textField);
76 |
77 |
78 |
79 | borderWidth_label = new JLabel("Border Width"){@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight() + 3);}};
80 | borderWidth_label.setHorizontalAlignment(JLabel.CENTER);
81 | borderWidth_label.setVerticalAlignment(JLabel.BOTTOM);
82 | this.add(borderWidth_label);
83 |
84 | borderWidth_textField = new JTextField(String.valueOf((int)getCurrentShape().getBorderWidth()), 10);
85 | borderWidth_textField.setHorizontalAlignment(JLabel.CENTER);
86 | this.add(borderWidth_textField);
87 |
88 | insiderColor_label = new JLabel("Insider Color (yellow)"){@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight() + 3);}};
89 | insiderColor_label.setHorizontalAlignment(JLabel.CENTER);
90 | insiderColor_label.setVerticalAlignment(JLabel.BOTTOM);
91 | this.add(insiderColor_label);
92 |
93 | insiderColor_textField = new JTextField("", 10);
94 | insiderColor_textField.setHorizontalAlignment(JLabel.CENTER);
95 | this.add(insiderColor_textField);
96 |
97 | borderColor_label = new JLabel("Border Color (black)"){@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight() + 3);}};
98 | borderColor_label.setHorizontalAlignment(JLabel.CENTER);
99 | borderColor_label.setVerticalAlignment(JLabel.BOTTOM);
100 | this.add(borderColor_label);
101 |
102 | borderColor_textField = new JTextField("", 10);
103 | borderColor_textField.setHorizontalAlignment(JLabel.CENTER);
104 | this.add(borderColor_textField);
105 |
106 | mass_label = new JLabel("Mass"){@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight() + 3);}};
107 | mass_label.setHorizontalAlignment(JLabel.CENTER);
108 | mass_label.setVerticalAlignment(JLabel.BOTTOM);
109 | this.add(mass_label);
110 |
111 | mass_textField = new JTextField(String.valueOf((int)getCurrentShape().getMass()), 10);
112 | mass_textField.setHorizontalAlignment(JLabel.CENTER);
113 | this.add(mass_textField);
114 |
115 | gravity_label = new JLabel("Gravity ( % )"){@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight() + 3);}};
116 | gravity_label.setHorizontalAlignment(JLabel.CENTER);
117 | gravity_label.setVerticalAlignment(JLabel.BOTTOM);
118 | this.add(gravity_label);
119 |
120 | gravity_textField = new JTextField(String.valueOf((int)getCurrentShape().getGravity()), 10);
121 | gravity_textField.setHorizontalAlignment(JLabel.CENTER);
122 | this.add(gravity_textField);
123 |
124 | bounce_label = new JLabel("Bounce ( % )"){@Override public Dimension getPreferredSize() {return new Dimension(FeaturesPanel.this.getWidth(), (int)super.getPreferredSize().getHeight() + 3);}};
125 | bounce_label.setHorizontalAlignment(JLabel.CENTER);
126 | bounce_label.setVerticalAlignment(JLabel.BOTTOM);
127 | this.add(bounce_label);
128 |
129 | bounce_textField = new JTextField("", 10);
130 | bounce_textField.setHorizontalAlignment(JLabel.CENTER);
131 | this.add(bounce_textField);
132 |
133 | x_textField.addCaretListener(this);
134 | gravity_textField.addCaretListener(this);
135 | mass_textField.addCaretListener(this);
136 | borderColor_textField.addCaretListener(this);
137 | insiderColor_textField.addCaretListener(this);
138 | borderWidth_textField.addCaretListener(this);
139 | height_textField.addCaretListener(this);
140 | width_textField.addCaretListener(this);
141 | y_textField.addCaretListener(this);
142 | bounce_textField.addCaretListener(this);
143 |
144 |
145 |
146 | }
147 |
148 | public void loadProperties() {
149 | x_textField.setText(getCurrentShape().getX() + "");
150 | y_textField.setText(getCurrentShape().getY() + "");
151 | width_textField.setText(getCurrentShape().getWidth() + "");
152 | height_textField.setText(getCurrentShape().getHeight() + "");
153 | borderWidth_textField.setText(getCurrentShape().getBorderWidth() + "");
154 | insiderColor_textField.setText("");
155 | borderColor_textField.setText("");
156 | mass_textField.setText(String.valueOf(getCurrentShape().getMass()));
157 | gravity_textField.setText(String.valueOf(getCurrentShape().getGravity()));
158 | bounce_textField.setText(String.valueOf(getCurrentShape().getBounce()));
159 |
160 |
161 | }
162 |
163 |
164 | @Override
165 | public void paint(Graphics g) {
166 | super.paint(g);
167 | }
168 |
169 |
170 | public MyShape getCurrentShape() {
171 | if(getShapes().size() <= currentShape)
172 | return new MyShape(0, 0, 0, 0);
173 | return getShapes().get(currentShape);
174 | }
175 |
176 | public ArrayList getShapes() {
177 | return shapes;
178 | }
179 |
180 | public void setCurrentShape(int i) {
181 | this.currentShape = i;
182 | this.loadProperties();
183 | }
184 |
185 | @Override
186 | public void caretUpdate(CaretEvent e) {
187 |
188 | if(((JTextField)e.getSource()).equals(x_textField)) {
189 |
190 | try {
191 | getCurrentShape().setX(Integer.parseInt(x_textField.getText()));
192 | state = true;
193 | } catch(NumberFormatException nfe) {
194 |
195 | }
196 |
197 |
198 | } else if(((JTextField)e.getSource()).equals(y_textField)) {
199 |
200 | try {
201 | getCurrentShape().setY(Integer.parseInt(y_textField.getText()));
202 | state = true;
203 | } catch(NumberFormatException nfe) {
204 |
205 | }
206 |
207 | } else if(((JTextField)e.getSource()).equals(width_textField)) {
208 |
209 | try {
210 | getCurrentShape().setWidth(Integer.parseInt(width_textField.getText()));
211 | state = true;
212 | } catch(NumberFormatException nfe) {
213 |
214 | }
215 |
216 | } else if(((JTextField)e.getSource()).equals(height_textField)) {
217 |
218 | try {
219 | getCurrentShape().setHeight(Integer.parseInt(height_textField.getText()));
220 | state = true;
221 | } catch(NumberFormatException nfe) {
222 |
223 | }
224 |
225 | } else if(((JTextField)e.getSource()).equals(borderWidth_textField)) {
226 |
227 | try {
228 | getCurrentShape().setBorderWidth(Integer.parseInt(borderWidth_textField.getText()));
229 | state = true;
230 | } catch(NumberFormatException nfe) {
231 |
232 | }
233 |
234 | } else if(((JTextField)e.getSource()).equals(insiderColor_textField)) {
235 | Color color;
236 | try {
237 | color = (Color)Class.forName("java.awt.Color").getField(insiderColor_textField.getText()).get(null);
238 | } catch(Exception exception) {
239 | color = null;
240 | }
241 |
242 | if(color != null) {
243 | getCurrentShape().setInsiderColor(color);
244 | state = true;
245 | }
246 | } else if(((JTextField)e.getSource()).equals(borderColor_textField)) {
247 |
248 | Color color;
249 | try {
250 | color = (Color)Class.forName("java.awt.Color").getField(borderColor_textField.getText()).get(null);
251 | } catch(Exception exception) {
252 | color = null;
253 | }
254 |
255 | if(color != null) {
256 | getCurrentShape().setBorderColor(color);
257 | state = true;
258 | }
259 | } else if(((JTextField)e.getSource()).equals(mass_textField)) {
260 | try {
261 | getCurrentShape().setMass(Double.parseDouble(mass_textField.getText()));
262 | state = true;
263 | } catch(NumberFormatException nfe) {
264 |
265 | }
266 | } else if(((JTextField)e.getSource()).equals(gravity_textField)) {
267 | try {
268 | getCurrentShape().setGravity(Double.parseDouble(gravity_textField.getText()));
269 | state = true;
270 | } catch(NumberFormatException nfe) {
271 |
272 | }
273 | } else if(((JTextField)e.getSource()).equals(bounce_textField)) {
274 |
275 | try {
276 | getCurrentShape().setBounce(Integer.parseInt(bounce_textField.getText()));
277 | state = true;
278 | } catch(NumberFormatException nfe) {
279 |
280 | }
281 |
282 | }
283 |
284 | if(state) {
285 | this.getParent().revalidate();
286 | this.getParent().repaint();
287 | this.revalidate();
288 | this.repaint();
289 | state = false;
290 | //loadProperties();
291 | }
292 |
293 |
294 | }
295 |
296 |
297 | }
298 |
--------------------------------------------------------------------------------