Commit | Line | Data |
---|---|---|
21c4e167 H |
1 | import static java.lang.Math.*; |
2 | import javax.swing.*; | |
3 | import java.awt.*; | |
4 | ||
5 | import java.awt.event.KeyEvent; | |
6 | import java.awt.event.KeyListener; | |
7 | import java.awt.event.MouseEvent; | |
8 | import java.awt.event.MouseMotionListener; | |
9 | ||
10 | import java.io.*; | |
11 | import java.net.*; | |
12 | ||
13 | /** Class implementing network interface for PongPanel objects */ | |
14 | class PongNetwork implements Runnable { | |
15 | BufferedReader br; | |
16 | BufferedWriter bw; | |
17 | Socket sock; | |
18 | String host = "localhost"; | |
19 | int port = 1033; | |
20 | ||
21 | PongPanel pp = null; | |
22 | ||
23 | /** constructor should be given instance of PongPanel to interface with and hostname to connect to */ | |
24 | PongNetwork(PongPanel pp, String host) { | |
25 | this.pp = pp; | |
26 | this.host = host; | |
27 | Thread t = new Thread(this); | |
28 | t.start(); | |
29 | } | |
30 | ||
31 | /** creates new thread which tries to connect to existing server on desired host and if it's not listening it starts own socket server. */ | |
32 | public void run() { | |
33 | try { | |
34 | if(!this.startClient(port)) this.startServer(port); | |
35 | ||
36 | br = new BufferedReader(new InputStreamReader(sock.getInputStream())); | |
37 | bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream())); | |
38 | ||
39 | if(pp.right == 0) { | |
40 | send("0.5,-5,-7"); | |
41 | send("0.5,-5,-7"); | |
42 | } | |
43 | ||
44 | String s = ""; | |
45 | while (s != null) { | |
46 | s = br.readLine(); | |
47 | if (s == null) continue; | |
48 | System.out.println(s); | |
49 | pp.putBall(s); | |
50 | } | |
51 | sock.close(); | |
52 | System.out.println("Remote host closed connection :-("); | |
53 | System.out.println("Your score was: "+ pp.score + " against oponent's score: " + pp.score_oponent); | |
54 | System.exit(0); | |
55 | } catch(Exception e) { | |
56 | System.out.println("Something's wrong with connection :-("); | |
57 | } | |
58 | } | |
59 | ||
60 | /** start own server */ | |
61 | boolean startServer(int port) { | |
62 | pp.right = 1; | |
63 | System.out.println("Starting server on port "+port+" ..."); | |
64 | try { | |
65 | ServerSocket ss = new ServerSocket(port); | |
66 | sock = ss.accept(); | |
67 | System.out.println("Client connected!"); | |
68 | } catch(Exception e) { | |
69 | e.printStackTrace(); | |
70 | return false; | |
71 | } | |
72 | return true; | |
73 | } | |
74 | ||
75 | /** try to connect to existing server */ | |
76 | boolean startClient(int port) { | |
77 | pp.right = 0; | |
78 | System.out.println("Connecting to server "+host+":"+port+" ..."); | |
79 | try { | |
80 | sock = new Socket(); | |
81 | sock.connect(new InetSocketAddress(host, port), 2000); | |
82 | System.out.println("Connected to server!"); | |
83 | } catch (Exception e) { | |
84 | System.out.println("Connection failed!"); | |
85 | return false; | |
86 | } | |
87 | return true; | |
88 | } | |
89 | ||
90 | /** once connection to another pong instance is estabilished, we can send data using this method */ | |
91 | public void send(String s) { | |
92 | try { | |
93 | bw.write(s+"\n"); // zapíšeme předem připravený požadavek | |
94 | bw.flush(); // odeslání z bufferu | |
95 | } catch(Exception e) { | |
96 | } | |
97 | } | |
98 | ||
99 | } | |
100 | ||
101 | /** Pong Panel is object painted on main pong window (PongFrame) and contains all methods and variables needed to play pong */ | |
102 | class PongPanel extends JPanel implements KeyListener, MouseMotionListener { | |
103 | PongNetwork pn; | |
104 | ||
105 | int right = 1; //right (1) or left (0)? | |
106 | ||
107 | int pad_pos = 50; //0-100; | |
108 | int pad_speed = 10; | |
109 | int pad_thickness = 10; | |
110 | int pad_size = 70; | |
111 | ||
112 | public int score = 0; | |
113 | public int score_oponent = 0; | |
114 | ||
115 | boolean have_ball = false; | |
116 | int ball_pos_x, ball_pos_y; | |
117 | int ball_mov_x, ball_mov_y; | |
118 | int ball_size = 10; | |
119 | ||
120 | /** new round is called when your opponent scored */ | |
121 | public void newRound() { | |
122 | if(!have_ball) return; | |
123 | ball_pos_x = getWidth()/2; | |
124 | ball_pos_y = getHeight()/2; | |
125 | ball_mov_x = 7*(right==0?-1:1); | |
126 | ball_mov_y = 3; | |
127 | } | |
128 | ||
129 | /** Constructor */ | |
130 | public PongPanel(int x, int y, String host) { | |
131 | setSize(x, y); | |
132 | //newRound(); | |
133 | addKeyListener(this); | |
134 | addMouseMotionListener(this); | |
135 | pn = new PongNetwork(this, host); | |
136 | } | |
137 | ||
138 | /** Repaint game window */ | |
139 | public void paint(Graphics g) { | |
140 | //createBufferStrategy(2); //double buffered | |
141 | Graphics2D g2D=(Graphics2D) g; // cast to 2D | |
142 | g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, | |
143 | RenderingHints.VALUE_ANTIALIAS_ON); | |
144 | ||
145 | g.setColor(Color.WHITE); | |
146 | g.setColor(Color.BLACK); | |
147 | g.fillRect(0,0, getWidth(), getHeight()); | |
148 | g.setColor(Color.GREEN); | |
149 | ||
150 | if(have_ball) g.fillOval(ball_pos_x-(ball_size/2), ball_pos_y-(ball_size/2), ball_size, ball_size); // draw ball | |
151 | ||
152 | g.fillRect(right*(getWidth()-pad_thickness), pad_pos, pad_thickness, pad_size); // draw pad | |
153 | g.drawString("PONG! "+score+":"+score_oponent, 20,20); | |
154 | } | |
155 | ||
156 | /** increment score of your oponent */ | |
157 | public void oponentScores() { | |
158 | score_oponent++; | |
159 | pn.send("+gotme :-)"); //HEY! do not comment this you cheater! :-P | |
160 | newRound(); | |
161 | } | |
162 | ||
163 | /** compute next iteration of game and repaint screen */ | |
164 | public boolean tick() { | |
165 | if(have_ball) { | |
166 | ball_pos_x += ball_mov_x; | |
167 | ball_pos_y += ball_mov_y; | |
168 | if(ball_pos_y >= getHeight() || ball_pos_y <= 0) ball_mov_y = -ball_mov_y; //bounce | |
169 | ||
170 | if( | |
171 | ( | |
172 | (right == 1 && ball_pos_x >= (getWidth()-pad_thickness-round(ball_size/2))) || | |
173 | (right == 0 && ball_pos_x <= pad_thickness+round(ball_size/2)) | |
174 | ) && | |
175 | ( | |
176 | ball_pos_y >= pad_pos && | |
177 | ball_pos_y <= pad_pos + pad_size | |
178 | ) | |
179 | ) { | |
180 | ball_mov_x = -ball_mov_x; | |
181 | } | |
182 | ||
183 | else if( | |
184 | (right == 1 && ball_pos_x >= getWidth()) || | |
185 | (right == 0 && ball_pos_x <= 0) | |
186 | ) oponentScores(); | |
187 | ||
188 | else if( | |
189 | (right == 0 && ball_pos_x >= getWidth()) || | |
190 | (right == 1 && ball_pos_x <= 0) | |
191 | ) { | |
192 | //send ball over network | |
193 | pn.send(getBall()); | |
194 | have_ball = false; super.repaint(); | |
195 | //newRound(); | |
196 | return false; | |
197 | } | |
198 | ||
199 | //putBall(getBall()); //haloooz s roundem | |
200 | } | |
201 | ||
202 | super.repaint(); | |
203 | return true; | |
204 | } | |
205 | ||
206 | /** serialize ball (position and speed) to be sent over TCP/IP socket */ | |
207 | public String getBall() { | |
208 | have_ball = false; | |
209 | return( | |
210 | ((float)ball_pos_y / (float)getHeight()) + | |
211 | ","+ball_mov_x + | |
212 | ","+ball_mov_y + | |
213 | ","+right | |
214 | ||
215 | ); | |
216 | ||
217 | } | |
218 | ||
219 | /** deserialize ball received through TCP/IP connection */ | |
220 | public void putBall(String ball) { | |
221 | if(ball.charAt(0) == '+') { | |
222 | score++; | |
223 | return; | |
224 | } | |
225 | have_ball = true; | |
226 | String[] vars = ball.trim().split(","); | |
227 | System.out.println("Parsing: "+vars[0]+" "+vars[1]+" "+vars[2]); | |
228 | ball_pos_x = (right==1)?pad_thickness+ball_size:getWidth()-(pad_thickness+ball_size); | |
229 | ball_pos_y = (int)round(getHeight()*(new Double(vars[0]))); | |
230 | ball_mov_x = new Integer(vars[1]); | |
231 | ball_mov_y = new Integer(vars[2]); | |
232 | System.out.println("Parsed: "+ball_pos_y+" "+ball_mov_x+" "+ball_mov_y); | |
233 | } | |
234 | ||
235 | public void keyPressed(KeyEvent evt) { | |
236 | int keyCode = evt.getKeyCode(); | |
237 | if(keyCode == KeyEvent.VK_UP && pad_pos >= pad_speed) pad_pos -= pad_speed; | |
238 | if(keyCode == KeyEvent.VK_DOWN && pad_pos <= (100-pad_speed)) pad_pos += pad_speed; | |
239 | super.repaint(); | |
240 | } | |
241 | ||
242 | public void keyReleased(KeyEvent evt) { | |
243 | } | |
244 | ||
245 | public void keyTyped(KeyEvent evt) { | |
246 | } | |
247 | public boolean isFocusTraversable() { return true; } | |
248 | ||
249 | public void mouseMoved(MouseEvent e) { | |
250 | pad_pos = e.getY()-(pad_size/2); | |
251 | } | |
252 | public void mouseDragged(MouseEvent e) { | |
253 | } | |
254 | ||
255 | } | |
256 | ||
257 | /** Main window of game */ | |
258 | class PongFrame extends JFrame { | |
259 | PongPanel pp; | |
260 | PongFrame(int x, int y, String host) throws InterruptedException { | |
261 | this.setSize(x,y); | |
262 | this.setTitle("NetPong"); | |
263 | this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
264 | ||
265 | pp=new PongPanel(getWidth(),getHeight(),host); | |
266 | this.getContentPane().add(pp); | |
267 | ||
268 | this.setVisible(true); | |
269 | } | |
270 | ||
271 | /** start game */ | |
272 | public void play() throws InterruptedException { | |
273 | while(true) { | |
274 | pp.tick(); | |
275 | //if(!pp.tick()) Thread.sleep(2*1000); | |
276 | Thread.sleep(1000/24); | |
277 | } | |
278 | } | |
279 | ||
280 | } | |
281 | ||
282 | /** | |
283 | * Implementation of classical "PONG" game modified to pass ball over TCP/IP connection. | |
284 | * You need to run two instances (client + server). | |
285 | * Game takes one optional commandline argument specifiing remote host running the server (localhost is default). | |
286 | * If there's no server running on desired hostname, server is started on local machine on port 1033. | |
287 | * Copylefted by: Harvie 2o1o | |
288 | * @author Thomas Harvie Mudrunka (mudruto1) | |
289 | * @version 1.0 | |
290 | */ | |
291 | ||
292 | public class pong { | |
293 | public static void main(String[] args) throws InterruptedException { | |
294 | PongFrame pf = new PongFrame(640,480,args.length>0?args[0]:"127.0.0.1"); | |
295 | pf.play(); | |
296 | } | |
297 | } |