Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epoxy
GitHub Repository: epoxy/proj11
Path: blob/master/SLICK_HOME/src/org/newdawn/slick/AppletGameContainer.java
1456 views
1
package org.newdawn.slick;
2
3
import java.applet.Applet;
4
import java.awt.BorderLayout;
5
import java.awt.Canvas;
6
import java.awt.Color;
7
import java.awt.Font;
8
import java.awt.GridLayout;
9
import java.awt.Label;
10
import java.awt.Panel;
11
import java.awt.TextArea;
12
import java.io.PrintWriter;
13
import java.io.StringWriter;
14
import java.nio.ByteBuffer;
15
16
import org.lwjgl.BufferUtils;
17
import org.lwjgl.LWJGLException;
18
import org.lwjgl.input.Cursor;
19
import org.lwjgl.input.Mouse;
20
import org.lwjgl.opengl.Display;
21
import org.lwjgl.opengl.GL11;
22
import org.lwjgl.opengl.PixelFormat;
23
import org.newdawn.slick.openal.SoundStore;
24
import org.newdawn.slick.opengl.CursorLoader;
25
import org.newdawn.slick.opengl.ImageData;
26
import org.newdawn.slick.opengl.InternalTextureLoader;
27
import org.newdawn.slick.util.Log;
28
29
/**
30
* A game container that displays the game as an applet. Note however that the
31
* actual game container implementation is an internal class which can be
32
* obtained with the getContainer() method - this is due to the Applet being a
33
* class wrap than an interface.
34
*
35
* @author kevin
36
*/
37
public class AppletGameContainer extends Applet {
38
/** The GL Canvas used for this container */
39
protected ContainerPanel canvas;
40
/** The actual container implementation */
41
protected Container container;
42
/** The parent of the display */
43
protected Canvas displayParent;
44
/** The thread that is looping for the game */
45
protected Thread gameThread;
46
/** Alpha background supported */
47
protected boolean alphaSupport = true;
48
49
/**
50
* @see java.applet.Applet#destroy()
51
*/
52
public void destroy() {
53
if (displayParent != null) {
54
remove(displayParent);
55
}
56
super.destroy();
57
58
Log.info("Clear up");
59
}
60
61
/**
62
* Clean up the LWJGL resources
63
*/
64
private void destroyLWJGL() {
65
container.stopApplet();
66
67
try {
68
gameThread.join();
69
} catch (InterruptedException e) {
70
Log.error(e);
71
}
72
}
73
74
/**
75
* @see java.applet.Applet#start()
76
*/
77
public void start() {
78
79
}
80
81
/**
82
* Start a thread to run LWJGL in
83
*/
84
public void startLWJGL() {
85
if (gameThread != null) {
86
return;
87
}
88
89
gameThread = new Thread() {
90
public void run() {
91
try {
92
canvas.start();
93
}
94
catch (Exception e) {
95
e.printStackTrace();
96
if (Display.isCreated()) {
97
Display.destroy();
98
}
99
displayParent.setVisible(false);//removeAll();
100
add(new ConsolePanel(e));
101
validate();
102
}
103
}
104
};
105
106
gameThread.start();
107
}
108
109
/**
110
* @see java.applet.Applet#stop()
111
*/
112
public void stop() {
113
}
114
115
/**
116
* @see java.applet.Applet#init()
117
*/
118
public void init() {
119
removeAll();
120
setLayout(new BorderLayout());
121
setIgnoreRepaint(true);
122
123
try {
124
Game game = (Game) Class.forName(getParameter("game")).newInstance();
125
126
container = new Container(game);
127
canvas = new ContainerPanel(container);
128
displayParent = new Canvas() {
129
public final void addNotify() {
130
super.addNotify();
131
startLWJGL();
132
}
133
public final void removeNotify() {
134
destroyLWJGL();
135
super.removeNotify();
136
}
137
138
};
139
140
displayParent.setSize(getWidth(), getHeight());
141
add(displayParent);
142
displayParent.setFocusable(true);
143
displayParent.requestFocus();
144
displayParent.setIgnoreRepaint(true);
145
setVisible(true);
146
} catch (Exception e) {
147
Log.error(e);
148
throw new RuntimeException("Unable to create game container");
149
}
150
}
151
152
/**
153
* Get the GameContainer providing this applet
154
*
155
* @return The game container providing this applet
156
*/
157
public GameContainer getContainer() {
158
return container;
159
}
160
161
/**
162
* Create a new panel to display the GL context
163
*
164
* @author kevin
165
*/
166
public class ContainerPanel {
167
/** The container being displayed on this canvas */
168
private Container container;
169
170
/**
171
* Create a new panel
172
*
173
* @param container The container we're running
174
*/
175
public ContainerPanel(Container container) {
176
this.container = container;
177
}
178
179
/**
180
* Create the LWJGL display
181
*
182
* @throws Exception Failure to create display
183
*/
184
private void createDisplay() throws Exception {
185
try {
186
// create display with alpha
187
Display.create(new PixelFormat(8,8,0));
188
alphaSupport = true;
189
} catch (Exception e) {
190
// if we couldn't get alpha, let us know
191
alphaSupport = false;
192
Display.destroy();
193
// create display without alpha
194
Display.create();
195
}
196
}
197
198
/**
199
* Start the game container
200
*
201
* @throws Exception Failure to create display
202
*/
203
public void start() throws Exception {
204
Display.setParent(displayParent);
205
Display.setVSyncEnabled(true);
206
207
try {
208
createDisplay();
209
} catch (LWJGLException e) {
210
e.printStackTrace();
211
// failed to create Display, apply workaround (sleep for 1 second) and try again
212
Thread.sleep(1000);
213
createDisplay();
214
}
215
216
initGL();
217
displayParent.requestFocus();
218
container.runloop();
219
}
220
221
/**
222
* Initialise GL state
223
*/
224
protected void initGL() {
225
try {
226
InternalTextureLoader.get().clear();
227
SoundStore.get().clear();
228
229
container.initApplet();
230
} catch (Exception e) {
231
Log.error(e);
232
container.stopApplet();
233
}
234
}
235
}
236
237
/**
238
* A game container to provide the applet context
239
*
240
* @author kevin
241
*/
242
public class Container extends GameContainer {
243
/**
244
* Create a new container wrapped round the game
245
*
246
* @param game The game to be held in this container
247
*/
248
public Container(Game game) {
249
super(game);
250
251
width = AppletGameContainer.this.getWidth();
252
height = AppletGameContainer.this.getHeight();
253
}
254
255
/**
256
* Initiliase based on Applet init
257
*
258
* @throws SlickException Indicates a failure to inialise the basic framework
259
*/
260
public void initApplet() throws SlickException {
261
initSystem();
262
enterOrtho();
263
264
try {
265
getInput().initControllers();
266
} catch (SlickException e) {
267
Log.info("Controllers not available");
268
} catch (Throwable e) {
269
Log.info("Controllers not available");
270
}
271
272
game.init(this);
273
getDelta();
274
}
275
276
/**
277
* Check if the applet is currently running
278
*
279
* @return True if the applet is running
280
*/
281
public boolean isRunning() {
282
return running;
283
}
284
285
/**
286
* Stop the applet play back
287
*/
288
public void stopApplet() {
289
running = false;
290
}
291
292
/**
293
* @see org.newdawn.slick.GameContainer#getScreenHeight()
294
*/
295
public int getScreenHeight() {
296
return 0;
297
}
298
299
/**
300
* @see org.newdawn.slick.GameContainer#getScreenWidth()
301
*/
302
public int getScreenWidth() {
303
return 0;
304
}
305
306
/**
307
* Check if the display created supported alpha in the back buffer
308
*
309
* @return True if the back buffer supported alpha
310
*/
311
public boolean supportsAlphaInBackBuffer() {
312
return alphaSupport;
313
}
314
315
/**
316
* @see org.newdawn.slick.GameContainer#hasFocus()
317
*/
318
public boolean hasFocus() {
319
return true;
320
}
321
322
/**
323
* Returns the Applet Object
324
* @return Applet Object
325
*/
326
public Applet getApplet() {
327
return AppletGameContainer.this;
328
}
329
330
/**
331
* @see org.newdawn.slick.GameContainer#setIcon(java.lang.String)
332
*/
333
public void setIcon(String ref) throws SlickException {
334
// unsupported in an applet
335
}
336
337
/**
338
* @see org.newdawn.slick.GameContainer#setMouseGrabbed(boolean)
339
*/
340
public void setMouseGrabbed(boolean grabbed) {
341
Mouse.setGrabbed(grabbed);
342
}
343
344
/**
345
* @see org.newdawn.slick.GameContainer#isMouseGrabbed()
346
*/
347
public boolean isMouseGrabbed() {
348
return Mouse.isGrabbed();
349
}
350
351
/**
352
* @see org.newdawn.slick.GameContainer#setMouseCursor(java.lang.String,
353
* int, int)
354
*/
355
public void setMouseCursor(String ref, int hotSpotX, int hotSpotY) throws SlickException {
356
try {
357
Cursor cursor = CursorLoader.get().getCursor(ref, hotSpotX, hotSpotY);
358
Mouse.setNativeCursor(cursor);
359
} catch (Exception e) {
360
Log.error("Failed to load and apply cursor.", e);
361
}
362
}
363
364
/**
365
* Get the closest greater power of 2 to the fold number
366
*
367
* @param fold The target number
368
* @return The power of 2
369
*/
370
private int get2Fold(int fold) {
371
int ret = 2;
372
while (ret < fold) {
373
ret *= 2;
374
}
375
return ret;
376
}
377
378
/**
379
* {@inheritDoc}
380
*/
381
public void setMouseCursor(Image image, int hotSpotX, int hotSpotY) throws SlickException {
382
try {
383
Image temp = new Image(get2Fold(image.getWidth()), get2Fold(image.getHeight()));
384
Graphics g = temp.getGraphics();
385
386
ByteBuffer buffer = BufferUtils.createByteBuffer(temp.getWidth() * temp.getHeight() * 4);
387
g.drawImage(image.getFlippedCopy(false, true), 0, 0);
388
g.flush();
389
g.getArea(0,0,temp.getWidth(),temp.getHeight(),buffer);
390
391
Cursor cursor = CursorLoader.get().getCursor(buffer, hotSpotX, hotSpotY,temp.getWidth(),temp.getHeight());
392
Mouse.setNativeCursor(cursor);
393
} catch (Exception e) {
394
Log.error("Failed to load and apply cursor.", e);
395
}
396
}
397
398
/**
399
* @see org.newdawn.slick.GameContainer#setIcons(java.lang.String[])
400
*/
401
public void setIcons(String[] refs) throws SlickException {
402
// unsupported in an applet
403
}
404
405
/**
406
* @see org.newdawn.slick.GameContainer#setMouseCursor(org.newdawn.slick.opengl.ImageData, int, int)
407
*/
408
public void setMouseCursor(ImageData data, int hotSpotX, int hotSpotY) throws SlickException {
409
try {
410
Cursor cursor = CursorLoader.get().getCursor(data, hotSpotX, hotSpotY);
411
Mouse.setNativeCursor(cursor);
412
} catch (Exception e) {
413
Log.error("Failed to load and apply cursor.", e);
414
}
415
}
416
417
/**
418
* @see org.newdawn.slick.GameContainer#setMouseCursor(org.lwjgl.input.Cursor, int, int)
419
*/
420
public void setMouseCursor(Cursor cursor, int hotSpotX, int hotSpotY) throws SlickException {
421
try {
422
Mouse.setNativeCursor(cursor);
423
} catch (Exception e) {
424
Log.error("Failed to load and apply cursor.", e);
425
}
426
}
427
428
/**
429
* @see org.newdawn.slick.GameContainer#setDefaultMouseCursor()
430
*/
431
public void setDefaultMouseCursor() {
432
}
433
434
public boolean isFullscreen() {
435
return Display.isFullscreen();
436
}
437
438
public void setFullscreen(boolean fullscreen) throws SlickException {
439
if (fullscreen == isFullscreen()) {
440
return;
441
}
442
443
try {
444
if (fullscreen) {
445
// get current screen resolution
446
int screenWidth = Display.getDisplayMode().getWidth();
447
int screenHeight = Display.getDisplayMode().getHeight();
448
449
// calculate aspect ratio
450
float gameAspectRatio = (float) width / height;
451
float screenAspectRatio = (float) screenWidth
452
/ screenHeight;
453
454
int newWidth;
455
int newHeight;
456
457
// get new screen resolution to match aspect ratio
458
459
if (gameAspectRatio >= screenAspectRatio) {
460
newWidth = screenWidth;
461
newHeight = (int) (height / ((float) width / screenWidth));
462
} else {
463
newWidth = (int) (width / ((float) height / screenHeight));
464
newHeight = screenHeight;
465
}
466
467
// center new screen
468
int xoffset = (screenWidth - newWidth) / 2;
469
int yoffset = (screenHeight - newHeight) / 2;
470
471
// scale game to match new resolution
472
GL11.glViewport(xoffset, yoffset, newWidth, newHeight);
473
474
enterOrtho();
475
476
// fix input to match new resolution
477
this.getInput().setOffset(
478
-xoffset * (float) width / newWidth,
479
-yoffset * (float) height / newHeight);
480
481
this.getInput().setScale((float) width / newWidth,
482
(float) height / newHeight);
483
484
width = screenWidth;
485
height = screenHeight;
486
Display.setFullscreen(true);
487
} else {
488
// restore input
489
this.getInput().setOffset(0, 0);
490
this.getInput().setScale(1, 1);
491
width = AppletGameContainer.this.getWidth();
492
height = AppletGameContainer.this.getHeight();
493
GL11.glViewport(0, 0, width, height);
494
495
enterOrtho();
496
497
Display.setFullscreen(false);
498
}
499
} catch (LWJGLException e) {
500
Log.error(e);
501
}
502
503
}
504
505
/**
506
* The running game loop
507
*
508
* @throws Exception Indicates a failure within the game's loop rather than the framework
509
*/
510
public void runloop() throws Exception {
511
while (running) {
512
int delta = getDelta();
513
514
updateAndRender(delta);
515
516
updateFPS();
517
Display.update();
518
}
519
520
Display.destroy();
521
}
522
}
523
524
/**
525
* A basic console to display an error message if the applet crashes.
526
* This will prevent the applet from just freezing in the browser
527
* and give the end user an a nice gui where the error message can easily
528
* be viewed and copied.
529
*/
530
public class ConsolePanel extends Panel {
531
/** The area display the console output */
532
TextArea textArea = new TextArea();
533
534
/**
535
* Create a new panel to display the console output
536
*
537
* @param e The exception causing the console to be displayed
538
*/
539
public ConsolePanel(Exception e) {
540
setLayout(new BorderLayout());
541
setBackground(Color.black);
542
setForeground(Color.white);
543
544
Font consoleFont = new Font("Arial", Font.BOLD, 14);
545
546
Label slickLabel = new Label("SLICK CONSOLE", Label.CENTER);
547
slickLabel.setFont(consoleFont);
548
add(slickLabel, BorderLayout.PAGE_START);
549
550
StringWriter sw = new StringWriter();
551
e.printStackTrace(new PrintWriter(sw));
552
553
textArea.setText(sw.toString());
554
textArea.setEditable(false);
555
add(textArea, BorderLayout.CENTER);
556
557
// add a border on both sides of the console
558
add(new Panel(), BorderLayout.LINE_START);
559
add(new Panel(), BorderLayout.LINE_END);
560
561
Panel bottomPanel = new Panel();
562
bottomPanel.setLayout(new GridLayout(0, 1));
563
Label infoLabel1 = new Label("An error occured while running the applet.", Label.CENTER);
564
Label infoLabel2 = new Label("Plese contact support to resolve this issue.", Label.CENTER);
565
infoLabel1.setFont(consoleFont);
566
infoLabel2.setFont(consoleFont);
567
bottomPanel.add(infoLabel1);
568
bottomPanel.add(infoLabel2);
569
add(bottomPanel, BorderLayout.PAGE_END);
570
}
571
}
572
}
573