-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLightsOut.java
267 lines (230 loc) · 10.5 KB
/
LightsOut.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/**
* @(#)LightsOut.java
*
*
* @author
* @version 1.00 2017/2/19
*/
//AWT package GUI details
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
//AWT Listener Events
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
//Swing package GUI components
import javax.swing.JButton;
import javax.swing.JFrame;
/**
* An implementation of a JFrame window that simulates the game Lights Out.
* <p>
* The LightsOut class extends a JFrame, thus it itself is a JFrame window.
* We extend the javax.swing.JFrame class so our Lights Out game will have
* all the properties and behaviors of a normal window on the operating system.
* Thus, all we have to do is at to the class what we want to be inside of
* that JFrame window. The parent class takes care of all of the difficult
* operating system window management details for us.
* <p>
* This is one of the most useful purposes of inheritance in programming. Once
* it has been created, we never recreate it again. A good programmer can
* break up their problem into a set of problems that we already have solutions
* for. What is left over that we haven't solved is usually much smaller and
* easier to implementation a solution that works for us for the time being.
*
*/
public class LightsOut extends JFrame {
/** Set width of game window to 70% width of computer screen */
public static final int WIDTH = (int)(Toolkit.getDefaultToolkit().getScreenSize().getWidth() * .6);
/** Set height of game window to 70% height of computer screen */
public static final int HEIGHT = (int)(Toolkit.getDefaultToolkit().getScreenSize().getHeight() * .8);
/** Text color for logo */
public static final Color LOGO = new Color(232, 247, 10); /*** yellow HOOSE COLOR FOR LIGHTS OUT LOGO ***/
/** Shadow color for logo */
public static final Color LOGO_SHADOW = new Color(178, 41, 173); /*** purple CHOOSE COLOR FOR SHADOW BEHIND LOGO ***/
/** Amount of depth the shadow is behind the Logo Text */
public static final int DEPTH = 2; /*** CHOOSE HOW MUCH DEPTH THE SHADOW GIVES TEXT (My implementation was 6) ***/
/** Window title of game */
public static final String TITLE = "Lights Out";
/** Font for text */
public static final Font FONT = new Font("Helvetica", Font.PLAIN, 40); /*** CHOOSE FONT FOR THE LOGO TEXT ***/
/** GameWindow for game containing the grid and control panel **/
private GameWindow gameWindow;
//=================================================================================================================================================================
/**
* Initialize and start LightsOut game window
*/
public static void main(String[] args)
{
/********************************************************
* Initialize and activate the Lights Out JFrame here *
********************************************************/
LightsOut game = new LightsOut();
game.play();
}
//=================================================================================================================================================================
/**
* Creates a default lights out window. Instantiates a new GameWindow
* object which is the panel that holds the different parts of the
* game. The GameWindow will then implement all the necessary components
* the Lights Out game needs to run.
*/
public LightsOut()
{
/********************************************************************
* Set the size of the window, deactivate the resizable option so *
* the window cannot be resized, set the JFrame window to stop the *
* program when the window is closed (look up JFrame default close *
* operation), nullify the layout of the JFrame, then instantiate *
* a the GameWindow with bounds that will cover the entire JFrame *
* and add it to the JFrame *
********************************************************************/
this.setSize(WIDTH, HEIGHT);
this.setResizable(false);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(null);
LightsOut.GameListener listener = this.new GameListener();
gameWindow = new GameWindow(listener);
gameWindow.setSize(WIDTH,HEIGHT);
this.add(gameWindow);
}
/**
* Activates the LightsOut JFrame window by setting
* visibility to true.
*/
public void play()
{
/********************************
* Activate the JFrame window *
********************************/
this.setVisible(true);
}
/**
* Overrides paint method from parent class. Important to note that
* overriding the paint method incorrectly can result in detrimental
* side effects in showing your GUI to the screen. If you must override
* the paint method there are two things you must consider:
* <p>
* <ul>
* <li> 1) If you are using a Layout Manager then you MUST make a call
* to the super class paint method in order to correctly draw
* those components with the corresponding layout. Then, any
* additional details you may draw AFTER said call has completed.
*
* <li> 2) If you have set the layout to <code>null</code> then the order
* in which components are drawn are up to your implementation and
* their locations will be based off of their bounds that are set
* via their setBounds(x, y, w, h) method. If no call to the set
* bounds method, then that component will not have a location in
* the container.
* </ul>
*
* @param g the specified Graphics window
*
*/
@Override public void paint(Graphics g)
{
//Convert Graphics object from OS of computer to 2D Graphics
// Graphics2D inherits (subclass of) Graphics
Graphics2D g2 = (Graphics2D) g;
//Call parent to paint all components added to window.
super.paint(g2);
/* Paint logo after other components painted */
g2.setFont(this.FONT);
int x = (int)(this.WIDTH * .5 - g2.getFontMetrics().stringWidth(this.TITLE) / 2);
int y = (int)(this.HEIGHT * .001 + g2.getFontMetrics().getHeight());
//Draw shadow first
g2.setColor(this.LOGO_SHADOW);
g2.drawString(this.TITLE, x, y + this.DEPTH);
g2.drawString(this.TITLE, x + this.DEPTH, y + this.DEPTH);
g2.drawString(this.TITLE, x + this.DEPTH, y);
//Draw logo over shadow
g2.setColor(this.LOGO);
g2.drawString(this.TITLE, x - 1, y - 1);
}
//=================================================================================================================================================================
// Listener For Game
//=================================================================================================================================================================
/**
* Implements an inner class to the LightsOut game to handle
* MouseEvents by implementing the MouseListener class. The
* MouseListener interface handles receiving mouse events on
* a component (press, release, click, enter, exit). The class
* that is interested in processing a mouse event must implement
* the MouseListener interface.
* <p>
* Most of the time as beginner programmers we want our top level
* class to implement our listener interfaces because they will
* have reference to all parts of the program (panels, buttons,
* text fields, images, etc.) by accessing the getters or those
* objects created inside of it.
* <p>
* Note, for larger programs this is not the best design as many
* different parts of the program will likely listen to for the
* same events. Like in a game with the arrow keys doing one thing
* when you're in the level, and a totally different thing when
* you're in the main menu.
*
*/
private class GameListener implements MouseListener
{
/**
* Invoked when the mouse button has been clicked (pressed
* and released) on a component.
*
* @param e MouseEvent that took place on the component.
* Note, a MouseEvent object has multiple properties
* that are very useful to invoke, a couple of them
* are described below in the comments in which you
* will implement.
*/
public void mouseClicked(MouseEvent e)
{
/************************************************************
* Correctly determine which mouse button threw the event. *
* We only care about the left mouse button (info found in *
* MouseEvent class). If the mouse button was not the left *
* one then go ahead and exit the method now. Otherwise, *
* you need to determine the source of the click. Was it *
* one of the Lights or the reset button. Once the source *
* is found, correctly invoke the method that performs *
* the appropriate task in the GameWindow. *
************************************************************/
if (e.getButton() == MouseEvent.BUTTON1) {
if (e.getSource() instanceof Light ) {
gameWindow.onLeftClick(e);
}
else if (e.getSource() instanceof JButton) {
gameWindow.reset();
}
}
else {
return;
}
}
/********************************************************************
* The following methods are unused methods of the MouseListener *
* interface. However, by "law" we must implement these methods *
* when we enter into the contract of using the MouseListener *
* interface. In our Lights Out game, these buttons don't do *
* anything, thus we will just leave these methods with empty *
* implementations. No different than any other program not using *
* a key that's on the keyboard. *
* *
* NOTE: IF YOU WOULD LIKE TO AFTER YOUR GAME WORKS TO IMPLEMENT *
* THESE TO DO SOMETHING IN YOUR GAME FEEL FREE! FOR EXAMPLE, *
* PERHAPS MOUSING OVER A LIGHT CHANGES IT'S COLOR. *
********************************************************************/
/** Invoked when a mouse button has been pressed down */
public void mousePressed(MouseEvent e) {}
/** Invoked when a mouse button has been let up */
public void mouseReleased(MouseEvent e) {}
/** Invoked when a mouse hovers over a component */
public void mouseEntered(MouseEvent e) {}
/** Invoked when a mouse is moved off of a component */
public void mouseExited(MouseEvent e) {}
}
}