├── .gitignore
├── CH01
├── .classpath
├── .project
├── src
│ └── javagames
│ │ ├── render
│ │ ├── ActiveRenderingExample.java
│ │ ├── DisplayModeExample.java
│ │ ├── FullScreenRenderingExample.java
│ │ ├── HelloWorldApp.java
│ │ └── RenderThreadExample.java
│ │ └── util
│ │ └── FrameRate.java
└── testing.txt
├── CH02
├── .classpath
├── .project
├── src
│ └── javagames
│ │ ├── input
│ │ ├── KeyboardExample.java
│ │ ├── RelativeMouseExample.java
│ │ ├── SimpleKeyboardExample.java
│ │ └── SimpleMouseExample.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── RelativeMouseInput.java
│ │ ├── SimpleKeyboardInput.java
│ │ └── SimpleMouseInput.java
└── testing.txt
├── CH03
├── .classpath
├── .project
├── src
│ └── javagames
│ │ ├── transform
│ │ ├── MatrixMultiplyExample.java
│ │ ├── PolarCoordinateExample.java
│ │ └── VectorGraphicsExample.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ └── Vector2f.java
└── testing.txt
├── CH04
├── .classpath
├── .project
├── src
│ └── javagames
│ │ ├── timeandspace
│ │ ├── CannonExample.java
│ │ ├── ScreenMappingExample.java
│ │ ├── TimeDeltaExample.java
│ │ └── ViewportRatio.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ └── Vector2f.java
└── testing.txt
├── CH05
├── .classpath
├── .project
├── src
│ └── javagames
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── SimpleFramework.java
│ │ ├── SimpleFrameworkTemplate.java
│ │ ├── Utility.java
│ │ └── Vector2f.java
└── testing.txt
├── CH06
├── .classpath
├── .project
├── src
│ └── javagames
│ │ └── util
│ │ └── Vector2f.java
└── testing.txt
├── CH07
├── .classpath
├── .project
├── src
│ └── javagames
│ │ ├── intersection
│ │ ├── LineLineOverlapExample.java
│ │ ├── OverlapExample.java
│ │ ├── PointInPolygonExample.java
│ │ └── RectRectOverlapExample.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── SimpleFramework.java
│ │ ├── Utility.java
│ │ └── Vector2f.java
└── testing.txt
├── CH08
├── .classpath
├── .project
├── src
│ └── javagames
│ │ ├── prototype
│ │ ├── FlyingShipExample.java
│ │ ├── PolygonWrapper.java
│ │ ├── PrototypeAsteroid.java
│ │ ├── PrototypeAsteroidFactory.java
│ │ ├── PrototypeBullet.java
│ │ ├── PrototypeEditor.java
│ │ ├── PrototypeGame.java
│ │ ├── PrototypeShip.java
│ │ ├── RandomAsteroidExample.java
│ │ └── ScreenWrapExample.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── SimpleFramework.java
│ │ ├── Utility.java
│ │ └── Vector2f.java
└── testing.txt
├── CH09
├── .classpath
├── .project
├── res
│ └── assets
│ │ ├── lib
│ │ ├── javagames
│ │ │ └── filesandres
│ │ │ │ ├── Test1.txt
│ │ │ │ ├── Test2.txt
│ │ │ │ └── Test3.txt
│ │ └── resources.jar
│ │ └── text
│ │ ├── byte-file.bin
│ │ ├── lorem-ipsum.txt
│ │ └── string-file.txt
├── sample.xml
├── src
│ └── javagames
│ │ ├── filesandres
│ │ ├── ClasspathResources.java
│ │ ├── FilesAndDirectories.java
│ │ ├── LoadXMLExample.java
│ │ ├── PrintSystemProperties.java
│ │ ├── PropertyFileExample.java
│ │ ├── ReadingDataFromFiles.java
│ │ ├── ResourceLoaderExample.java
│ │ ├── SaveXMLExample.java
│ │ ├── SavingPropertyFiles.java
│ │ └── WritingDataToFiles.java
│ │ └── util
│ │ ├── ResourceLoader.java
│ │ └── XMLUtility.java
├── testing.properties
└── testing.txt
├── CH10
├── .classpath
├── .project
├── image-creator.bmp
├── image-creator.gif
├── image-creator.jpg
├── image-creator.png
├── src
│ └── javagames
│ │ ├── images
│ │ ├── AlphaCompositeExample.java
│ │ ├── ColorInterpolationExample.java
│ │ ├── FlyingSpritesExample.java
│ │ ├── ImageCreator.java
│ │ ├── ImageSpeedTest.java
│ │ ├── ScaleImageExample.java
│ │ ├── ScaleUpImageExample.java
│ │ └── TransparentImageExample.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── SimpleFramework.java
│ │ ├── Utility.java
│ │ └── Vector2f.java
└── testing.txt
├── CH11
├── .classpath
├── .project
├── src
│ └── javagames
│ │ ├── text
│ │ ├── BoxedTextProblem.java
│ │ ├── BoxedTextSolution.java
│ │ ├── ConsoleOverlayExample.java
│ │ ├── SafeKeyboardInputExample.java
│ │ ├── TextLayoutExample.java
│ │ ├── TextMetricsExample.java
│ │ └── UtilityDrawStringExample.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── SafeKeyboardFramework.java
│ │ ├── SafeKeyboardInput.java
│ │ ├── SimpleFramework.java
│ │ ├── Utility.java
│ │ └── Vector2f.java
└── testing.txt
├── CH12
├── .classpath
├── .project
├── src
│ └── javagames
│ │ ├── threads
│ │ ├── BlockingHardware.java
│ │ ├── BlockingHardwareListener.java
│ │ ├── BlockingQueueExample.java
│ │ ├── CallableTaskExample.java
│ │ ├── FakeHardware.java
│ │ ├── FakeHardwareListener.java
│ │ ├── FileLoadingExample.java
│ │ ├── LoopEvent.java
│ │ ├── MultiThreadEventExample.java
│ │ ├── OneShotEvent.java
│ │ ├── RestartEvent.java
│ │ └── WaitNotifyExample.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── SafeKeyboardFramework.java
│ │ ├── SafeKeyboardInput.java
│ │ ├── SimpleFramework.java
│ │ ├── Utility.java
│ │ └── Vector2f.java
└── testing.txt
├── CH13
├── .classpath
├── .project
├── res
│ └── assets
│ │ └── sound
│ │ ├── AMBIENCE_alien.wav
│ │ ├── ANIMAL_creatureelement_human_05.wav
│ │ ├── BLAST9.WAV
│ │ ├── DRONE9RE.WAV
│ │ ├── ELECTRONIC_computer_beep_09.wav
│ │ ├── EXPLOSION_large_01.wav
│ │ ├── EXPLOSION_large_02.wav
│ │ ├── EXPLOSION_large_03.wav
│ │ ├── EXPLOSION_large_04.wav
│ │ ├── EXPLOSION_large_05.wav
│ │ ├── LASER13.WAV
│ │ ├── WEAPON_scifi_fire_02.wav
│ │ ├── WEAPON_scifi_fire_03.wav
│ │ └── WEATHER_rain_medium_5k.wav
├── src
│ └── javagames
│ │ ├── sound
│ │ ├── AudioDataLine.java
│ │ ├── AudioStream.java
│ │ ├── BlockingAudioListener.java
│ │ ├── BlockingClip.java
│ │ ├── BlockingDataLine.java
│ │ ├── LoopEvent.java
│ │ ├── OneShotEvent.java
│ │ ├── PlayingClipsExample.java
│ │ ├── RestartEvent.java
│ │ ├── SoundControlsExample.java
│ │ ├── SoundEvent.java
│ │ ├── SoundException.java
│ │ └── SoundPlayerExample.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── ResourceLoader.java
│ │ ├── SafeKeyboardFramework.java
│ │ ├── SafeKeyboardInput.java
│ │ ├── SimpleFramework.java
│ │ ├── Utility.java
│ │ └── Vector2f.java
└── testing.txt
├── CH14
├── .classpath
├── .project
├── common.xml
├── custom.xml
├── hello-world.xml
├── lib
│ └── custom-build.jar
└── testing.txt
├── CH15
├── .classpath
├── .project
├── src
│ └── javagames
│ │ ├── collision
│ │ ├── BouncingBallsExample.java
│ │ ├── BouncingPointExample.java
│ │ ├── CircleLineIntersectionExample.java
│ │ ├── LineLineIntersectionExample.java
│ │ ├── LineRectIntersectionExample.java
│ │ └── ReflectionVectorExample.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── SimpleFramework.java
│ │ ├── Utility.java
│ │ └── Vector2f.java
└── testing.txt
├── CH16
├── .classpath
├── .project
├── asdf
├── res
│ └── assets
│ │ └── images
│ │ └── large0.png
├── src
│ └── javagames
│ │ ├── tools
│ │ ├── ExampleFileFilter.java
│ │ ├── ParticleExample.java
│ │ ├── PolygonEditor.java
│ │ ├── SpriteExample.java
│ │ └── TestParticle.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── FullScreenFramework.java
│ │ ├── GameFramework.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── ResourceLoader.java
│ │ ├── SimpleFramework.java
│ │ ├── Sprite.java
│ │ ├── SwingFramework.java
│ │ ├── Utility.java
│ │ ├── Vector2f.java
│ │ ├── WindowFramework.java
│ │ └── XMLUtility.java
└── testing.txt
├── CH17
├── .classpath
├── .project
├── build.xml
├── lib
│ └── complete-game.jar
├── res
│ └── assets
│ │ ├── images
│ │ ├── Ship.png
│ │ ├── ShipGlow.png
│ │ ├── large0.png
│ │ ├── large1.png
│ │ ├── large2.png
│ │ ├── medium0.png
│ │ ├── medium1.png
│ │ ├── medium2.png
│ │ ├── small0.png
│ │ ├── small1.png
│ │ ├── small2.png
│ │ └── space_background_600x600.png
│ │ ├── sound
│ │ ├── AMBIENCE_alien.wav
│ │ ├── DRONE9RE.WAV
│ │ ├── EXPLOSION_large_01.wav
│ │ ├── EXPLOSION_large_02.wav
│ │ ├── EXPLOSION_large_03.wav
│ │ ├── EXPLOSION_large_04.wav
│ │ ├── EXPLOSION_large_05.wav
│ │ └── WEAPON_scifi_fire_02.wav
│ │ └── xml
│ │ ├── common.xml
│ │ ├── new_asteroids.xml
│ │ └── ship.xml
├── src
│ └── javagames
│ │ ├── completegame
│ │ ├── CompleteGame.java
│ │ ├── admin
│ │ │ ├── Acme.java
│ │ │ ├── GameConstants.java
│ │ │ ├── HighScoreMgr.java
│ │ │ ├── QuickLooper.java
│ │ │ └── QuickRestart.java
│ │ ├── object
│ │ │ ├── Asteroid.java
│ │ │ ├── AsteroidExplosion.java
│ │ │ ├── AsteroidFactory.java
│ │ │ ├── Bullet.java
│ │ │ ├── Particle.java
│ │ │ ├── PolygonWrapper.java
│ │ │ ├── Ship.java
│ │ │ ├── ShipExplosion.java
│ │ │ └── ShipFactory.java
│ │ └── state
│ │ │ ├── AttractState.java
│ │ │ ├── EnterHighScoreName.java
│ │ │ ├── GameInformationState.java
│ │ │ ├── GameLoading.java
│ │ │ ├── GameOver.java
│ │ │ ├── GameState.java
│ │ │ ├── HighScore.java
│ │ │ ├── LevelPlaying.java
│ │ │ ├── LevelStarting.java
│ │ │ ├── PressSpaceToPlay.java
│ │ │ ├── Score.java
│ │ │ ├── State.java
│ │ │ └── StateController.java
│ │ ├── sound
│ │ ├── AudioDataLine.java
│ │ ├── AudioStream.java
│ │ ├── BlockingAudioListener.java
│ │ ├── BlockingClip.java
│ │ ├── BlockingDataLine.java
│ │ ├── LoopEvent.java
│ │ ├── SoundEvent.java
│ │ └── SoundException.java
│ │ └── util
│ │ ├── FrameRate.java
│ │ ├── GameFramework.java
│ │ ├── KeyboardInput.java
│ │ ├── Matrix3x3f.java
│ │ ├── RelativeMouseInput.java
│ │ ├── ResourceLoader.java
│ │ ├── Sprite.java
│ │ ├── Utility.java
│ │ ├── Vector2f.java
│ │ ├── WindowFramework.java
│ │ └── XMLUtility.java
└── testing.txt
├── README.md
└── build.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | **/bin
2 | **/.settings
3 | .metadata
4 | **/dist
--------------------------------------------------------------------------------
/CH01/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH01/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH01
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 |
--------------------------------------------------------------------------------
/CH01/src/javagames/render/HelloWorldApp.java:
--------------------------------------------------------------------------------
1 | package javagames.render;
2 |
3 | import java.awt.*;
4 | import javax.swing.*;
5 | import javagames.util.*;
6 |
7 | public class HelloWorldApp extends JFrame {
8 |
9 | private FrameRate frameRate;
10 |
11 | public HelloWorldApp() {
12 | frameRate = new FrameRate();
13 | }
14 |
15 | protected void createAndShowGUI() {
16 | GamePanel gamePanel = new GamePanel();
17 | gamePanel.setBackground( Color.WHITE );
18 | gamePanel.setPreferredSize( new Dimension( 320, 240 ) );
19 | getContentPane().add( gamePanel );
20 | setDefaultCloseOperation( EXIT_ON_CLOSE );
21 | setTitle( "Hello World!" );
22 | pack();
23 | frameRate.initialize();
24 | setVisible( true );
25 | }
26 |
27 | private class GamePanel extends JPanel {
28 | public void paint( Graphics g ) {
29 | super.paint( g );
30 | onPaint( g );
31 | }
32 | }
33 |
34 | protected void onPaint( Graphics g ) {
35 | frameRate.calculate();
36 | g.setColor( Color.BLACK );
37 | g.drawString( frameRate.getFrameRate(), 30, 30 );
38 | repaint();
39 | }
40 |
41 | public static void main( String[] args ) {
42 | final HelloWorldApp app = new HelloWorldApp();
43 | SwingUtilities.invokeLater( new Runnable() {
44 | public void run() {
45 | app.createAndShowGUI();
46 | }
47 | });
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/CH01/src/javagames/render/RenderThreadExample.java:
--------------------------------------------------------------------------------
1 | package javagames.render;
2 |
3 | import java.awt.event.*;
4 | import javax.swing.*;
5 |
6 |
7 | public class RenderThreadExample extends JFrame implements Runnable {
8 |
9 | private volatile boolean running;
10 | private Thread gameThread;
11 |
12 | public RenderThreadExample() {
13 |
14 | }
15 |
16 | protected void createAndShowGUI() {
17 |
18 | setSize( 320, 240 );
19 | setTitle( "Render Thread" );
20 | setVisible( true );
21 |
22 | gameThread = new Thread( this );
23 | gameThread.start();
24 | }
25 |
26 | public void run() {
27 | running = true;
28 | while( running ) {
29 | System.out.println( "Game Loop" );
30 | sleep( 10 );
31 | }
32 | }
33 |
34 | private void sleep( long sleep ) {
35 | try {
36 | Thread.sleep( sleep );
37 | } catch( InterruptedException ex ) { }
38 | }
39 |
40 | protected void onWindowClosing() {
41 | try {
42 | System.out.println( "Stopping Thread..." );
43 | running = false;
44 | gameThread.join();
45 | System.out.println( "Stopped!!!" );
46 | } catch( InterruptedException e ) {
47 | e.printStackTrace();
48 | }
49 | System.exit( 0 );
50 | }
51 |
52 | public static void main( String[] args ) {
53 | final RenderThreadExample app = new RenderThreadExample();
54 | app.addWindowListener( new WindowAdapter() {
55 | public void windowClosing( WindowEvent e ) {
56 | app.onWindowClosing();
57 | }
58 | });
59 | SwingUtilities.invokeLater( new Runnable() {
60 | public void run() {
61 | app.createAndShowGUI();
62 | }
63 | });
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/CH01/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class FrameRate {
4 |
5 | private String frameRate;
6 | private long lastTime;
7 | private long delta;
8 | private int frameCount;
9 |
10 | public void initialize() {
11 | lastTime = System.currentTimeMillis();
12 | frameRate = "FPS 0";
13 | }
14 |
15 | public void calculate() {
16 | long current = System.currentTimeMillis();
17 | delta += current - lastTime;
18 | lastTime = current;
19 | frameCount++;
20 | if( delta > 1000 ) {
21 | delta -= 1000;
22 | frameRate = String.format( "FPS %s", frameCount );
23 | frameCount = 0;
24 | }
25 | }
26 |
27 | public String getFrameRate() {
28 | return frameRate;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/CH01/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH02/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH02/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH02
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 |
--------------------------------------------------------------------------------
/CH02/src/javagames/input/KeyboardExample.java:
--------------------------------------------------------------------------------
1 | package javagames.input;
2 |
3 | import java.awt.event.*;
4 | import javax.swing.*;
5 | import javagames.util.*;
6 |
7 |
8 | public class KeyboardExample extends JFrame implements Runnable {
9 |
10 | private volatile boolean running;
11 | private Thread gameThread;
12 | private KeyboardInput keys;
13 |
14 | public KeyboardExample() {
15 | keys = new KeyboardInput();
16 | }
17 |
18 | protected void createAndShowGUI() {
19 |
20 | setTitle( "Keyboard Input" );
21 | setSize( 320, 240 );
22 | addKeyListener( keys );
23 | setVisible( true );
24 |
25 | gameThread = new Thread( this );
26 | gameThread.start();
27 | }
28 |
29 | public void run() {
30 | running = true;
31 | while( running ) {
32 | gameLoop();
33 | }
34 | }
35 |
36 | public void gameLoop() {
37 | keys.poll();
38 | if( keys.keyDownOnce( KeyEvent.VK_SPACE ) ) {
39 | System.out.println( "VK_SPACE" );
40 | }
41 | if( keys.keyDown( KeyEvent.VK_UP ) ) {
42 | System.out.println( "VK_UP" );
43 | }
44 | if( keys.keyDown( KeyEvent.VK_DOWN ) ) {
45 | System.out.println( "VK_DOWN" );
46 | }
47 | if( keys.keyDown( KeyEvent.VK_LEFT ) ) {
48 | System.out.println( "VK_LEFT" );
49 | }
50 | if( keys.keyDown( KeyEvent.VK_RIGHT ) ) {
51 | System.out.println( "VK_RIGHT" );
52 | }
53 | try {
54 | Thread.sleep( 10 );
55 | } catch( InterruptedException ex ) { }
56 | }
57 |
58 | protected void onWindowClosing() {
59 | try {
60 | running = false;
61 | gameThread.join();
62 | } catch( InterruptedException e ) {
63 | e.printStackTrace();
64 | }
65 | System.exit( 0 );
66 | }
67 |
68 | public static void main( String[] args ) {
69 | final KeyboardExample app = new KeyboardExample();
70 | app.addWindowListener( new WindowAdapter() {
71 | public void windowClosing( WindowEvent e ) {
72 | app.onWindowClosing();
73 | }
74 | });
75 | SwingUtilities.invokeLater( new Runnable() {
76 | public void run() {
77 | app.createAndShowGUI();
78 | }
79 | });
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/CH02/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class FrameRate {
4 |
5 | private String frameRate;
6 | private long lastTime;
7 | private long delta;
8 | private int frameCount;
9 |
10 | public void initialize() {
11 | lastTime = System.currentTimeMillis();
12 | frameRate = "FPS 0";
13 | }
14 |
15 | public void calculate() {
16 | long current = System.currentTimeMillis();
17 | delta += current - lastTime;
18 | lastTime = current;
19 | frameCount++;
20 | if( delta > 1000 ) {
21 | delta -= 1000;
22 | frameRate = String.format( "FPS %s", frameCount );
23 | frameCount = 0;
24 | }
25 | }
26 |
27 | public String getFrameRate() {
28 | return frameRate;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/CH02/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.event.*;
4 |
5 | public class KeyboardInput implements KeyListener {
6 |
7 | private boolean[] keys;
8 | private int[] polled;
9 |
10 | public KeyboardInput() {
11 | keys = new boolean[ 256 ];
12 | polled = new int[ 256 ];
13 | }
14 |
15 | public boolean keyDown( int keyCode ) {
16 | return polled[ keyCode ] > 0;
17 | }
18 |
19 | public boolean keyDownOnce( int keyCode ) {
20 | return polled[ keyCode ] == 1;
21 | }
22 |
23 | public synchronized void poll() {
24 | for( int i = 0; i < keys.length; ++i ) {
25 | if( keys[i] ) {
26 | polled[i]++;
27 | } else {
28 | polled[i] = 0;
29 | }
30 | }
31 | }
32 |
33 | public synchronized void keyPressed( KeyEvent e ) {
34 | int keyCode = e.getKeyCode();
35 | if( keyCode >= 0 && keyCode < keys.length ) {
36 | keys[ keyCode ] = true;
37 | }
38 | }
39 |
40 | public synchronized void keyReleased( KeyEvent e ) {
41 | int keyCode = e.getKeyCode();
42 | if( keyCode >= 0 && keyCode < keys.length ) {
43 | keys[ keyCode ] = false;
44 | }
45 | }
46 |
47 | public void keyTyped( KeyEvent e ) {
48 | // Not needed
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/CH02/src/javagames/util/SimpleKeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.event.*;
4 |
5 | public class SimpleKeyboardInput implements KeyListener {
6 |
7 | private boolean[] keys;
8 |
9 | public SimpleKeyboardInput() {
10 | keys = new boolean[ 256 ];
11 | }
12 |
13 | public synchronized boolean keyDown( int keyCode ) {
14 | return keys[ keyCode ];
15 | }
16 |
17 | public synchronized void keyPressed( KeyEvent e ) {
18 | int keyCode = e.getKeyCode();
19 | if( keyCode >= 0 && keyCode < keys.length ) {
20 | keys[ keyCode ] = true;
21 | }
22 | }
23 |
24 | public synchronized void keyReleased( KeyEvent e ) {
25 | int keyCode = e.getKeyCode();
26 | if( keyCode >= 0 && keyCode < keys.length ) {
27 | keys[ keyCode ] = false;
28 | }
29 | }
30 |
31 | public void keyTyped( KeyEvent e ) {
32 | // Not needed
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/CH02/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 | Notes
17 | -----
18 | 14JAN2015 - Win7 - problem with alt key on relative mouse. Pressing the Alt key activates the upper-left window menu,
19 | This causes strange problems with the mouse. Simple to add a list of key events to consume. You could even set a boolean
20 | to toggle exclusion, and only eclude the meta keys in relative mode. Exercise for reader: e.consume()
--------------------------------------------------------------------------------
/CH03/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH03/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH03
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 |
--------------------------------------------------------------------------------
/CH03/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class FrameRate {
4 |
5 | private String frameRate;
6 | private long lastTime;
7 | private long delta;
8 | private int frameCount;
9 |
10 | public void initialize() {
11 | lastTime = System.currentTimeMillis();
12 | frameRate = "FPS 0";
13 | }
14 |
15 | public void calculate() {
16 | long current = System.currentTimeMillis();
17 | delta += current - lastTime;
18 | lastTime = current;
19 | frameCount++;
20 | if( delta > 1000 ) {
21 | delta -= 1000;
22 | frameRate = String.format( "FPS %s", frameCount );
23 | frameCount = 0;
24 | }
25 | }
26 |
27 | public String getFrameRate() {
28 | return frameRate;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/CH03/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.event.*;
4 |
5 | public class KeyboardInput implements KeyListener {
6 |
7 | private boolean[] keys;
8 | private int[] polled;
9 |
10 | public KeyboardInput() {
11 | keys = new boolean[ 256 ];
12 | polled = new int[ 256 ];
13 | }
14 |
15 | public boolean keyDown( int keyCode ) {
16 | return polled[ keyCode ] > 0;
17 | }
18 |
19 | public boolean keyDownOnce( int keyCode ) {
20 | return polled[ keyCode ] == 1;
21 | }
22 |
23 | public synchronized void poll() {
24 | for( int i = 0; i < keys.length; ++i ) {
25 | if( keys[i] ) {
26 | polled[i]++;
27 | } else {
28 | polled[i] = 0;
29 | }
30 | }
31 | }
32 |
33 | public synchronized void keyPressed( KeyEvent e ) {
34 | int keyCode = e.getKeyCode();
35 | if( keyCode >= 0 && keyCode < keys.length ) {
36 | keys[ keyCode ] = true;
37 | }
38 | }
39 |
40 | public synchronized void keyReleased( KeyEvent e ) {
41 | int keyCode = e.getKeyCode();
42 | if( keyCode >= 0 && keyCode < keys.length ) {
43 | keys[ keyCode ] = false;
44 | }
45 | }
46 |
47 | public void keyTyped( KeyEvent e ) {
48 | // Not needed
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/CH03/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 | public float x;
5 | public float y;
6 | public float w;
7 |
8 | public Vector2f() {
9 | this.x = 0.0f;
10 | this.y = 0.0f;
11 | this.w = 1.0f; // !?!
12 | }
13 |
14 | public Vector2f(Vector2f v) {
15 | this.x = v.x;
16 | this.y = v.y;
17 | this.w = v.w; // !?!
18 | }
19 |
20 | public Vector2f(float x, float y) {
21 | this.x = x;
22 | this.y = y;
23 | this.w = 1.0f; // !?!
24 | }
25 |
26 | public Vector2f(float x, float y, float w) {
27 | this.x = x;
28 | this.y = y;
29 | this.w = w; // !?!
30 | }
31 |
32 | public void translate(float tx, float ty) {
33 | x += tx;
34 | y += ty;
35 | }
36 |
37 | public void scale(float sx, float sy) {
38 | x *= sx;
39 | y *= sy;
40 | }
41 |
42 | public void rotate(float rad) {
43 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
44 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
45 | x = tmp;
46 | }
47 |
48 | public void shear(float sx, float sy) {
49 | float tmp = x + sx * y;
50 | y = y + sy * x;
51 | x = tmp;
52 | }
53 | }
--------------------------------------------------------------------------------
/CH03/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH04/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH04/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH04
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 |
--------------------------------------------------------------------------------
/CH04/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH04/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH04/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 | public float x;
5 | public float y;
6 | public float w;
7 |
8 | public Vector2f() {
9 | this.x = 0.0f;
10 | this.y = 0.0f;
11 | this.w = 1.0f; // !?!
12 | }
13 |
14 | public Vector2f(Vector2f v) {
15 | this.x = v.x;
16 | this.y = v.y;
17 | this.w = v.w; // !?!
18 | }
19 |
20 | public Vector2f(float x, float y) {
21 | this.x = x;
22 | this.y = y;
23 | this.w = 1.0f; // !?!
24 | }
25 |
26 | public Vector2f(float x, float y, float w) {
27 | this.x = x;
28 | this.y = y;
29 | this.w = w; // !?!
30 | }
31 |
32 | public void translate(float tx, float ty) {
33 | x += tx;
34 | y += ty;
35 | }
36 |
37 | public void scale(float sx, float sy) {
38 | x *= sx;
39 | y *= sy;
40 | }
41 |
42 | public void rotate(float rad) {
43 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
44 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
45 | x = tmp;
46 | }
47 |
48 | public void shear(float sx, float sy) {
49 | float tmp = x + sx * y;
50 | y = y + sy * x;
51 | x = tmp;
52 | }
53 | }
--------------------------------------------------------------------------------
/CH04/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH05/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH05/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH05
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 |
--------------------------------------------------------------------------------
/CH05/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH05/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH05/src/javagames/util/SimpleFrameworkTemplate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.Color;
4 | import java.awt.Font;
5 | import java.awt.Graphics;
6 | import javagames.util.SimpleFramework;
7 |
8 | public class SimpleFrameworkTemplate extends SimpleFramework {
9 |
10 | public SimpleFrameworkTemplate() {
11 | appBackground = Color.WHITE;
12 | appBorder = Color.LIGHT_GRAY;
13 | appFont = new Font("Courier New", Font.PLAIN, 14);
14 | appBorderScale = 0.9f;
15 | appFPSColor = Color.BLACK;
16 | appWidth = 640;
17 | appHeight = 640;
18 | appMaintainRatio = true;
19 | appSleep = 10L;
20 | appTitle = "FramworkTemplate";
21 | appWorldWidth = 2.0f;
22 | appWorldHeight = 2.0f;
23 | }
24 |
25 | @Override
26 | protected void initialize() {
27 | super.initialize();
28 | }
29 |
30 | @Override
31 | protected void processInput(float delta) {
32 | super.processInput(delta);
33 | }
34 |
35 | @Override
36 | protected void updateObjects(float delta) {
37 | super.updateObjects(delta);
38 | }
39 |
40 | @Override
41 | protected void render(Graphics g) {
42 | super.render(g);
43 | }
44 |
45 | @Override
46 | protected void terminate() {
47 | super.terminate();
48 | }
49 |
50 | public static void main(String[] args) {
51 | launchApp(new SimpleFrameworkTemplate());
52 | }
53 | }
--------------------------------------------------------------------------------
/CH05/src/javagames/util/Utility.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Utility {
4 |
5 | public static Matrix3x3f createViewport(
6 | float worldWidth, float worldHeight,
7 | float screenWidth, float screenHeight ) {
8 | float sx = (screenWidth - 1) / worldWidth;
9 | float sy = (screenHeight - 1) / worldHeight;
10 | float tx = (screenWidth - 1) / 2.0f;
11 | float ty = (screenHeight - 1) / 2.0f;
12 | Matrix3x3f viewport = Matrix3x3f.scale(sx, -sy);
13 | viewport = viewport.mul(Matrix3x3f.translate(tx, ty));
14 | return viewport;
15 | }
16 |
17 | public static Matrix3x3f createReverseViewport(
18 | float worldWidth, float worldHeight,
19 | float screenWidth, float screenHeight ) {
20 | float sx = worldWidth / (screenWidth - 1);
21 | float sy = worldHeight / (screenHeight - 1);
22 | float tx = (screenWidth - 1) / 2.0f;
23 | float ty = (screenHeight - 1) / 2.0f;
24 | Matrix3x3f viewport = Matrix3x3f.translate(-tx, -ty);
25 | viewport = viewport.mul(Matrix3x3f.scale(sx, -sy));
26 | return viewport;
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/CH05/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 | public float x;
5 | public float y;
6 | public float w;
7 |
8 | public Vector2f() {
9 | this.x = 0.0f;
10 | this.y = 0.0f;
11 | this.w = 1.0f; // !?!
12 | }
13 |
14 | public Vector2f(Vector2f v) {
15 | this.x = v.x;
16 | this.y = v.y;
17 | this.w = v.w; // !?!
18 | }
19 |
20 | public Vector2f(float x, float y) {
21 | this.x = x;
22 | this.y = y;
23 | this.w = 1.0f; // !?!
24 | }
25 |
26 | public Vector2f(float x, float y, float w) {
27 | this.x = x;
28 | this.y = y;
29 | this.w = w; // !?!
30 | }
31 |
32 | public void translate(float tx, float ty) {
33 | x += tx;
34 | y += ty;
35 | }
36 |
37 | public void scale(float sx, float sy) {
38 | x *= sx;
39 | y *= sy;
40 | }
41 |
42 | public void rotate(float rad) {
43 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
44 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
45 | x = tmp;
46 | }
47 |
48 | public void shear(float sx, float sy) {
49 | float tmp = x + sx * y;
50 | y = y + sy * x;
51 | x = tmp;
52 | }
53 | }
--------------------------------------------------------------------------------
/CH05/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH06/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH06/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH06
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 |
--------------------------------------------------------------------------------
/CH06/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH06/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH07/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH07/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH07
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 |
--------------------------------------------------------------------------------
/CH07/src/javagames/intersection/LineLineOverlapExample.java:
--------------------------------------------------------------------------------
1 | package javagames.intersection;
2 |
3 | import java.awt.*;
4 | import java.awt.event.MouseEvent;
5 | import javagames.util.*;
6 |
7 | public class LineLineOverlapExample extends SimpleFramework {
8 |
9 | private Vector2f P, Q;
10 | private Vector2f start, end;
11 | boolean overlap = false;
12 |
13 | public LineLineOverlapExample() {
14 | appWidth = 640;
15 | appHeight = 640;
16 | appSleep = 10L;
17 | appTitle = "Line Line Overlap";
18 | appBackground = Color.WHITE;
19 | appFPSColor = Color.BLACK;
20 | }
21 |
22 | @Override
23 | protected void initialize() {
24 | super.initialize();
25 | P = new Vector2f(-0.6f, 0.4f);
26 | Q = new Vector2f(0.6f, -0.4f);
27 | start = new Vector2f(0.8f, 0.8f);
28 | end = new Vector2f();
29 | }
30 |
31 | @Override
32 | protected void processInput(float delta) {
33 | super.processInput(delta);
34 | end = getWorldMousePosition();
35 | if (mouse.buttonDownOnce(MouseEvent.BUTTON1)) {
36 | start = new Vector2f(end);
37 | }
38 | }
39 |
40 | @Override
41 | protected void updateObjects(float delta) {
42 | super.updateObjects(delta);
43 | overlap = lineLineOverlap(P, Q, start, end);
44 | }
45 |
46 | private boolean lineLineOverlap(Vector2f A, Vector2f B, Vector2f P,
47 | Vector2f Q) {
48 | Vector2f C0 = A.add(B).div(2.0f);
49 | Vector2f C1 = P.add(Q).div(2.0f);
50 | Vector2f C = C0.sub(C1);
51 | Vector2f r0 = A.sub(C0);
52 | Vector2f r1 = P.sub(C1);
53 | Vector2f N0 = r0.perp().norm();
54 | Vector2f N1 = r1.perp().norm();
55 | float abs1 = Math.abs(N0.dot(C));
56 | float abs2 = Math.abs(N0.dot(r1));
57 | if (abs1 > abs2)
58 | return false;
59 | abs1 = Math.abs(N1.dot(C));
60 | abs2 = Math.abs(N1.dot(r0));
61 | if (abs1 > abs2)
62 | return false;
63 | return true;
64 | }
65 |
66 | @Override
67 | protected void render(Graphics g) {
68 | super.render(g);
69 | g.drawString("Overlap: " + overlap, 20, 35);
70 | g.drawString("Left Click for new line", 20, 50);
71 | g.setColor(overlap ? Color.BLUE : Color.BLACK);
72 | Matrix3x3f view = getViewportTransform();
73 | Vector2f v0 = view.mul(P);
74 | Vector2f v1 = view.mul(Q);
75 | g.drawLine((int) v0.x, (int) v0.y, (int) v1.x, (int) v1.y);
76 | v0 = view.mul(start);
77 | v1 = view.mul(end);
78 | g.drawLine((int) v0.x, (int) v0.y, (int) v1.x, (int) v1.y);
79 | }
80 |
81 | public static void main(String[] args) {
82 | launchApp(new LineLineOverlapExample());
83 | }
84 | }
--------------------------------------------------------------------------------
/CH07/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH07/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH07/src/javagames/util/Utility.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.Graphics;
4 | import java.util.List;
5 |
6 | public class Utility {
7 |
8 | public static Matrix3x3f createViewport(
9 | float worldWidth, float worldHeight,
10 | float screenWidth, float screenHeight ) {
11 | float sx = (screenWidth - 1) / worldWidth;
12 | float sy = (screenHeight - 1) / worldHeight;
13 | float tx = (screenWidth - 1) / 2.0f;
14 | float ty = (screenHeight - 1) / 2.0f;
15 | Matrix3x3f viewport = Matrix3x3f.scale(sx, -sy);
16 | viewport = viewport.mul(Matrix3x3f.translate(tx, ty));
17 | return viewport;
18 | }
19 |
20 | public static Matrix3x3f createReverseViewport(
21 | float worldWidth, float worldHeight,
22 | float screenWidth, float screenHeight ) {
23 | float sx = worldWidth / (screenWidth - 1);
24 | float sy = worldHeight / (screenHeight - 1);
25 | float tx = (screenWidth - 1) / 2.0f;
26 | float ty = (screenHeight - 1) / 2.0f;
27 | Matrix3x3f viewport = Matrix3x3f.translate(-tx, -ty);
28 | viewport = viewport.mul(Matrix3x3f.scale(sx, -sy));
29 | return viewport;
30 | }
31 |
32 | public static void drawPolygon(Graphics g, Vector2f[] polygon) {
33 | Vector2f P;
34 | Vector2f S = polygon[polygon.length - 1];
35 | for (int i = 0; i < polygon.length; ++i) {
36 | P = polygon[i];
37 | g.drawLine((int) S.x, (int) S.y, (int) P.x, (int) P.y);
38 | S = P;
39 | }
40 | }
41 |
42 | public static void drawPolygon(Graphics g, List polygon) {
43 | Vector2f S = polygon.get(polygon.size() - 1);
44 | for (Vector2f P : polygon) {
45 | g.drawLine((int) S.x, (int) S.y, (int) P.x, (int) P.y);
46 | S = P;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/CH07/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH07/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH08/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH08/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH08
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 |
--------------------------------------------------------------------------------
/CH08/src/javagames/prototype/FlyingShipExample.java:
--------------------------------------------------------------------------------
1 | package javagames.prototype;
2 |
3 | import java.awt.*;
4 | import java.awt.event.KeyEvent;
5 | import java.util.ArrayList;
6 | import javagames.util.*;
7 |
8 | public class FlyingShipExample extends SimpleFramework {
9 |
10 | private PrototypeShip ship;
11 | private PolygonWrapper wrapper;
12 | private ArrayList bullets;
13 |
14 | public FlyingShipExample() {
15 | appBorderScale = 0.9f;
16 | appWidth = 640;
17 | appHeight = 640;
18 | appMaintainRatio = true;
19 | appSleep = 1L;
20 | appTitle = "Flying Ship Example";
21 | }
22 |
23 | @Override
24 | protected void initialize() {
25 | super.initialize();
26 | bullets = new ArrayList();
27 | wrapper = new PolygonWrapper(appWorldWidth, appWorldHeight);
28 | ship = new PrototypeShip(wrapper);
29 | }
30 |
31 | @Override
32 | protected void processInput(float delta) {
33 | super.processInput(delta);
34 | if (keyboard.keyDown(KeyEvent.VK_LEFT)) {
35 | ship.rotateLeft(delta);
36 | }
37 | if (keyboard.keyDown(KeyEvent.VK_RIGHT)) {
38 | ship.rotateRight(delta);
39 | }
40 | if (keyboard.keyDownOnce(KeyEvent.VK_SPACE)) {
41 | bullets.add(ship.launchBullet());
42 | }
43 | ship.setThrusting(keyboard.keyDown(KeyEvent.VK_UP));
44 | }
45 |
46 | @Override
47 | protected void updateObjects(float delta) {
48 | super.updateObjects(delta);
49 | ship.update(delta);
50 | ArrayList copy = new ArrayList(
51 | bullets);
52 | for (PrototypeBullet bullet : copy) {
53 | bullet.update(delta);
54 | if (wrapper.hasLeftWorld(bullet.getPosition())) {
55 | bullets.remove(bullet);
56 | }
57 | }
58 | }
59 |
60 | @Override
61 | protected void render(Graphics g) {
62 | super.render(g);
63 | g.drawString("Rotate: Left/Right Arrow", 20, 35);
64 | g.drawString("Thrust: Up Arrow", 20, 50);
65 | g.drawString("Fire: Space Bar", 20, 65);
66 | Matrix3x3f view = getViewportTransform();
67 | ship.draw((Graphics2D) g, view);
68 | for (PrototypeBullet b : bullets) {
69 | b.draw((Graphics2D) g, view);
70 | }
71 | }
72 |
73 | public static void main(String[] args) {
74 | launchApp(new FlyingShipExample());
75 | }
76 | }
--------------------------------------------------------------------------------
/CH08/src/javagames/prototype/PrototypeBullet.java:
--------------------------------------------------------------------------------
1 | package javagames.prototype;
2 |
3 | import java.awt.*;
4 | import javagames.util.*;
5 |
6 | public class PrototypeBullet {
7 |
8 | private Vector2f velocity;
9 | private Vector2f position;
10 | private Color color;
11 | private float radius;
12 |
13 | public PrototypeBullet(Vector2f position, float angle) {
14 | this.position = position;
15 | velocity = Vector2f.polar(angle, 1.0f);
16 | radius = 0.006f;
17 | color = Color.GREEN;
18 | }
19 |
20 | public Vector2f getPosition() {
21 | return position;
22 | }
23 |
24 | public void draw(Graphics2D g, Matrix3x3f view) {
25 | g.setColor(color);
26 | Vector2f topLeft = new Vector2f(position.x - radius, position.y
27 | + radius);
28 | topLeft = view.mul(topLeft);
29 | Vector2f bottomRight = new Vector2f(position.x + radius, position.y
30 | - radius);
31 | bottomRight = view.mul(bottomRight);
32 | int circleX = (int) topLeft.x;
33 | int circleY = (int) topLeft.y;
34 | int circleWidth = (int) (bottomRight.x - topLeft.x);
35 | int circleHeight = (int) (bottomRight.y - topLeft.y);
36 | g.fillOval(circleX, circleY, circleWidth, circleHeight);
37 | }
38 |
39 | public void update(float time) {
40 | position = position.add(velocity.mul(time));
41 | }
42 | }
--------------------------------------------------------------------------------
/CH08/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH08/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH08/src/javagames/util/Utility.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.Graphics;
4 | import java.awt.Graphics2D;
5 | import java.awt.Polygon;
6 | import java.util.List;
7 |
8 | public class Utility {
9 |
10 | public static Matrix3x3f createViewport(
11 | float worldWidth, float worldHeight,
12 | float screenWidth, float screenHeight ) {
13 | float sx = (screenWidth - 1) / worldWidth;
14 | float sy = (screenHeight - 1) / worldHeight;
15 | float tx = (screenWidth - 1) / 2.0f;
16 | float ty = (screenHeight - 1) / 2.0f;
17 | Matrix3x3f viewport = Matrix3x3f.scale(sx, -sy);
18 | viewport = viewport.mul(Matrix3x3f.translate(tx, ty));
19 | return viewport;
20 | }
21 |
22 | public static Matrix3x3f createReverseViewport(
23 | float worldWidth, float worldHeight,
24 | float screenWidth, float screenHeight ) {
25 | float sx = worldWidth / (screenWidth - 1);
26 | float sy = worldHeight / (screenHeight - 1);
27 | float tx = (screenWidth - 1) / 2.0f;
28 | float ty = (screenHeight - 1) / 2.0f;
29 | Matrix3x3f viewport = Matrix3x3f.translate(-tx, -ty);
30 | viewport = viewport.mul(Matrix3x3f.scale(sx, -sy));
31 | return viewport;
32 | }
33 |
34 | public static void drawPolygon(Graphics g, Vector2f[] polygon) {
35 | Vector2f P;
36 | Vector2f S = polygon[polygon.length - 1];
37 | for (int i = 0; i < polygon.length; ++i) {
38 | P = polygon[i];
39 | g.drawLine((int) S.x, (int) S.y, (int) P.x, (int) P.y);
40 | S = P;
41 | }
42 | }
43 |
44 | public static void drawPolygon(Graphics g, List polygon) {
45 | Vector2f S = polygon.get(polygon.size() - 1);
46 | for (Vector2f P : polygon) {
47 | g.drawLine((int) S.x, (int) S.y, (int) P.x, (int) P.y);
48 | S = P;
49 | }
50 | }
51 |
52 | public static void fillPolygon(Graphics2D g, Vector2f[] polygon) {
53 | Polygon p = new Polygon();
54 | for (Vector2f v : polygon) {
55 | p.addPoint((int) v.x, (int) v.y);
56 | }
57 | g.fill(p);
58 | }
59 |
60 | public static void fillPolygon(Graphics2D g, List polygon) {
61 | Polygon p = new Polygon();
62 | for (Vector2f v : polygon) {
63 | p.addPoint((int) v.x, (int) v.y);
64 | }
65 | g.fill(p);
66 | }
67 | }
--------------------------------------------------------------------------------
/CH08/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH08/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH09/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH09/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH09
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 |
--------------------------------------------------------------------------------
/CH09/res/assets/lib/javagames/filesandres/Test1.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consectetur adipisicing elit,
2 | sed do eiusmod tempor incididunt ut labore et dolore magna
3 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation
4 | ullamco laboris nisi ut aliquip ex ea commodo consequat.
5 | Duis aute irure dolor in reprehenderit in voluptate velit
6 | esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
7 | occaecat cupidatat non proident, sunt in culpa qui officia
8 | deserunt mollit anim id est laborum.
--------------------------------------------------------------------------------
/CH09/res/assets/lib/javagames/filesandres/Test2.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consectetur adipisicing elit,
2 | sed do eiusmod tempor incididunt ut labore et dolore magna
3 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation
4 | ullamco laboris nisi ut aliquip ex ea commodo consequat.
5 | Duis aute irure dolor in reprehenderit in voluptate velit
6 | esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
7 | occaecat cupidatat non proident, sunt in culpa qui officia
8 | deserunt mollit anim id est laborum.
--------------------------------------------------------------------------------
/CH09/res/assets/lib/javagames/filesandres/Test3.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consectetur adipisicing elit,
2 | sed do eiusmod tempor incididunt ut labore et dolore magna
3 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation
4 | ullamco laboris nisi ut aliquip ex ea commodo consequat.
5 | Duis aute irure dolor in reprehenderit in voluptate velit
6 | esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
7 | occaecat cupidatat non proident, sunt in culpa qui officia
8 | deserunt mollit anim id est laborum.
--------------------------------------------------------------------------------
/CH09/res/assets/lib/resources.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH09/res/assets/lib/resources.jar
--------------------------------------------------------------------------------
/CH09/res/assets/text/byte-file.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH09/res/assets/text/byte-file.bin
--------------------------------------------------------------------------------
/CH09/res/assets/text/lorem-ipsum.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consectetur adipisicing elit,
2 | sed do eiusmod tempor incididunt ut labore et dolore magna
3 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation
4 | ullamco laboris nisi ut aliquip ex ea commodo consequat.
5 | Duis aute irure dolor in reprehenderit in voluptate velit
6 | esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
7 | occaecat cupidatat non proident, sunt in culpa qui officia
8 | deserunt mollit anim id est laborum.
--------------------------------------------------------------------------------
/CH09/res/assets/text/string-file.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consectetur adipisicing elit,
2 | sed do eiusmod tempor incididunt ut labore et dolore magna
3 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation
4 | ullamco laboris nisi ut aliquip ex ea commodo consequat.
5 | Duis aute irure dolor in reprehenderit in voluptate velit
6 | esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
7 | occaecat cupidatat non proident, sunt in culpa qui officia
8 | deserunt mollit anim id est laborum.
9 |
--------------------------------------------------------------------------------
/CH09/sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | I'm some text
7 |
8 | I'm some text
9 |
10 | < > & ' "
11 |
12 |
14 | ]]>
15 |
16 |
17 |
--------------------------------------------------------------------------------
/CH09/src/javagames/filesandres/FilesAndDirectories.java:
--------------------------------------------------------------------------------
1 | package javagames.filesandres;
2 |
3 | import java.io.File;
4 | import java.text.DecimalFormat;
5 | import java.text.SimpleDateFormat;
6 | import java.util.Date;
7 |
8 | public class FilesAndDirectories {
9 |
10 | public FilesAndDirectories() {
11 |
12 | }
13 |
14 | public void runTest() {
15 | // list files and folders
16 | String dir = "D:\\code examples";
17 | File file = new File(dir);
18 | displayInfo(0, file);
19 | }
20 |
21 | private void displayInfo(int depth, File file) {
22 | // Name, Date, Size, Attr
23 | boolean executable = file.canExecute();
24 | boolean readable = file.canRead();
25 | boolean writable = file.canWrite();
26 | boolean hidden = file.isHidden();
27 | boolean directory = file.isDirectory();
28 | long lastModified = file.lastModified();
29 | long length = file.length();
30 | String name = file.getName();
31 | // create ASCII file structure
32 | StringBuilder buf = new StringBuilder();
33 | for (int i = 0; i < depth; ++i) {
34 | buf.append("|");
35 | }
36 | if (directory) {
37 | buf.append("+ ");
38 | }
39 | if (name.isEmpty()) {
40 | buf.append(".");
41 | } else {
42 | buf.append(name);
43 | }
44 | // add modification date
45 | buf.append("\t\t");
46 | Date date = new Date(lastModified);
47 | buf.append(new SimpleDateFormat().format(date));
48 | buf.append("\t\t");
49 | // add file size in kilobytes
50 | long kb = length / 1024;
51 | DecimalFormat format = new DecimalFormat();
52 | format.setGroupingUsed(true);
53 | buf.append(format.format(kb));
54 | buf.append(" KB");
55 | // add read, write, execute attribute flags
56 | buf.append("\t\t");
57 | if (hidden)
58 | buf.append(".");
59 | if (readable)
60 | buf.append("R");
61 | if (writable)
62 | buf.append("W");
63 | if (executable)
64 | buf.append("X");
65 | // print everything to the command line
66 | System.out.println(buf.toString());
67 | File[] children = file.listFiles();
68 | if (children != null) {
69 | for (File child : children) {
70 | displayInfo(depth + 1, child);
71 | }
72 | }
73 | }
74 |
75 | public static void main(String[] args) {
76 | new FilesAndDirectories().runTest();
77 | }
78 | }
--------------------------------------------------------------------------------
/CH09/src/javagames/filesandres/PrintSystemProperties.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH09/src/javagames/filesandres/PrintSystemProperties.java
--------------------------------------------------------------------------------
/CH09/src/javagames/filesandres/PropertyFileExample.java:
--------------------------------------------------------------------------------
1 | package javagames.filesandres;
2 |
3 | import java.io.*;
4 | import java.util.Properties;
5 | import javagames.util.ResourceLoader;
6 |
7 | public class PropertyFileExample {
8 |
9 | private Properties props;
10 |
11 | public PropertyFileExample() {
12 | props = new Properties();
13 | }
14 |
15 | private void loadAndPrintProperties() {
16 | boolean loadPropsFirst = getLoadFirstProperty();
17 | if (loadPropsFirst) {
18 | props.putAll(System.getProperties());
19 | }
20 | loadProperties();
21 | if (!loadPropsFirst) {
22 | props.putAll(System.getProperties());
23 | }
24 | printProperties();
25 | }
26 |
27 | private void loadProperties() {
28 | InputStream in = null;
29 | try {
30 | in = ResourceLoader.load(PropertyFileExample.class,
31 | "./testing.properties", "/testing.properties");
32 | props.load(in);
33 | } catch (IOException e) {
34 | e.printStackTrace();
35 | } finally {
36 | try {
37 | in.close();
38 | } catch (Exception e) {
39 | }
40 | }
41 | }
42 |
43 | private boolean getLoadFirstProperty() {
44 | try {
45 | String value = System.getProperty("load.props.first", "false");
46 | return Boolean.parseBoolean(value);
47 | } catch (Exception e) {
48 | return false;
49 | }
50 | }
51 |
52 | private void printProperties() {
53 | System.out.println("load.props.first=" + getLoadFirstProperty());
54 | System.out.println("user.home=" + props.getProperty("user.home", "."));
55 | System.out.println("prop1=" + props.getProperty("prop1", "default1"));
56 | System.out.println("prop2=" + props.getProperty("prop2", "default2"));
57 | System.out.println("prop3=" + props.getProperty("prop3", "default3"));
58 | System.out.println("override="
59 | + props.getProperty("override", "defaultOverride"));
60 | }
61 |
62 | public static void main(String[] args) {
63 | PropertyFileExample example = new PropertyFileExample();
64 | example.loadAndPrintProperties();
65 | }
66 | }
--------------------------------------------------------------------------------
/CH09/src/javagames/filesandres/ReadingDataFromFiles.java:
--------------------------------------------------------------------------------
1 | package javagames.filesandres;
2 |
3 | import java.io.*;
4 |
5 | public class ReadingDataFromFiles {
6 |
7 | public void runTest() {
8 | String path = "./res/assets/text/lorem-ipsum.txt";
9 | File file = new File(path);
10 | readInBytes(file);
11 | readInStrings(file);
12 | }
13 |
14 | public void readInBytes(File file) {
15 | System.out.println();
16 | System.out.println();
17 | System.out.println("********************");
18 | System.out.println("Reading in bytes");
19 | System.out.println();
20 | InputStream in = null;
21 | try {
22 | in = new FileInputStream(file);
23 | int next = -1;
24 | while ((next = in.read()) != -1) {
25 | System.out.print((char) next);
26 | }
27 | } catch (IOException ex) {
28 | ex.printStackTrace();
29 | } finally {
30 | try {
31 | in.close();
32 | } catch (IOException ex) {
33 | }
34 | }
35 | }
36 |
37 | public void readInStrings(File file) {
38 | System.out.println();
39 | System.out.println();
40 | System.out.println("********************");
41 | System.out.println("Reading in strings");
42 | System.out.println();
43 | Reader reader = null;
44 | try {
45 | reader = new FileReader(file);
46 | BufferedReader buf = new BufferedReader(reader);
47 | String line = null;
48 | while ((line = buf.readLine()) != null) {
49 | System.out.println(line);
50 | }
51 | } catch (IOException ex) {
52 | ex.printStackTrace();
53 | } finally {
54 | try {
55 | reader.close();
56 | } catch (IOException ex) {
57 | }
58 | }
59 | }
60 |
61 | public static void main(String[] args) {
62 | new ReadingDataFromFiles().runTest();
63 | }
64 | }
--------------------------------------------------------------------------------
/CH09/src/javagames/filesandres/ResourceLoaderExample.java:
--------------------------------------------------------------------------------
1 | package javagames.filesandres;
2 |
3 | import java.io.*;
4 | import javagames.util.ResourceLoader;
5 |
6 |
7 | public class ResourceLoaderExample {
8 |
9 | public ResourceLoaderExample() {
10 |
11 | }
12 |
13 | public void runTest() {
14 | Class> clazz = ResourceLoaderExample.class;
15 | // load absolute resource
16 | String filePath = "not/used";
17 | String resPath = "/javagames/filesandres/Test1.txt";
18 | InputStream in = ResourceLoader.load(clazz, filePath, resPath);
19 | printResource(in);
20 | // load relative resource
21 | filePath = "not/used";
22 | resPath = "Test2.txt";
23 | in = ResourceLoader.load(clazz, filePath, resPath);
24 | printResource(in);
25 | // load absolute file path
26 | filePath = "C:/Book/res/assets/lib/javagames/filesandres/Test3.txt";
27 | resPath = "/not/available";
28 | in = ResourceLoader.load(clazz, filePath, resPath);
29 | printResource(in);
30 | // load relative file path
31 | filePath = "res/assets/lib/javagames/filesandres/Test3.txt";
32 | resPath = "/not/available";
33 | in = ResourceLoader.load(clazz, filePath, resPath);
34 | printResource(in);
35 | // error with both is null
36 | filePath = "fat/finger";
37 | resPath = "fat/finger/too";
38 | in = ResourceLoader.load(clazz, filePath, resPath);
39 | printResource(in);
40 | }
41 |
42 | private void printResource(InputStream in) {
43 | try {
44 | InputStreamReader reader = new InputStreamReader(in);
45 | BufferedReader buf = new BufferedReader(reader);
46 | String line = null;
47 | while ((line = buf.readLine()) != null) {
48 | System.out.println(line);
49 | }
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | } finally {
53 | try {
54 | in.close();
55 | } catch (Exception e) {
56 | }
57 | }
58 | }
59 |
60 | public static void main(String[] args) {
61 | new ResourceLoaderExample().runTest();
62 | }
63 | }
--------------------------------------------------------------------------------
/CH09/src/javagames/filesandres/SaveXMLExample.java:
--------------------------------------------------------------------------------
1 | package javagames.filesandres;
2 |
3 | import java.io.File;
4 | import java.io.FileNotFoundException;
5 | import java.io.PrintWriter;
6 |
7 | public class SaveXMLExample {
8 |
9 | public SaveXMLExample() {
10 |
11 | }
12 |
13 | public void createXMLFile() {
14 | File file = new File("sample.xml");
15 | PrintWriter out = null;
16 | try {
17 | out = new PrintWriter(file);
18 | writeXML(out);
19 | } catch (FileNotFoundException fex) {
20 | fex.printStackTrace();
21 | } finally {
22 | try {
23 | out.close();
24 | System.out.println("Wrote: " + file.getPath());
25 | } catch (Exception e) {
26 | }
27 | }
28 | }
29 |
30 | private void writeXML(PrintWriter out) {
31 | out.println("");
32 | // all XML must have a single root tag
33 | out.println("");
34 | // a comment
35 | out.println(" ");
36 | // and empty tag
37 | out.println(" ");
38 | // shorthand for a tag with no children
39 | out.println(" ");
40 | // text element
41 | out.println(" I'm some text");
42 | // nested elements
43 | out.println(" ");
44 | // nested text with child
45 | out.println(" I'm some text ");
46 | // attributes
47 | out.println(" ");
48 | // special characters
49 | out.println(" < > & '"
50 | + " " ");
51 | // unparsed character data CDATA
52 | out.println(" ");
53 | // Starting CDATA tag
54 | out.println(" ");
56 | // Ending CDATA tag
57 | out.println(" ]]>");
58 | out.println(" ");
59 | // ending root tag
60 | out.println("");
61 | }
62 |
63 | public static void main(String[] args) {
64 | new SaveXMLExample().createXMLFile();
65 | }
66 | }
--------------------------------------------------------------------------------
/CH09/src/javagames/filesandres/SavingPropertyFiles.java:
--------------------------------------------------------------------------------
1 | package javagames.filesandres;
2 |
3 | import java.io.*;
4 |
5 | public class SavingPropertyFiles {
6 |
7 | public SavingPropertyFiles() {
8 |
9 | }
10 |
11 | public void saveFile() {
12 | File file = new File("testing.properties");
13 | PrintWriter out = null;
14 | try {
15 | out = new PrintWriter(file);
16 | out.println("# This is a comment");
17 | out.println("prop1=fileValue1");
18 | out.println("# This is another comment");
19 | out.println("prop2=fileValue2");
20 | out.println("# This can be overriden from the");
21 | out.println("! command line, or not...");
22 | out.println("override=fileoverride");
23 | } catch (FileNotFoundException fex) {
24 | fex.printStackTrace();
25 | } finally {
26 | try {
27 | out.close();
28 | System.out.println("Wrote: " + file.getPath());
29 | } catch (Exception e) {
30 | }
31 | }
32 | }
33 |
34 | public static void main(String[] args) {
35 | new SavingPropertyFiles().saveFile();
36 | }
37 | }
--------------------------------------------------------------------------------
/CH09/src/javagames/util/ResourceLoader.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.FileNotFoundException;
5 | import java.io.InputStream;
6 |
7 | public class ResourceLoader {
8 |
9 | public static InputStream load(Class> clazz, String filePath,
10 | String resPath) {
11 | // try the resource first
12 | InputStream in = null;
13 | if (!(resPath == null || resPath.isEmpty())) {
14 | in = clazz.getResourceAsStream(resPath);
15 | }
16 | if (in == null) {
17 | // try the file path
18 | try {
19 | in = new FileInputStream(filePath);
20 | } catch (FileNotFoundException e) {
21 | e.printStackTrace();
22 | }
23 | }
24 | return in;
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/CH09/src/javagames/util/XMLUtility.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.io.*;
4 | import java.util.*;
5 | import javax.xml.parsers.*;
6 | import org.w3c.dom.*;
7 | import org.xml.sax.*;
8 |
9 | public class XMLUtility {
10 |
11 | public static Document parseDocument(InputStream inputStream)
12 | throws ParserConfigurationException, SAXException, IOException {
13 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
14 | DocumentBuilder builder = factory.newDocumentBuilder();
15 | Document document = builder.parse(new InputSource(inputStream));
16 | return document;
17 | }
18 |
19 | public static Document parseDocument(Reader reader)
20 | throws ParserConfigurationException, SAXException, IOException {
21 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
22 | DocumentBuilder builder = factory.newDocumentBuilder();
23 | Document document = builder.parse(new InputSource(reader));
24 | return document;
25 | }
26 |
27 | public static List getAllElements(Element element, String tagName) {
28 | ArrayList elements = new ArrayList();
29 | NodeList nodes = element.getElementsByTagName(tagName);
30 | for (int i = 0; i < nodes.getLength(); i++) {
31 | elements.add((Element) nodes.item(i));
32 | }
33 | return elements;
34 | }
35 |
36 | public static List getElements(Element element, String tagName) {
37 | ArrayList elements = new ArrayList();
38 | NodeList children = element.getChildNodes();
39 | for (int i = 0; i < children.getLength(); i++) {
40 | Node node = children.item(i);
41 | if (node.getNodeType() == Node.ELEMENT_NODE) {
42 | String nodeName = node.getNodeName();
43 | if (nodeName != null && nodeName.equals(tagName)) {
44 | elements.add((Element) node);
45 | }
46 | }
47 | }
48 | return elements;
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/CH09/testing.properties:
--------------------------------------------------------------------------------
1 | # This is a comment
2 | prop1=fileValue1
3 | # This is another comment
4 | prop2=fileValue2
5 | # This can be overriden from the
6 | ! command line, or not...
7 | override=fileoverride
8 |
--------------------------------------------------------------------------------
/CH09/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH10/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH10/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH10
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 |
--------------------------------------------------------------------------------
/CH10/image-creator.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH10/image-creator.bmp
--------------------------------------------------------------------------------
/CH10/image-creator.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH10/image-creator.gif
--------------------------------------------------------------------------------
/CH10/image-creator.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH10/image-creator.jpg
--------------------------------------------------------------------------------
/CH10/image-creator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH10/image-creator.png
--------------------------------------------------------------------------------
/CH10/src/javagames/images/TransparentImageExample.java:
--------------------------------------------------------------------------------
1 | package javagames.images;
2 |
3 | import java.awt.*;
4 | import java.awt.image.BufferedImage;
5 | import javagames.util.SimpleFramework;
6 |
7 | public class TransparentImageExample extends SimpleFramework {
8 |
9 | private BufferedImage img;
10 | private float shift;
11 |
12 | public TransparentImageExample() {
13 | appWidth = 400;
14 | appHeight = 300;
15 | appSleep = 10L;
16 | appTitle = "Transparent Image Example";
17 | appBackground = Color.DARK_GRAY;
18 | }
19 |
20 | @Override
21 | protected void initialize() {
22 | super.initialize();
23 | img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
24 | Graphics2D g2d = img.createGraphics();
25 | int w = 8;
26 | int h = 8;
27 | int dx = img.getWidth() / w;
28 | int dy = img.getHeight() / h;
29 | for (int i = 0; i < w; ++i) {
30 | for (int j = 0; j < h; ++j) {
31 | if ((i + j) % 2 == 0) {
32 | g2d.setColor(Color.WHITE);
33 | g2d.fillRect(i * dx, j * dy, dx, dy);
34 | }
35 | }
36 | }
37 | g2d.dispose();
38 | }
39 |
40 | @Override
41 | protected void updateObjects(float delta) {
42 | super.updateObjects(delta);
43 | int ribbonHeight = canvas.getHeight() / 5;
44 | shift += delta * ribbonHeight;
45 | if (shift > ribbonHeight) {
46 | shift -= ribbonHeight;
47 | }
48 | }
49 |
50 | @Override
51 | protected void render(Graphics g) {
52 | super.render(g);
53 | // draw shifting background
54 | int hx = canvas.getHeight() / 5;
55 | g.setColor(Color.LIGHT_GRAY);
56 | for (int i = -1; i < 5; ++i) {
57 | g.fillRect(0, (int) shift + hx * i, canvas.getWidth(), hx / 2);
58 | }
59 | int x = (canvas.getWidth() - img.getWidth()) / 2;
60 | int y = (canvas.getHeight() - img.getHeight()) / 2;
61 | g.drawImage(img, x, y, null);
62 | }
63 |
64 | public static void main(String[] args) {
65 | launchApp(new TransparentImageExample());
66 | }
67 | }
--------------------------------------------------------------------------------
/CH10/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH10/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH10/src/javagames/util/Utility.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.Graphics;
4 | import java.awt.Graphics2D;
5 | import java.awt.Polygon;
6 | import java.util.List;
7 |
8 | public class Utility {
9 |
10 | public static Matrix3x3f createViewport(
11 | float worldWidth, float worldHeight,
12 | float screenWidth, float screenHeight ) {
13 | float sx = (screenWidth - 1) / worldWidth;
14 | float sy = (screenHeight - 1) / worldHeight;
15 | float tx = (screenWidth - 1) / 2.0f;
16 | float ty = (screenHeight - 1) / 2.0f;
17 | Matrix3x3f viewport = Matrix3x3f.scale(sx, -sy);
18 | viewport = viewport.mul(Matrix3x3f.translate(tx, ty));
19 | return viewport;
20 | }
21 |
22 | public static Matrix3x3f createReverseViewport(
23 | float worldWidth, float worldHeight,
24 | float screenWidth, float screenHeight ) {
25 | float sx = worldWidth / (screenWidth - 1);
26 | float sy = worldHeight / (screenHeight - 1);
27 | float tx = (screenWidth - 1) / 2.0f;
28 | float ty = (screenHeight - 1) / 2.0f;
29 | Matrix3x3f viewport = Matrix3x3f.translate(-tx, -ty);
30 | viewport = viewport.mul(Matrix3x3f.scale(sx, -sy));
31 | return viewport;
32 | }
33 |
34 | public static void drawPolygon(Graphics g, Vector2f[] polygon) {
35 | Vector2f P;
36 | Vector2f S = polygon[polygon.length - 1];
37 | for (int i = 0; i < polygon.length; ++i) {
38 | P = polygon[i];
39 | g.drawLine((int) S.x, (int) S.y, (int) P.x, (int) P.y);
40 | S = P;
41 | }
42 | }
43 |
44 | public static void drawPolygon(Graphics g, List polygon) {
45 | Vector2f S = polygon.get(polygon.size() - 1);
46 | for (Vector2f P : polygon) {
47 | g.drawLine((int) S.x, (int) S.y, (int) P.x, (int) P.y);
48 | S = P;
49 | }
50 | }
51 |
52 | public static void fillPolygon(Graphics2D g, Vector2f[] polygon) {
53 | Polygon p = new Polygon();
54 | for (Vector2f v : polygon) {
55 | p.addPoint((int) v.x, (int) v.y);
56 | }
57 | g.fill(p);
58 | }
59 |
60 | public static void fillPolygon(Graphics2D g, List polygon) {
61 | Polygon p = new Polygon();
62 | for (Vector2f v : polygon) {
63 | p.addPoint((int) v.x, (int) v.y);
64 | }
65 | g.fill(p);
66 | }
67 | }
--------------------------------------------------------------------------------
/CH10/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH10/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH11/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH11/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH11
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 |
--------------------------------------------------------------------------------
/CH11/src/javagames/text/BoxedTextProblem.java:
--------------------------------------------------------------------------------
1 | package javagames.text;
2 |
3 | import java.awt.Color;
4 | import java.awt.Font;
5 | import java.awt.Graphics;
6 | import javagames.util.SimpleFramework;
7 |
8 | public class BoxedTextProblem extends SimpleFramework {
9 |
10 | public BoxedTextProblem() {
11 | appWidth = 640;
12 | appHeight = 640;
13 | appSleep = 10L;
14 | appTitle = "Boxed Text Problem";
15 | appBackground = Color.WHITE;
16 | appFPSColor = Color.BLACK;
17 | }
18 |
19 | @Override
20 | protected void initialize() {
21 | super.initialize();
22 | }
23 |
24 | @Override
25 | protected void render(Graphics g) {
26 | super.render(g);
27 | // Box this text...
28 | g.setColor(Color.BLACK);
29 | String box = "great Java, now what?";
30 | Font font = new Font("Arial", Font.PLAIN, 24);
31 | g.setFont(font);
32 | g.drawString(box, 20, 50);
33 | g.setColor(Color.RED);
34 | g.drawRect(20, 50, 200, 20);
35 | }
36 |
37 | public static void main(String[] args) {
38 | launchApp(new BoxedTextProblem());
39 | }
40 | }
--------------------------------------------------------------------------------
/CH11/src/javagames/text/BoxedTextSolution.java:
--------------------------------------------------------------------------------
1 | package javagames.text;
2 |
3 | import java.awt.*;
4 | import javagames.util.SimpleFramework;
5 |
6 | public class BoxedTextSolution extends SimpleFramework {
7 |
8 | public BoxedTextSolution() {
9 | appWidth = 640;
10 | appHeight = 640;
11 | appSleep = 10L;
12 | appTitle = "Boxed Text Solution";
13 | appBackground = Color.WHITE;
14 | appFPSColor = Color.BLACK;
15 | }
16 |
17 | @Override
18 | protected void initialize() {
19 | super.initialize();
20 | }
21 |
22 | @Override
23 | protected void render(Graphics g) {
24 | super.render(g);
25 | // Set the font...
26 | Font font = new Font("Arial", Font.PLAIN, 24);
27 | g.setFont(font);
28 | FontMetrics fm = g.getFontMetrics();
29 | int x = 20;
30 | int y = 50;
31 | // Draw the top...
32 | String str = "draw the top line";
33 | g.setColor(Color.DARK_GRAY);
34 | g.drawString(str, x, y);
35 | int width = 100;
36 | g.setColor(Color.RED);
37 | g.drawLine(x, y, x + width, y);
38 | // Calculate the string width...
39 | y += 40;
40 | str = "Calculate correct width";
41 | g.setColor(Color.DARK_GRAY);
42 | g.drawString(str, x, y);
43 | width = fm.stringWidth(str);
44 | g.setColor(Color.GREEN);
45 | g.drawLine(x, y, x + width, y);
46 | // Use Ascent to offset y
47 | y += 40;
48 | g.setColor(Color.DARK_GRAY);
49 | str = "offset text with the Ascent";
50 | g.drawString(str, x, y + fm.getAscent());
51 | width = fm.stringWidth(str);
52 | g.setColor(Color.BLUE);
53 | g.drawLine(x, y, x + width, y);
54 | // Ascent+Decent+Leading=Height
55 | y += 40;
56 | g.setColor(Color.DARK_GRAY);
57 | str = "Calculate height of font";
58 | g.drawString(str, x, y + fm.getAscent());
59 | width = fm.stringWidth(str);
60 | g.setColor(Color.BLUE);
61 | g.drawLine(x, y, x + width, y);
62 | int height = fm.getAscent() + fm.getDescent() + fm.getLeading();
63 | g.drawLine(x, y + height, x + width, y + height);
64 | // Box the text
65 | y += 40;
66 | g.setColor(Color.DARK_GRAY);
67 | str = "Groovy, we got it!!!";
68 | g.drawString(str, x, y + fm.getAscent());
69 | width = fm.stringWidth(str);
70 | g.setColor(Color.BLUE);
71 | height = fm.getAscent() + fm.getDescent() + fm.getLeading();
72 | g.drawRect(x, y, width, height);
73 | }
74 |
75 | public static void main(String[] args) {
76 | launchApp(new BoxedTextSolution());
77 | }
78 | }
--------------------------------------------------------------------------------
/CH11/src/javagames/text/TextLayoutExample.java:
--------------------------------------------------------------------------------
1 | package javagames.text;
2 |
3 | import java.awt.*;
4 | import java.awt.RenderingHints;
5 | import java.awt.image.BufferedImage;
6 | import javagames.util.SimpleFramework;
7 |
8 | public class TextLayoutExample extends SimpleFramework {
9 |
10 | private Font font;
11 | private int maxWidth;
12 |
13 | public TextLayoutExample() {
14 | appWidth = 640;
15 | appHeight = 640;
16 | appSleep = 10L;
17 | appTitle = "Text Layout Example";
18 | appBackground = Color.WHITE;
19 | appFPSColor = Color.BLACK;
20 | }
21 |
22 | @Override
23 | protected void initialize() {
24 | super.initialize();
25 | font = new Font("Arial", Font.BOLD, 40);
26 | FontMetrics fm = getFontMetrics(font);
27 | maxWidth = Integer.MIN_VALUE;
28 | for (int i = (int) '!'; i < (int) 'z'; ++i) {
29 | String letter = " " + (char) i;
30 | maxWidth = Math.max(maxWidth, fm.stringWidth(letter));
31 | }
32 | // another way
33 | BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
34 | Graphics2D g = img.createGraphics();
35 | FontMetrics fontMetrics = g.getFontMetrics(font);
36 | g.dispose();
37 | }
38 |
39 | @Override
40 | protected void render(Graphics g) {
41 | super.render(g);
42 | Graphics2D g2d = (Graphics2D) g;
43 | g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
44 | RenderingHints.VALUE_ANTIALIAS_ON);
45 | g2d.setColor(Color.GREEN);
46 | g2d.setFont(font);
47 | FontMetrics fm = g2d.getFontMetrics();
48 | int height = fm.getAscent() + fm.getDescent() + fm.getLeading();
49 | int x = 20;
50 | int y = 50;
51 | y += fm.getAscent();
52 | int count = 0;
53 | for (int i = (int) '!'; i <= (int) 'z'; ++i) {
54 | String letter = " " + (char) i;
55 | g2d.drawString(letter, x, y);
56 | x += maxWidth;
57 | count++;
58 | if (count % 10 == 0) {
59 | y += height;
60 | x = 20;
61 | }
62 | }
63 | }
64 |
65 | public static void main(String[] args) {
66 | launchApp(new TextLayoutExample());
67 | }
68 | }
--------------------------------------------------------------------------------
/CH11/src/javagames/text/UtilityDrawStringExample.java:
--------------------------------------------------------------------------------
1 | package javagames.text;
2 |
3 | import java.awt.*;
4 | import java.awt.event.KeyEvent;
5 | import java.util.Vector;
6 | import javagames.util.*;
7 |
8 | public class UtilityDrawStringExample extends SimpleFramework {
9 |
10 | public UtilityDrawStringExample() {
11 | appFont = new Font("Courier New", Font.BOLD, 48);
12 | appWidth = 640;
13 | appHeight = 640;
14 | appSleep = 10L;
15 | appTitle = "Utility Draw String Example";
16 | appBackground = Color.WHITE;
17 | appFPSColor = Color.BLACK;
18 | }
19 |
20 | @Override
21 | protected void processInput(float delta) {
22 | super.processInput(delta);
23 | if (keyboard.keyDownOnce(KeyEvent.VK_UP)) {
24 | int fontSize = appFont.getSize();
25 | appFont = new Font(appFont.getFamily(), appFont.getStyle(),
26 | fontSize + 2);
27 | }
28 | if (keyboard.keyDownOnce(KeyEvent.VK_DOWN)) {
29 | int fontSize = appFont.getSize();
30 | appFont = new Font(appFont.getFamily(), appFont.getStyle(),
31 | fontSize - 2);
32 | }
33 | }
34 |
35 | @Override
36 | protected void render(Graphics g) {
37 | super.render(g);
38 | Graphics2D g2d = (Graphics2D) g;
39 | g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
40 | RenderingHints.VALUE_ANTIALIAS_ON);
41 | textPos = Utility.drawString(g2d, 20, textPos, "Font Size: "
42 | + g2d.getFont().getSize());
43 | textPos = Utility.drawString(g2d, 20, textPos, "Use the arrow keys",
44 | "to tweak the font size", "");
45 | g2d.setColor(Color.WHITE);
46 | textPos = Utility.drawString(g2d, 20, textPos, "Single String");
47 | g2d.setColor(Color.BLUE);
48 | textPos = Utility.drawString(g2d, 20, textPos, "Strings ", "With",
49 | "Commas");
50 | g2d.setColor(Color.DARK_GRAY);
51 | String[] array = new String[] { "Strings", "With", "Arrays", };
52 | textPos = Utility.drawString(g2d, 20, textPos, array);
53 | g2d.setColor(Color.RED);
54 | Vector list = new Vector();
55 | list.add("Strings");
56 | list.add("With");
57 | list.add("Lists");
58 | textPos = Utility.drawString(g2d, 20, textPos, list);
59 | }
60 |
61 | public static void main(String[] args) {
62 | launchApp(new UtilityDrawStringExample());
63 | }
64 | }
--------------------------------------------------------------------------------
/CH11/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH11/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH11/src/javagames/util/SafeKeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.event.KeyEvent;
4 | import java.awt.event.KeyListener;
5 | import java.util.LinkedList;
6 |
7 | public class SafeKeyboardInput implements KeyListener {
8 |
9 | enum EventType {
10 | PRESSED, RELEASED, TYPED;
11 | }
12 |
13 | class Event {
14 | KeyEvent event;
15 | EventType type;
16 |
17 | public Event(KeyEvent event, EventType type) {
18 | this.event = event;
19 | this.type = type;
20 | }
21 | }
22 |
23 | private LinkedList eventThread = new LinkedList();
24 | private LinkedList gameThread = new LinkedList();
25 | private Event event = null;
26 | private int[] polled;
27 |
28 | public SafeKeyboardInput() {
29 | polled = new int[256];
30 | }
31 |
32 | public boolean keyDown(int keyCode) {
33 | return keyCode == event.event.getKeyCode() && polled[keyCode] > 0;
34 | }
35 |
36 | public boolean keyDownOnce(int keyCode) {
37 | return keyCode == event.event.getKeyCode() && polled[keyCode] == 1;
38 | }
39 |
40 | public boolean processEvent() {
41 | event = gameThread.poll();
42 | if (event != null) {
43 | int keyCode = event.event.getKeyCode();
44 | if (keyCode >= 0 && keyCode < polled.length) {
45 | if (event.type == EventType.PRESSED) {
46 | polled[keyCode]++;
47 | } else if (event.type == EventType.RELEASED) {
48 | polled[keyCode] = 0;
49 | }
50 | }
51 | }
52 | return event != null;
53 | }
54 |
55 | public Character getKeyTyped() {
56 | if (event.type != EventType.TYPED) {
57 | return null;
58 | } else {
59 | return event.event.getKeyChar();
60 | }
61 | }
62 |
63 | public synchronized void poll() {
64 | LinkedList swap = eventThread;
65 | eventThread = gameThread;
66 | gameThread = swap;
67 | }
68 |
69 | public synchronized void keyPressed(KeyEvent e) {
70 | eventThread.add(new Event(e, EventType.PRESSED));
71 | }
72 |
73 | public synchronized void keyReleased(KeyEvent e) {
74 | eventThread.add(new Event(e, EventType.RELEASED));
75 | }
76 |
77 | public synchronized void keyTyped(KeyEvent e) {
78 | eventThread.add(new Event(e, EventType.TYPED));
79 | }
80 | }
--------------------------------------------------------------------------------
/CH11/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH11/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH12/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH12/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH12
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 |
--------------------------------------------------------------------------------
/CH12/src/javagames/threads/BlockingHardwareListener.java:
--------------------------------------------------------------------------------
1 | package javagames.threads;
2 |
3 | public interface BlockingHardwareListener {
4 |
5 | public void taskFinished();
6 |
7 | }
--------------------------------------------------------------------------------
/CH12/src/javagames/threads/CallableTaskExample.java:
--------------------------------------------------------------------------------
1 | package javagames.threads;
2 |
3 | import java.util.Random;
4 | import java.util.concurrent.*;
5 |
6 | public class CallableTaskExample implements Callable {
7 |
8 | @Override
9 | public Boolean call() throws Exception {
10 | // simulate some stupid long task and maybe fail...
11 | Random rand = new Random();
12 | int seconds = rand.nextInt(6);
13 | if (seconds == 0) {
14 | // pretend there was an error
15 | throw new RuntimeException("I love the new thread stuff!!! :)");
16 | }
17 | try {
18 | Thread.sleep(seconds * 100);
19 | } catch (InterruptedException e) {
20 | }
21 | // even = true, odd = false
22 | return seconds % 2 == 0;
23 | }
24 |
25 | public static void main(String[] args) {
26 | ExecutorService exec = Executors.newCachedThreadPool();
27 | try {
28 | for (int i = 0; i < 50; ++i) {
29 | try {
30 | Future result = exec.submit(new CallableTaskExample());
31 | Boolean success = result.get();
32 | System.out.println("Result: " + success);
33 | } catch (ExecutionException ex) {
34 | Throwable throwable = ex.getCause();
35 | System.out.println("Error: " + throwable.getMessage());
36 | } catch (InterruptedException e) {
37 | System.out.println("Awesome! Thread was canceled");
38 | e.printStackTrace();
39 | }
40 | }
41 | } finally {
42 | try {
43 | exec.shutdown();
44 | exec.awaitTermination(10, TimeUnit.SECONDS);
45 | System.out.println("Threadpool Shutdown :)");
46 | } catch (InterruptedException e) {
47 | // at this point, just give up...
48 | e.printStackTrace();
49 | System.exit(-1);
50 | }
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/CH12/src/javagames/threads/FakeHardwareListener.java:
--------------------------------------------------------------------------------
1 | package javagames.threads;
2 |
3 | import javagames.threads.FakeHardware.FakeHardwareEvent;
4 |
5 | public interface FakeHardwareListener {
6 |
7 | public void event(FakeHardware source, FakeHardwareEvent event);
8 |
9 | }
--------------------------------------------------------------------------------
/CH12/src/javagames/threads/MultiThreadEventExample.java:
--------------------------------------------------------------------------------
1 | package javagames.threads;
2 |
3 | import java.awt.Color;
4 | import java.awt.Graphics;
5 | import java.awt.event.KeyEvent;
6 | import javagames.util.SimpleFramework;
7 | import javagames.util.Utility;
8 |
9 | public class MultiThreadEventExample extends SimpleFramework {
10 |
11 | private OneShotEvent oneShot;
12 | private LoopEvent loop;
13 | private RestartEvent restart;
14 |
15 | public MultiThreadEventExample() {
16 | appWidth = 640;
17 | appHeight = 640;
18 | appSleep = 10L;
19 | appTitle = "Multi-Thread Event Example";
20 | appBackground = Color.WHITE;
21 | appFPSColor = Color.BLACK;
22 | }
23 |
24 | @Override
25 | protected void initialize() {
26 | super.initialize();
27 | oneShot = new OneShotEvent(5000, 10);
28 | oneShot.initialize();
29 | loop = new LoopEvent(1000, 4);
30 | loop.initialize();
31 | restart = new RestartEvent(5000, 10);
32 | restart.initialize();
33 | }
34 |
35 | @Override
36 | protected void processInput(float delta) {
37 | super.processInput(delta);
38 | if (keyboard.keyDownOnce(KeyEvent.VK_1)) {
39 | oneShot.fire();
40 | }
41 | if (keyboard.keyDownOnce(KeyEvent.VK_2)) {
42 | oneShot.done();
43 | }
44 | if (keyboard.keyDownOnce(KeyEvent.VK_3)) {
45 | loop.fire();
46 | }
47 | if (keyboard.keyDownOnce(KeyEvent.VK_4)) {
48 | loop.done();
49 | }
50 | if (keyboard.keyDownOnce(KeyEvent.VK_5)) {
51 | restart.fire();
52 | }
53 | }
54 |
55 | @Override
56 | protected void render(Graphics g) {
57 | super.render(g);
58 | textPos = Utility.drawString(g, 20, textPos, "", "(1) Fire One Shot",
59 | "(2) Cancel One Shot", "(3) Start Loop", "(4) Stop Loop",
60 | "(5) Reusable");
61 | }
62 |
63 | @Override
64 | protected void terminate() {
65 | super.terminate();
66 | oneShot.shutDown();
67 | loop.shutDown();
68 | restart.shutDown();
69 | }
70 |
71 | public static void main(String[] args) {
72 | launchApp(new MultiThreadEventExample());
73 | }
74 | }
--------------------------------------------------------------------------------
/CH12/src/javagames/threads/WaitNotifyExample.java:
--------------------------------------------------------------------------------
1 | package javagames.threads;
2 |
3 | import javagames.threads.FakeHardware.FakeHardwareEvent;
4 |
5 | public class WaitNotifyExample implements FakeHardwareListener {
6 |
7 | public WaitNotifyExample() {
8 |
9 | }
10 |
11 | public void runTest() throws Exception {
12 | FakeHardware hardware = new FakeHardware("name");
13 | hardware.addListener(this);
14 | synchronized (this) {
15 | hardware.turnOn();
16 | while (!hardware.isOn()) {
17 | wait();
18 | }
19 | }
20 | System.out.println("Hardware is on!");
21 | synchronized (this) {
22 | hardware.start(1000, 4);
23 | while (!hardware.isRunning()) {
24 | wait();
25 | }
26 | }
27 | System.out.println("Hardware is running");
28 | synchronized (this) {
29 | while (hardware.isRunning()) {
30 | wait();
31 | }
32 | }
33 | System.out.println("Hardware has stopped!");
34 | synchronized (this) {
35 | hardware.turnOff();
36 | while (hardware.isOn()) {
37 | wait();
38 | }
39 | }
40 | }
41 |
42 | @Override
43 | public synchronized void event(FakeHardware source, FakeHardwareEvent event) {
44 | System.out.println("Got Event: " + event);
45 | notifyAll();
46 | }
47 |
48 | public static void main(String[] args) throws Exception {
49 | new WaitNotifyExample().runTest();
50 | }
51 | }
--------------------------------------------------------------------------------
/CH12/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH12/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH12/src/javagames/util/SafeKeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.event.KeyEvent;
4 | import java.awt.event.KeyListener;
5 | import java.util.LinkedList;
6 |
7 | public class SafeKeyboardInput implements KeyListener {
8 |
9 | enum EventType {
10 | PRESSED, RELEASED, TYPED;
11 | }
12 |
13 | class Event {
14 | KeyEvent event;
15 | EventType type;
16 |
17 | public Event(KeyEvent event, EventType type) {
18 | this.event = event;
19 | this.type = type;
20 | }
21 | }
22 |
23 | private LinkedList eventThread = new LinkedList();
24 | private LinkedList gameThread = new LinkedList();
25 | private Event event = null;
26 | private int[] polled;
27 |
28 | public SafeKeyboardInput() {
29 | polled = new int[256];
30 | }
31 |
32 | public boolean keyDown(int keyCode) {
33 | return keyCode == event.event.getKeyCode() && polled[keyCode] > 0;
34 | }
35 |
36 | public boolean keyDownOnce(int keyCode) {
37 | return keyCode == event.event.getKeyCode() && polled[keyCode] == 1;
38 | }
39 |
40 | public boolean processEvent() {
41 | event = gameThread.poll();
42 | if (event != null) {
43 | int keyCode = event.event.getKeyCode();
44 | if (keyCode >= 0 && keyCode < polled.length) {
45 | if (event.type == EventType.PRESSED) {
46 | polled[keyCode]++;
47 | } else if (event.type == EventType.RELEASED) {
48 | polled[keyCode] = 0;
49 | }
50 | }
51 | }
52 | return event != null;
53 | }
54 |
55 | public Character getKeyTyped() {
56 | if (event.type != EventType.TYPED) {
57 | return null;
58 | } else {
59 | return event.event.getKeyChar();
60 | }
61 | }
62 |
63 | public synchronized void poll() {
64 | LinkedList swap = eventThread;
65 | eventThread = gameThread;
66 | gameThread = swap;
67 | }
68 |
69 | public synchronized void keyPressed(KeyEvent e) {
70 | eventThread.add(new Event(e, EventType.PRESSED));
71 | }
72 |
73 | public synchronized void keyReleased(KeyEvent e) {
74 | eventThread.add(new Event(e, EventType.RELEASED));
75 | }
76 |
77 | public synchronized void keyTyped(KeyEvent e) {
78 | eventThread.add(new Event(e, EventType.TYPED));
79 | }
80 | }
--------------------------------------------------------------------------------
/CH12/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH12/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH13/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH13/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH13
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 |
--------------------------------------------------------------------------------
/CH13/res/assets/sound/AMBIENCE_alien.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/AMBIENCE_alien.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/ANIMAL_creatureelement_human_05.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/ANIMAL_creatureelement_human_05.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/BLAST9.WAV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/BLAST9.WAV
--------------------------------------------------------------------------------
/CH13/res/assets/sound/DRONE9RE.WAV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/DRONE9RE.WAV
--------------------------------------------------------------------------------
/CH13/res/assets/sound/ELECTRONIC_computer_beep_09.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/ELECTRONIC_computer_beep_09.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/EXPLOSION_large_01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/EXPLOSION_large_01.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/EXPLOSION_large_02.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/EXPLOSION_large_02.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/EXPLOSION_large_03.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/EXPLOSION_large_03.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/EXPLOSION_large_04.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/EXPLOSION_large_04.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/EXPLOSION_large_05.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/EXPLOSION_large_05.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/LASER13.WAV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/LASER13.WAV
--------------------------------------------------------------------------------
/CH13/res/assets/sound/WEAPON_scifi_fire_02.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/WEAPON_scifi_fire_02.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/WEAPON_scifi_fire_03.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/WEAPON_scifi_fire_03.wav
--------------------------------------------------------------------------------
/CH13/res/assets/sound/WEATHER_rain_medium_5k.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH13/res/assets/sound/WEATHER_rain_medium_5k.wav
--------------------------------------------------------------------------------
/CH13/src/javagames/sound/BlockingAudioListener.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public interface BlockingAudioListener {
4 |
5 | public void audioFinished();
6 |
7 | }
--------------------------------------------------------------------------------
/CH13/src/javagames/sound/BlockingDataLine.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public class BlockingDataLine extends AudioStream {
4 |
5 | private AudioDataLine stream;
6 |
7 | public BlockingDataLine(byte[] soundData) {
8 | super(soundData);
9 | }
10 |
11 | @Override
12 | public void open() {
13 | lock.lock();
14 | try {
15 | stream = new AudioDataLine(soundData);
16 | stream.initialize();
17 | stream.addLineListener(this);
18 | stream.open();
19 | while (!open) {
20 | cond.await();
21 | }
22 | //UPDATE
23 | createControls( stream.getLine() );
24 | //UPDATE
25 | System.out.println("open");
26 | } catch (InterruptedException ex) {
27 | ex.printStackTrace();
28 | } finally {
29 | lock.unlock();
30 | }
31 | }
32 |
33 | @Override
34 | public void start() {
35 | lock.lock();
36 | try {
37 | stream.start();
38 | while (!started) {
39 | cond.await();
40 | }
41 | System.out.println("started");
42 | } catch (InterruptedException ex) {
43 | ex.printStackTrace();
44 | } finally {
45 | lock.unlock();
46 | }
47 | }
48 |
49 | @Override
50 | public void loop(int count) {
51 | lock.lock();
52 | try {
53 | stream.loop(count);
54 | while (!started) {
55 | cond.await();
56 | }
57 | System.out.println("started");
58 | } catch (InterruptedException ex) {
59 | ex.printStackTrace();
60 | } finally {
61 | lock.unlock();
62 | }
63 | }
64 |
65 | @Override
66 | public void restart() {
67 | stream.reset();
68 | }
69 |
70 | @Override
71 | public void stop() {
72 | lock.lock();
73 | try {
74 | stream.stop();
75 | while (started) {
76 | cond.await();
77 | }
78 | System.out.println("stopped");
79 | } catch (InterruptedException ex) {
80 | ex.printStackTrace();
81 | } finally {
82 | lock.unlock();
83 | }
84 | }
85 |
86 | @Override
87 | public void close() {
88 | lock.lock();
89 | try {
90 | stream.close();
91 | while (open) {
92 | cond.await();
93 | }
94 | //UPDATE
95 | clearControls();
96 | //UPDATE
97 | System.out.println("closed");
98 | } catch (InterruptedException ex) {
99 | ex.printStackTrace();
100 | } finally {
101 | lock.unlock();
102 | }
103 | }
104 | }
--------------------------------------------------------------------------------
/CH13/src/javagames/sound/LoopEvent.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public class LoopEvent extends SoundEvent {
4 |
5 | public static final String STATE_WAITING = "waiting";
6 | public static final String STATE_RUNNING = "running";
7 | public static final String EVENT_FIRE = "fire";
8 | public static final String EVENT_DONE = "done";
9 | private String currentState;
10 |
11 | public LoopEvent(AudioStream audio) {
12 | super(audio);
13 | currentState = STATE_WAITING;
14 | }
15 |
16 | public void fire() {
17 | put(EVENT_FIRE);
18 | }
19 |
20 | public void done() {
21 | put(EVENT_DONE);
22 | }
23 |
24 | protected void processEvent(String event) throws InterruptedException {
25 | System.out.println("Got " + event + " event");
26 | if (currentState == STATE_WAITING) {
27 | if (event == EVENT_FIRE) {
28 | audio.open();
29 | audio.loop(AudioStream.LOOP_CONTINUOUSLY);
30 | currentState = STATE_RUNNING;
31 | }
32 | } else if (currentState == STATE_RUNNING) {
33 | if (event == EVENT_DONE) {
34 | audio.stop();
35 | audio.close();
36 | currentState = STATE_WAITING;
37 | }
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/CH13/src/javagames/sound/OneShotEvent.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public class OneShotEvent extends SoundEvent {
4 |
5 | public static final String STATE_WAITING = "waiting";
6 | public static final String STATE_RUNNING = "running";
7 | public static final String EVENT_FIRE = "fire";
8 | public static final String EVENT_DONE = "done";
9 | private String currentState;
10 |
11 | public OneShotEvent(AudioStream audio) {
12 | super(audio);
13 | currentState = STATE_WAITING;
14 | }
15 |
16 | public void fire() {
17 | put(EVENT_FIRE);
18 | }
19 |
20 | public void done() {
21 | put(EVENT_DONE);
22 | }
23 |
24 | protected void processEvent(String event) throws InterruptedException {
25 | System.out.println("Got " + event + " event");
26 | if (currentState == STATE_WAITING) {
27 | if (event == EVENT_FIRE) {
28 | audio.open();
29 | audio.start();
30 | currentState = STATE_RUNNING;
31 | }
32 | } else if (currentState == STATE_RUNNING) {
33 | if (event == EVENT_DONE) {
34 | audio.stop();
35 | audio.close();
36 | currentState = STATE_WAITING;
37 | }
38 | }
39 | }
40 |
41 | @Override
42 | protected void onAudioFinished() {
43 | put(EVENT_DONE);
44 | }
45 | }
--------------------------------------------------------------------------------
/CH13/src/javagames/sound/RestartEvent.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public class RestartEvent extends SoundEvent {
4 |
5 | public static final String STATE_WAITING = "waiting";
6 | public static final String STATE_RUNNING = "running";
7 | public static final String EVENT_FIRE = "fire";
8 | public static final String EVENT_DONE = "done";
9 | private String currentState;
10 |
11 | public RestartEvent(AudioStream stream) {
12 | super(stream);
13 | currentState = STATE_WAITING;
14 | }
15 |
16 | public void fire() {
17 | put(EVENT_FIRE);
18 | }
19 |
20 | protected void processEvent(String event) throws InterruptedException {
21 | System.out.println("Got " + event + " event");
22 | if (currentState == STATE_WAITING) {
23 | if (event == EVENT_FIRE) {
24 | currentState = STATE_RUNNING;
25 | audio.open();
26 | audio.start();
27 | }
28 | } else if (currentState == STATE_RUNNING) {
29 | if (event == EVENT_FIRE) {
30 | audio.restart();
31 | }
32 | if (event == EVENT_DONE) {
33 | currentState = STATE_WAITING;
34 | audio.close();
35 | }
36 | }
37 | }
38 |
39 | @Override
40 | protected void onAudioFinished() {
41 | put(EVENT_DONE);
42 | }
43 | }
--------------------------------------------------------------------------------
/CH13/src/javagames/sound/SoundEvent.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | import java.util.concurrent.BlockingQueue;
4 | import java.util.concurrent.LinkedBlockingQueue;
5 |
6 | public class SoundEvent implements Runnable {
7 |
8 | public static final String SHUT_DOWN = "shutdown";
9 | protected AudioStream audio;
10 | protected BlockingQueue queue;
11 | private Thread consumer;
12 |
13 | public SoundEvent(AudioStream audio) {
14 | this.audio = audio;
15 | }
16 |
17 | public void initialize() {
18 | audio.addListener(getListener());
19 | queue = new LinkedBlockingQueue();
20 | consumer = new Thread(this);
21 | consumer.start();
22 | }
23 |
24 | public void put(String event) {
25 | try {
26 | queue.put(event);
27 | } catch (InterruptedException e) {
28 | }
29 | }
30 |
31 | public void shutDown() {
32 | Thread temp = consumer;
33 | consumer = null;
34 | try {
35 | // send event to wake up consumer
36 | // and/or stop.
37 | queue.put(SHUT_DOWN);
38 | temp.join(10000L);
39 | System.out.println("Event shutdown!!!");
40 | } catch (InterruptedException ex) {
41 | }
42 | }
43 |
44 | @Override
45 | public void run() {
46 | while (Thread.currentThread() == consumer) {
47 | try {
48 | processEvent(queue.take());
49 | } catch (InterruptedException e) {
50 | }
51 | }
52 | }
53 |
54 | protected void processEvent(String event) throws InterruptedException {
55 | }
56 |
57 | protected void onAudioFinished() {
58 | }
59 |
60 | private BlockingAudioListener getListener() {
61 | return new BlockingAudioListener() {
62 | @Override
63 | public void audioFinished() {
64 | onAudioFinished();
65 | }
66 | };
67 | }
68 | }
--------------------------------------------------------------------------------
/CH13/src/javagames/sound/SoundException.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public class SoundException extends RuntimeException {
4 |
5 | public SoundException(String message) {
6 | super(message);
7 | }
8 |
9 | public SoundException(String message, Throwable cause) {
10 | super(message, cause);
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/CH13/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH13/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH13/src/javagames/util/ResourceLoader.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.FileNotFoundException;
5 | import java.io.InputStream;
6 |
7 | public class ResourceLoader {
8 |
9 | public static InputStream load(Class> clazz, String filePath,
10 | String resPath) {
11 | // try the resource first
12 | InputStream in = null;
13 | if (!(resPath == null || resPath.isEmpty())) {
14 | in = clazz.getResourceAsStream(resPath);
15 | }
16 | if (in == null) {
17 | // try the file path
18 | try {
19 | in = new FileInputStream(filePath);
20 | } catch (FileNotFoundException e) {
21 | e.printStackTrace();
22 | }
23 | }
24 | return in;
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/CH13/src/javagames/util/SafeKeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.event.KeyEvent;
4 | import java.awt.event.KeyListener;
5 | import java.util.LinkedList;
6 |
7 | public class SafeKeyboardInput implements KeyListener {
8 |
9 | enum EventType {
10 | PRESSED, RELEASED, TYPED;
11 | }
12 |
13 | class Event {
14 | KeyEvent event;
15 | EventType type;
16 |
17 | public Event(KeyEvent event, EventType type) {
18 | this.event = event;
19 | this.type = type;
20 | }
21 | }
22 |
23 | private LinkedList eventThread = new LinkedList();
24 | private LinkedList gameThread = new LinkedList();
25 | private Event event = null;
26 | private int[] polled;
27 |
28 | public SafeKeyboardInput() {
29 | polled = new int[256];
30 | }
31 |
32 | public boolean keyDown(int keyCode) {
33 | return keyCode == event.event.getKeyCode() && polled[keyCode] > 0;
34 | }
35 |
36 | public boolean keyDownOnce(int keyCode) {
37 | return keyCode == event.event.getKeyCode() && polled[keyCode] == 1;
38 | }
39 |
40 | public boolean processEvent() {
41 | event = gameThread.poll();
42 | if (event != null) {
43 | int keyCode = event.event.getKeyCode();
44 | if (keyCode >= 0 && keyCode < polled.length) {
45 | if (event.type == EventType.PRESSED) {
46 | polled[keyCode]++;
47 | } else if (event.type == EventType.RELEASED) {
48 | polled[keyCode] = 0;
49 | }
50 | }
51 | }
52 | return event != null;
53 | }
54 |
55 | public Character getKeyTyped() {
56 | if (event.type != EventType.TYPED) {
57 | return null;
58 | } else {
59 | return event.event.getKeyChar();
60 | }
61 | }
62 |
63 | public synchronized void poll() {
64 | LinkedList swap = eventThread;
65 | eventThread = gameThread;
66 | gameThread = swap;
67 | }
68 |
69 | public synchronized void keyPressed(KeyEvent e) {
70 | eventThread.add(new Event(e, EventType.PRESSED));
71 | }
72 |
73 | public synchronized void keyReleased(KeyEvent e) {
74 | eventThread.add(new Event(e, EventType.RELEASED));
75 | }
76 |
77 | public synchronized void keyTyped(KeyEvent e) {
78 | eventThread.add(new Event(e, EventType.TYPED));
79 | }
80 | }
--------------------------------------------------------------------------------
/CH13/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH13/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 15JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 | Notes:
17 | Win7 - the pan no longer seems to work?
--------------------------------------------------------------------------------
/CH14/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH14/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH14
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 |
--------------------------------------------------------------------------------
/CH14/custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Extending the common.xml
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
19 |
20 |
--------------------------------------------------------------------------------
/CH14/hello-world.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This is a simple Hello World script
5 |
6 |
7 | Hello World!
8 |
9 |
--------------------------------------------------------------------------------
/CH14/lib/custom-build.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH14/lib/custom-build.jar
--------------------------------------------------------------------------------
/CH14/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 14JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH15/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH15/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH15
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 |
--------------------------------------------------------------------------------
/CH15/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH15/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH15/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH15/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH16/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH16/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH16
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 |
--------------------------------------------------------------------------------
/CH16/asdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CH16/res/assets/images/large0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH16/res/assets/images/large0.png
--------------------------------------------------------------------------------
/CH16/src/javagames/tools/ExampleFileFilter.java:
--------------------------------------------------------------------------------
1 | package javagames.tools;
2 |
3 | import java.io.File;
4 | import javax.swing.filechooser.FileFilter;
5 |
6 | public class ExampleFileFilter extends FileFilter {
7 |
8 | private String description;
9 | private String[] filters;
10 |
11 | public ExampleFileFilter(String description, String[] filters) {
12 | this.description = description;
13 | this.filters = filters;
14 | }
15 |
16 | @Override
17 | public boolean accept(File f) {
18 | if (f.isDirectory()) {
19 | return true;
20 | }
21 | String extension = getExtension(f);
22 | if (extension != null) {
23 | for (String filter : filters) {
24 | if (extension.equalsIgnoreCase(filter)) {
25 | return true;
26 | }
27 | }
28 | }
29 | return false;
30 | }
31 |
32 | @Override
33 | public String getDescription() {
34 | return description;
35 | }
36 |
37 | public String getExtension(File f) {
38 | String ext = null;
39 | String s = f.getName();
40 | int i = s.lastIndexOf('.');
41 | if (i > 0 && i < s.length() - 1) {
42 | ext = s.substring(i + 1).toLowerCase();
43 | }
44 | return ext;
45 | }
46 | }
--------------------------------------------------------------------------------
/CH16/src/javagames/tools/SpriteExample.java:
--------------------------------------------------------------------------------
1 | package javagames.tools;
2 |
3 | import java.awt.*;
4 | import java.awt.image.BufferedImage;
5 | import java.io.InputStream;
6 | import javagames.util.*;
7 | import javax.imageio.ImageIO;
8 |
9 | public class SpriteExample extends WindowFramework {
10 |
11 | private Sprite sprite;
12 | private Vector2f pos;
13 | private Vector2f vel;
14 | private float rot;
15 | private float rotDelta;
16 |
17 | public SpriteExample() {
18 | appTitle = "Sprite Example";
19 | pos = new Vector2f();
20 | vel = new Vector2f(0.25f, -0.3f);
21 | rotDelta = (float) Math.toRadians(90.0);
22 | }
23 |
24 | @Override
25 | protected void initialize() {
26 | super.initialize();
27 | InputStream in = ResourceLoader.load(SpriteExample.class,
28 | "res/assets/images/large0.png", "/images/large0.png");
29 | try {
30 | BufferedImage image = ImageIO.read(in);
31 | Vector2f topLeft = new Vector2f(-0.25f, 0.25f);
32 | Vector2f bottomRight = new Vector2f(0.25f, -0.25f);
33 | sprite = new Sprite(image, topLeft, bottomRight);
34 | } catch (Exception e) {
35 | e.printStackTrace();
36 | }
37 | }
38 |
39 | @Override
40 | protected void updateObjects(float delta) {
41 | super.updateObjects(delta);
42 | pos = pos.add(vel.mul(delta));
43 | if (pos.x < -appWorldWidth / 2.0f) {
44 | pos.x = -appWorldWidth / 2.0f;
45 | vel.x = -vel.x;
46 | } else if (pos.x > appWorldWidth / 2.0f) {
47 | pos.x = appWorldWidth / 2.0f;
48 | vel.x = -vel.x;
49 | }
50 | if (pos.y < -appWorldHeight / 2.0f) {
51 | pos.y = -appWorldHeight / 2.0f;
52 | vel.y = -vel.y;
53 | } else if (pos.y > appWorldHeight / 2.0f) {
54 | pos.y = appWorldHeight / 2.0f;
55 | vel.y = -vel.y;
56 | }
57 | rot += rotDelta * delta;
58 | }
59 |
60 | @Override
61 | protected void render(Graphics g) {
62 | super.render(g);
63 | g.setColor(Color.GREEN);
64 | g.drawRect(0, 0, getScreenWidth() - 1, getScreenHeight() - 1);
65 | sprite.render((Graphics2D) g, getViewportTransform(), pos, rot);
66 | }
67 |
68 | public static void main(String[] args) {
69 | launchApp(new SpriteExample());
70 | }
71 | }
--------------------------------------------------------------------------------
/CH16/src/javagames/tools/TestParticle.java:
--------------------------------------------------------------------------------
1 | package javagames.tools;
2 |
3 | import java.awt.Color;
4 | import java.awt.Graphics2D;
5 | import javagames.util.Matrix3x3f;
6 | import javagames.util.Vector2f;
7 |
8 | public class TestParticle {
9 |
10 | private Vector2f pos;
11 | private Vector2f curPos;
12 | private Vector2f vel;
13 | private Vector2f curVel;
14 | private Color color;
15 | private float lifeSpan;
16 | private float time;
17 | private float radius;
18 |
19 | public TestParticle() {
20 |
21 | }
22 |
23 | public void setPosition(Vector2f pos) {
24 | this.pos = pos;
25 | }
26 |
27 | public void setRadius(float radius) {
28 | this.radius = radius;
29 | }
30 |
31 | public void setVector(float angle, float r) {
32 | vel = Vector2f.polar(angle, r);
33 | }
34 |
35 | public void setColor(Color color) {
36 | this.color = color;
37 | }
38 |
39 | public void setLifeSpan(float lifeSpan) {
40 | this.lifeSpan = lifeSpan;
41 | }
42 |
43 | public void update(float delta) {
44 | time += delta;
45 | curVel = vel.mul(time);
46 | curPos = pos.add(curVel);
47 | }
48 |
49 | public void draw(Graphics2D g, Matrix3x3f view) {
50 | g.setColor(color);
51 | Vector2f topLeft = new Vector2f(curPos.x - radius, curPos.y + radius);
52 | topLeft = view.mul(topLeft);
53 | Vector2f bottomRight = new Vector2f(curPos.x + radius, curPos.y
54 | - radius);
55 | bottomRight = view.mul(bottomRight);
56 | int circleX = (int) topLeft.x;
57 | int circleY = (int) topLeft.y;
58 | int circleWidth = (int) (bottomRight.x - topLeft.x);
59 | int circleHeight = (int) (bottomRight.y - topLeft.y);
60 | g.fillOval(circleX, circleY, circleWidth, circleHeight);
61 | }
62 |
63 | public boolean hasDied() {
64 | return time > lifeSpan;
65 | }
66 | }
--------------------------------------------------------------------------------
/CH16/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH16/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH16/src/javagames/util/ResourceLoader.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.FileNotFoundException;
5 | import java.io.InputStream;
6 |
7 | public class ResourceLoader {
8 |
9 | public static InputStream load(Class> clazz, String filePath,
10 | String resPath) {
11 | // try the resource first
12 | InputStream in = null;
13 | if (!(resPath == null || resPath.isEmpty())) {
14 | in = clazz.getResourceAsStream(resPath);
15 | }
16 | if (in == null) {
17 | // try the file path
18 | try {
19 | in = new FileInputStream(filePath);
20 | } catch (FileNotFoundException e) {
21 | e.printStackTrace();
22 | }
23 | }
24 | return in;
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/CH16/src/javagames/util/Sprite.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.*;
4 | import java.awt.geom.AffineTransform;
5 | import java.awt.image.BufferedImage;
6 |
7 | public class Sprite {
8 |
9 | private BufferedImage image;
10 | private BufferedImage scaled;
11 | private Vector2f topLeft;
12 | private Vector2f bottomRight;
13 |
14 | public Sprite(BufferedImage image, Vector2f topLeft, Vector2f bottomRight) {
15 | this.image = image;
16 | this.topLeft = topLeft;
17 | this.bottomRight = bottomRight;
18 | }
19 |
20 | public void render(Graphics2D g, Matrix3x3f view) {
21 | render(g, view, new Vector2f(), 0.0f);
22 | }
23 |
24 | public void render(Graphics2D g, Matrix3x3f view, Vector2f position, float angle) {
25 | if (image != null) {
26 | Vector2f tl = view.mul(topLeft);
27 | Vector2f br = view.mul(bottomRight);
28 | int width = (int) Math.abs(br.x - tl.x);
29 | int height = (int) Math.abs(br.y - tl.y);
30 | if (scaled == null || width != scaled.getWidth() ||
31 | height != scaled.getHeight()) {
32 | scaled = Utility.scaleImage(image, width, height);
33 | }
34 | g.setRenderingHint(
35 | RenderingHints.KEY_INTERPOLATION,
36 | RenderingHints.VALUE_INTERPOLATION_BILINEAR
37 | );
38 | Vector2f screen = view.mul(position);
39 | AffineTransform transform =
40 | AffineTransform.getTranslateInstance(screen.x, screen.y);
41 | transform.rotate(-angle);
42 | transform.translate(-scaled.getWidth() / 2, -scaled.getHeight() / 2);
43 | g.drawImage(scaled, transform, null);
44 | }
45 | }
46 |
47 | public void scaleImage(Matrix3x3f view) {
48 | Vector2f screenTopLeft = view.mul(topLeft);
49 | Vector2f screenBottomRight = view.mul(bottomRight);
50 | int scaledWidth = (int) Math.abs(screenBottomRight.x - screenTopLeft.x);
51 | int scaledHeight = (int) Math.abs(screenBottomRight.y - screenTopLeft.y);
52 | scaled = Utility.scaleImage(image, scaledWidth, scaledHeight);
53 | }
54 | }
--------------------------------------------------------------------------------
/CH16/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH16/src/javagames/util/WindowFramework.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.*;
4 | import java.awt.event.*;
5 |
6 | public class WindowFramework extends GameFramework {
7 |
8 | private Canvas canvas;
9 |
10 | @Override
11 | protected void createFramework() {
12 | canvas = new Canvas();
13 | canvas.setBackground(appBackground);
14 | canvas.setIgnoreRepaint(true);
15 | getContentPane().add(canvas);
16 | setLocationByPlatform(true);
17 | if (appMaintainRatio) {
18 | getContentPane().setBackground(appBorder);
19 | setSize(appWidth, appHeight);
20 | setLayout(null);
21 | getContentPane().addComponentListener(new ComponentAdapter() {
22 | public void componentResized(ComponentEvent e) {
23 | onComponentResized(e);
24 | }
25 | });
26 | } else {
27 | canvas.setSize(appWidth, appHeight);
28 | pack();
29 | }
30 | setTitle(appTitle);
31 | setupInput(canvas);
32 | setVisible(true);
33 | createBufferStrategy(canvas);
34 | canvas.requestFocus();
35 | }
36 |
37 | protected void onComponentResized(ComponentEvent e) {
38 | Dimension size = getContentPane().getSize();
39 | setupViewport(size.width, size.height);
40 | canvas.setLocation(vx, vy);
41 | canvas.setSize(vw, vh);
42 | }
43 |
44 | public int getScreenWidth() {
45 | return canvas.getWidth();
46 | }
47 |
48 | public int getScreenHeight() {
49 | return canvas.getHeight();
50 | }
51 |
52 | @Override
53 | protected void renderFrame(Graphics g) {
54 | g.clearRect(0, 0, getScreenWidth(), getScreenHeight());
55 | render(g);
56 | }
57 | }
--------------------------------------------------------------------------------
/CH16/src/javagames/util/XMLUtility.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.io.*;
4 | import java.util.*;
5 | import javax.xml.parsers.*;
6 | import org.w3c.dom.*;
7 | import org.xml.sax.*;
8 |
9 | public class XMLUtility {
10 |
11 | public static Document parseDocument(InputStream inputStream)
12 | throws ParserConfigurationException, SAXException, IOException {
13 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
14 | DocumentBuilder builder = factory.newDocumentBuilder();
15 | Document document = builder.parse(new InputSource(inputStream));
16 | return document;
17 | }
18 |
19 | public static Document parseDocument(Reader reader)
20 | throws ParserConfigurationException, SAXException, IOException {
21 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
22 | DocumentBuilder builder = factory.newDocumentBuilder();
23 | Document document = builder.parse(new InputSource(reader));
24 | return document;
25 | }
26 |
27 | public static List getAllElements(Element element, String tagName) {
28 | ArrayList elements = new ArrayList();
29 | NodeList nodes = element.getElementsByTagName(tagName);
30 | for (int i = 0; i < nodes.getLength(); i++) {
31 | elements.add((Element) nodes.item(i));
32 | }
33 | return elements;
34 | }
35 |
36 | public static List getElements(Element element, String tagName) {
37 | ArrayList elements = new ArrayList();
38 | NodeList children = element.getChildNodes();
39 | for (int i = 0; i < children.getLength(); i++) {
40 | Node node = children.item(i);
41 | if (node.getNodeType() == Node.ELEMENT_NODE) {
42 | String nodeName = node.getNodeName();
43 | if (nodeName != null && nodeName.equals(tagName)) {
44 | elements.add((Element) node);
45 | }
46 | }
47 | }
48 | return elements;
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/CH16/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 14JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/CH17/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH17/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | CH17
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 |
--------------------------------------------------------------------------------
/CH17/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Building Space Rocks
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/CH17/lib/complete-game.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/lib/complete-game.jar
--------------------------------------------------------------------------------
/CH17/res/assets/images/Ship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/Ship.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/ShipGlow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/ShipGlow.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/large0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/large0.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/large1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/large1.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/large2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/large2.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/medium0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/medium0.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/medium1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/medium1.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/medium2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/medium2.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/small0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/small0.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/small1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/small1.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/small2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/small2.png
--------------------------------------------------------------------------------
/CH17/res/assets/images/space_background_600x600.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/images/space_background_600x600.png
--------------------------------------------------------------------------------
/CH17/res/assets/sound/AMBIENCE_alien.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/sound/AMBIENCE_alien.wav
--------------------------------------------------------------------------------
/CH17/res/assets/sound/DRONE9RE.WAV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/sound/DRONE9RE.WAV
--------------------------------------------------------------------------------
/CH17/res/assets/sound/EXPLOSION_large_01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/sound/EXPLOSION_large_01.wav
--------------------------------------------------------------------------------
/CH17/res/assets/sound/EXPLOSION_large_02.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/sound/EXPLOSION_large_02.wav
--------------------------------------------------------------------------------
/CH17/res/assets/sound/EXPLOSION_large_03.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/sound/EXPLOSION_large_03.wav
--------------------------------------------------------------------------------
/CH17/res/assets/sound/EXPLOSION_large_04.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/sound/EXPLOSION_large_04.wav
--------------------------------------------------------------------------------
/CH17/res/assets/sound/EXPLOSION_large_05.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/sound/EXPLOSION_large_05.wav
--------------------------------------------------------------------------------
/CH17/res/assets/sound/WEAPON_scifi_fire_02.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/res/assets/sound/WEAPON_scifi_fire_02.wav
--------------------------------------------------------------------------------
/CH17/res/assets/xml/ship.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/admin/Acme.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.admin;
2 |
3 | import java.awt.*;
4 | import javagames.completegame.CompleteGame;
5 | import javagames.completegame.object.Ship;
6 | import javagames.util.*;
7 |
8 | public class Acme {
9 |
10 | private CompleteGame app;
11 | private Ship ship;
12 |
13 | public Acme(CompleteGame app) {
14 | this.app = app;
15 | }
16 |
17 | public void setShip(Ship ship) {
18 | this.ship = ship;
19 | }
20 |
21 | public void drawScore(Graphics2D g, int score) {
22 | g.setRenderingHint(
23 | RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON
24 | );
25 | String toShow = "" + score;
26 | while (toShow.length() < 6) {
27 | toShow = "0" + toShow;
28 | }
29 | g.setFont(new Font("Arial", Font.BOLD, 20));
30 | g.setColor(Color.GREEN);
31 | Utility.drawCenteredString(g, app.getScreenWidth(), 0, toShow);
32 | }
33 |
34 | public void drawLives(Graphics2D g, Matrix3x3f view, int lives) {
35 | float w = ship.getWidth();
36 | float h = ship.getHeight();
37 | float x = -0.95f + w;
38 | float y = 1.0f - h / 2.0f;
39 | for (int i = 0; i < lives; ++i) {
40 | x += w * i;
41 | ship.setAngle((float) Math.toRadians(90));
42 | ship.setPotition(new Vector2f(x, y));
43 | ship.update(0.0f);
44 | ship.draw(g, view);
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/admin/GameConstants.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.admin;
2 |
3 | import java.awt.Color;
4 |
5 | public class GameConstants {
6 |
7 | public static final Color APP_BORDER = Color.DARK_GRAY;
8 | public static final int APP_WIDTH = 1680;
9 | public static final int APP_HEIGHT = 1050;
10 | public static final long APP_SLEEP = 10L;
11 | public static final String APP_TITLE = "Complete Game";
12 | public static final float WORLD_WIDTH = 2.0f;
13 | public static final float WORLD_HEIGHT = 2.0f;
14 | public static final float BORDER_SCALE = 0.95f;
15 | public static final boolean DISABLE_CURSOR = true;
16 | public static final boolean MAINTAIN_RATIO = true;
17 |
18 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/admin/HighScoreMgr.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TimothyWrightSoftware/Fundamental-2D-Game-Programming-With-Java/d99c991515e72fde58098b9c7de5201d4ad8a639/CH17/src/javagames/completegame/admin/HighScoreMgr.java
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/admin/QuickLooper.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.admin;
2 |
3 | import javagames.sound.AudioStream;
4 | import javagames.sound.SoundEvent;
5 |
6 | public class QuickLooper extends SoundEvent {
7 |
8 | public static final String STATE_CLOSED = "closed";
9 | public static final String STATE_WAITING = "waiting";
10 | public static final String STATE_RUNNING = "running";
11 | public static final String EVENT_FIRE = "fire";
12 | public static final String EVENT_DONE = "done";
13 | public static final String EVENT_OPEN = "open";
14 | public static final String EVENT_CLOSE = "close";
15 | private String currentState;
16 |
17 | public QuickLooper(AudioStream audio) {
18 | super(audio);
19 | currentState = STATE_CLOSED;
20 | }
21 |
22 | public void open() {
23 | put(EVENT_OPEN);
24 | }
25 |
26 | public void close() {
27 | put(EVENT_CLOSE);
28 | }
29 |
30 | public void fire() {
31 | put(EVENT_FIRE);
32 | }
33 |
34 | public void done() {
35 | put(EVENT_DONE);
36 | }
37 |
38 | protected void processEvent(String event) throws InterruptedException {
39 | while (queue.peek() == EVENT_DONE || queue.peek() == EVENT_FIRE) {
40 | event = queue.take();
41 | }
42 | if (currentState == STATE_CLOSED) {
43 | if (event == EVENT_OPEN) {
44 | audio.open();
45 | currentState = STATE_WAITING;
46 | }
47 | } else if (currentState == STATE_WAITING) {
48 | if (event == EVENT_CLOSE) {
49 | audio.close();
50 | currentState = STATE_CLOSED;
51 | }
52 | if (event == EVENT_FIRE) {
53 | audio.loop(AudioStream.LOOP_CONTINUOUSLY);
54 | currentState = STATE_RUNNING;
55 | }
56 | } else if (currentState == STATE_RUNNING) {
57 | if (event == EVENT_CLOSE) {
58 | audio.stop();
59 | audio.close();
60 | currentState = STATE_CLOSED;
61 | }
62 | if (event == EVENT_DONE) {
63 | audio.stop();
64 | currentState = STATE_WAITING;
65 | }
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/admin/QuickRestart.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.admin;
2 |
3 | import javagames.sound.AudioStream;
4 | import javagames.sound.SoundEvent;
5 |
6 | public class QuickRestart extends SoundEvent {
7 |
8 | public static final String STATE_CLOSED = "closed";
9 | public static final String STATE_WAITING = "waiting";
10 | public static final String STATE_RUNNING = "running";
11 | public static final String EVENT_FIRE = "fire";
12 | public static final String EVENT_DONE = "done";
13 | public static final String EVENT_OPEN = "open";
14 | public static final String EVENT_CLOSE = "close";
15 | private String currentState;
16 |
17 | public QuickRestart(AudioStream stream) {
18 | super(stream);
19 | currentState = STATE_CLOSED;
20 | }
21 |
22 | public void open() {
23 | put(EVENT_OPEN);
24 | }
25 |
26 | public void close() {
27 | put(EVENT_CLOSE);
28 | }
29 |
30 | public void fire() {
31 | put(EVENT_FIRE);
32 | }
33 |
34 | protected void processEvent(String event) throws InterruptedException {
35 | System.out.println("Quick Restart Got: " + event);
36 | System.out.println("Current State: " + currentState);
37 | if (currentState == STATE_CLOSED) {
38 | if (event == EVENT_OPEN) {
39 | audio.open();
40 | currentState = STATE_WAITING;
41 | }
42 | } else if (currentState == STATE_WAITING) {
43 | if (event == EVENT_CLOSE) {
44 | audio.close();
45 | currentState = STATE_CLOSED;
46 | }
47 | if (event == EVENT_FIRE) {
48 | audio.start();
49 | currentState = STATE_RUNNING;
50 | }
51 | } else if (currentState == STATE_RUNNING) {
52 | if (event == EVENT_FIRE) {
53 | audio.restart();
54 | }
55 | if (event == EVENT_CLOSE) {
56 | audio.stop();
57 | audio.close();
58 | currentState = STATE_CLOSED;
59 | }
60 | if (event == EVENT_DONE) {
61 | currentState = STATE_WAITING;
62 | }
63 | }
64 | System.out.println("New State: " + currentState);
65 | }
66 |
67 | @Override
68 | protected void onAudioFinished() {
69 | put(EVENT_DONE);
70 | }
71 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/object/AsteroidExplosion.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.object;
2 |
3 | import java.awt.*;
4 | import java.util.*;
5 | import javagames.util.*;
6 |
7 | public class AsteroidExplosion {
8 |
9 | private static final int MAX_PARTICLES = 150;
10 | private Vector particles;
11 | private Random random = new Random();
12 | private Vector2f pos;
13 |
14 | public AsteroidExplosion(Vector2f pos) {
15 | this.pos = pos;
16 | createParticles();
17 | }
18 |
19 | private void createParticles() {
20 | particles = new Vector();
21 | for (int i = 0; i < MAX_PARTICLES; ++i) {
22 | particles.add(createRandomParticle());
23 | }
24 | }
25 |
26 | private Particle createRandomParticle() {
27 | Particle p = new Particle();
28 | p.setPosition(pos);
29 | p.setRadius(0.002f + random.nextFloat() * 0.004f);
30 | p.setLifeSpan(random.nextFloat() * 1.0f);
31 | switch (random.nextInt(4)) {
32 | case 0:
33 | p.setColor(Color.WHITE);
34 | break;
35 | case 1:
36 | p.setColor(Color.GRAY);
37 | break;
38 | case 2:
39 | p.setColor(Color.LIGHT_GRAY);
40 | break;
41 | case 3:
42 | p.setColor(Color.DARK_GRAY);
43 | break;
44 | }
45 | float angle = (float) Math.toRadians(random.nextInt(360));
46 | float velocity = random.nextFloat() * 2.0f;
47 | p.setVector(angle, velocity);
48 | return p;
49 | }
50 |
51 | public void update(float time) {
52 | Iterator it = particles.iterator();
53 | while (it.hasNext()) {
54 | Particle p = it.next();
55 | p.update(time);
56 | if (p.hasDied()) {
57 | it.remove();
58 | }
59 | }
60 | }
61 |
62 | public void render(Graphics2D g, Matrix3x3f view) {
63 | for (Particle p : particles) {
64 | p.draw(g, view);
65 | }
66 | }
67 |
68 | public boolean isFinished() {
69 | return particles.size() == 0;
70 | }
71 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/object/Bullet.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.object;
2 |
3 | import java.awt.Color;
4 | import java.awt.Graphics2D;
5 | import javagames.util.*;
6 |
7 | public class Bullet {
8 |
9 | private Vector2f velocity;
10 | private Vector2f position;
11 | private Color color;
12 | private float radius;
13 |
14 | public Bullet(Vector2f position, float angle) {
15 | this.position = position;
16 | velocity = Vector2f.polar(angle, 1.0f);
17 | radius = 0.006f;
18 | color = Color.GREEN;
19 | }
20 |
21 | public Vector2f getPosition() {
22 | return position;
23 | }
24 |
25 | public void draw(Graphics2D g, Matrix3x3f view) {
26 | g.setColor(color);
27 | Vector2f topLeft = new Vector2f(position.x - radius, position.y
28 | + radius);
29 | topLeft = view.mul(topLeft);
30 | Vector2f bottomRight = new Vector2f(position.x + radius, position.y
31 | - radius);
32 | bottomRight = view.mul(bottomRight);
33 | int circleX = (int) topLeft.x;
34 | int circleY = (int) topLeft.y;
35 | int circleWidth = (int) (bottomRight.x - topLeft.x);
36 | int circleHeight = (int) (bottomRight.y - topLeft.y);
37 | g.fillOval(circleX, circleY, circleWidth, circleHeight);
38 | }
39 |
40 | public void update(float time) {
41 | position = position.add(velocity.mul(time));
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/object/Particle.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.object;
2 |
3 | import java.awt.Color;
4 | import java.awt.Graphics2D;
5 | import javagames.util.Matrix3x3f;
6 | import javagames.util.Vector2f;
7 |
8 | public class Particle {
9 |
10 | private Vector2f pos;
11 | private Vector2f curPos;
12 | private Vector2f vel;
13 | private Vector2f curVel;
14 | private Color color;
15 | private float lifeSpan;
16 | private float time;
17 | private float radius;
18 |
19 | public Particle() {
20 | }
21 |
22 | public void setPosition(Vector2f pos) {
23 | this.pos = pos;
24 | }
25 |
26 | public void setRadius(float radius) {
27 | this.radius = radius;
28 | }
29 |
30 | public void setVector(float angle, float r) {
31 | vel = Vector2f.polar(angle, r);
32 | }
33 |
34 | public void setColor(Color color) {
35 | this.color = color;
36 | }
37 |
38 | public void setLifeSpan(float lifeSpan) {
39 | this.lifeSpan = lifeSpan;
40 | }
41 |
42 | public void update(float delta) {
43 | time += delta;
44 | curVel = vel.mul(time);
45 | curPos = pos.add(curVel);
46 | }
47 |
48 | public void draw(Graphics2D g, Matrix3x3f view) {
49 | g.setColor(color);
50 | Vector2f topLeft = new Vector2f(curPos.x - radius, curPos.y + radius);
51 | topLeft = view.mul(topLeft);
52 | Vector2f bottomRight = new Vector2f(curPos.x + radius, curPos.y - radius);
53 | bottomRight = view.mul(bottomRight);
54 | int circleX = (int) topLeft.x;
55 | int circleY = (int) topLeft.y;
56 | int circleWidth = (int) (bottomRight.x - topLeft.x);
57 | int circleHeight = (int) (bottomRight.y - topLeft.y);
58 | g.fillOval(circleX, circleY, circleWidth, circleHeight);
59 | }
60 |
61 | public boolean hasDied() {
62 | return time > lifeSpan;
63 | }
64 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/object/ShipExplosion.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.object;
2 |
3 | import java.awt.*;
4 | import java.util.*;
5 | import javagames.util.*;
6 |
7 | public class ShipExplosion {
8 |
9 | private static final int MAX_PARTICLES = 150;
10 | private static final int MAX_RINGS = 5;
11 | private Vector particles;
12 | private Random random = new Random();
13 | private Vector2f pos;
14 | private Vector colors;
15 |
16 | public ShipExplosion(Vector2f pos) {
17 | this.pos = pos;
18 | createColors();
19 | createParticles();
20 | }
21 |
22 | private void createColors() {
23 | colors = new Vector();
24 | colors.add(Color.WHITE);
25 | colors.add(Color.RED);
26 | colors.add(Color.YELLOW);
27 | colors.add(Color.ORANGE);
28 | colors.add(Color.PINK);
29 | }
30 |
31 | private void createParticles() {
32 | particles = new Vector();
33 | for (int ring = 0; ring < MAX_RINGS; ++ring) {
34 | float velocity = 0.25f + random.nextFloat() * 1.0f;
35 | float lifeSpan = random.nextFloat() * 1.0f;
36 | float radius = 0.003f + random.nextFloat() * 0.003f;
37 | for (int i = 0; i < MAX_PARTICLES; ++i) {
38 | Particle p = new Particle();
39 | p.setPosition(pos);
40 | p.setRadius(radius);
41 | p.setLifeSpan(lifeSpan);
42 | p.setColor(colors.get(random.nextInt(colors.size())));
43 | float angle = (float) Math.toRadians(random.nextInt(360));
44 | p.setVector(angle, velocity);
45 | particles.add(p);
46 | }
47 | }
48 | }
49 |
50 | public void update(float time) {
51 | Iterator it = particles.iterator();
52 | while (it.hasNext()) {
53 | Particle p = it.next();
54 | p.update(time);
55 | if (p.hasDied())
56 | it.remove();
57 | }
58 | }
59 |
60 | public void render(Graphics2D g, Matrix3x3f view) {
61 | for (Particle p : particles) {
62 | p.draw(g, view);
63 | }
64 | }
65 |
66 | public boolean isFinished() {
67 | return particles.size() == 0;
68 | }
69 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/object/ShipFactory.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.object;
2 |
3 | import java.awt.image.BufferedImage;
4 | import java.io.InputStream;
5 | import java.util.Vector;
6 | import javax.imageio.ImageIO;
7 | import javagames.util.*;
8 | import org.w3c.dom.Element;
9 |
10 | public class ShipFactory {
11 |
12 | private PolygonWrapper wrapper;
13 | private Vector2f[] polygon;
14 | private Sprite shipRegular;
15 | private Sprite shipGlow;
16 |
17 | public ShipFactory(PolygonWrapper wrapper) {
18 | this.wrapper = wrapper;
19 | }
20 |
21 | public void loadFactory(Element xml) {
22 | Vector points = new Vector();
23 | String spritePath = xml.getAttribute("sprite");
24 | String glowPath = xml.getAttribute("glow");
25 | String bounds = xml.getAttribute("bounds");
26 | for (Element coords : XMLUtility.getAllElements(xml, "coord")) {
27 | float x = Float.parseFloat(coords.getAttribute("x"));
28 | float y = Float.parseFloat(coords.getAttribute("y"));
29 | points.add(new Vector2f(x, y));
30 | }
31 | polygon = points.toArray(new Vector2f[0]);
32 | float bound = Float.parseFloat(bounds);
33 | Vector2f topLeft = new Vector2f(-bound / 2.0f, bound / 2.0f);
34 | Vector2f bottomRight = new Vector2f(bound / 2.0f, -bound / 2.0f);
35 | BufferedImage image = loadSprite(spritePath);
36 | shipRegular = new Sprite(image, topLeft, bottomRight);
37 | image = loadSprite(glowPath);
38 | shipGlow = new Sprite(image, topLeft, bottomRight);
39 | }
40 |
41 | public Ship createShip() {
42 | Ship ship = new Ship(wrapper);
43 | ship.setAlive(true);
44 | ship.setPolygon(polygon);
45 | ship.setGlowSprite(shipGlow);
46 | ship.setShipSprite(shipRegular);
47 | return ship;
48 | }
49 |
50 | private BufferedImage loadSprite(String path) {
51 | InputStream stream = ResourceLoader.load(
52 | ShipFactory.class, "res/assets/images/" + path, "/images/" + path
53 | );
54 | try {
55 | return ImageIO.read(stream);
56 | } catch (Exception e) {
57 | e.printStackTrace();
58 | }
59 | return null;
60 | }
61 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/state/GameInformationState.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.state;
2 |
3 | import java.awt.*;
4 | import javagames.util.Matrix3x3f;
5 | import javagames.util.Utility;
6 |
7 | public class GameInformationState extends AttractState {
8 |
9 | private static final String[] gameInfo = {
10 | "Space Rocks - version 2.0",
11 | "Programmed by: Tim Wright",
12 | "",
13 | "Special thanks to:",
14 | "Michaela Wright",
15 | "Destiny Tamboer",
16 | "Jimmi Wright",
17 | };
18 |
19 | @Override
20 | protected AttractState getState() {
21 | return new PressSpaceToPlay();
22 | }
23 |
24 | @Override
25 | public void render(Graphics2D g, Matrix3x3f view) {
26 | super.render(g, view);
27 | g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
28 | RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
29 | g.setFont(new Font("Arial", Font.PLAIN, 20));
30 | g.setColor(Color.GREEN);
31 | Utility.drawCenteredString(g, app.getScreenWidth(),
32 | app.getScreenHeight() / 3, gameInfo);
33 | }
34 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/state/GameOver.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.state;
2 |
3 | import java.awt.Graphics2D;
4 | import java.util.List;
5 | import javagames.completegame.object.*;
6 | import javagames.util.Matrix3x3f;
7 | import javagames.util.Utility;
8 |
9 | public class GameOver extends AttractState {
10 |
11 | GameState state;
12 |
13 | public GameOver(List asteroids, GameState state) {
14 | super(asteroids);
15 | this.state = state;
16 | }
17 |
18 | @Override
19 | protected float getWaitTime() {
20 | return 3.0f;
21 | }
22 |
23 | @Override
24 | protected AttractState getState() {
25 | if (highScoreMgr.newHighScore(state)) {
26 | return new EnterHighScoreName(state);
27 | } else {
28 | return new HighScore();
29 | }
30 | }
31 |
32 | @Override
33 | public void render(Graphics2D g, Matrix3x3f view) {
34 | super.render(g, view);
35 | acme.drawScore(g, state.getScore());
36 | Utility.drawCenteredString(g, app.getScreenWidth(),
37 | app.getScreenHeight() / 3, "G A M E O V E R");
38 | }
39 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/state/GameState.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.state;
2 |
3 | import javagames.completegame.object.Asteroid.Size;
4 |
5 | public class GameState {
6 |
7 | private int level;
8 | private int lives;
9 | private int score;
10 |
11 | public void setLevel(int level) {
12 | this.level = level;
13 | }
14 |
15 | public int getLevel() {
16 | return level;
17 | }
18 |
19 | public void setLives(int lives) {
20 | this.lives = lives;
21 | }
22 |
23 | public int getLives() {
24 | return lives;
25 | }
26 |
27 | public int getScore() {
28 | return score;
29 | }
30 |
31 | public void updateScore(Size size) {
32 | switch (size) {
33 | case Small:
34 | score += 500;
35 | break;
36 | case Medium:
37 | score += 300;
38 | break;
39 | case Large:
40 | score += 100;
41 | break;
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/state/HighScore.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.state;
2 |
3 | import java.awt.*;
4 | import java.awt.geom.Rectangle2D;
5 | import javagames.util.Matrix3x3f;
6 | import javagames.util.Utility;
7 |
8 | public class HighScore extends AttractState {
9 |
10 | @Override
11 | protected AttractState getState() {
12 | return new GameInformationState();
13 | }
14 |
15 | @Override
16 | public void render(Graphics2D g, Matrix3x3f view) {
17 | super.render(g, view);
18 | String[] hs = highScoreMgr.getHighScores();
19 | g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
20 | RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
21 | g.setFont(new Font("Arial", Font.PLAIN, 20));
22 | g.setColor(Color.GREEN);
23 | Rectangle2D bounds = g.getFontMetrics().getStringBounds(hs[0], g);
24 | int x = (app.getScreenWidth() - (int) bounds.getWidth()) / 2;
25 | Utility.drawString(g, x, app.getScreenHeight() / 3, hs);
26 | }
27 |
28 | @Override
29 | protected float getWaitTime() {
30 | return 7.0f;
31 | }
32 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/state/LevelStarting.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.state;
2 |
3 | import java.awt.*;
4 | import javagames.completegame.admin.Acme;
5 | import javagames.util.*;
6 |
7 | public class LevelStarting extends State {
8 |
9 | double time;
10 | private Sprite background;
11 | private GameState state;
12 | private Acme acme;
13 |
14 | public LevelStarting(GameState state) {
15 | this.state = state;
16 | }
17 |
18 | @Override
19 | public void enter() {
20 | background = (Sprite) controller.getAttribute("background");
21 | acme = (Acme) controller.getAttribute("ACME");
22 | time = 0.0;
23 | }
24 |
25 | @Override
26 | public void updateObjects(float delta) {
27 | time += delta;
28 | if (time > 2.0) {
29 | getController().setState(new LevelPlaying(state));
30 | }
31 | }
32 |
33 | @Override
34 | public void render(Graphics2D g, Matrix3x3f view) {
35 | super.render(g, view);
36 | background.render(g, view);
37 | acme.drawScore(g, state.getScore());
38 | acme.drawLives(g, view, state.getLives());
39 | g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
40 | RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
41 | g.setFont(new Font("Arial", Font.PLAIN, 20));
42 | g.setColor(Color.GREEN);
43 | Utility.drawCenteredString(g, app.getScreenWidth(),
44 | app.getScreenHeight() / 3, "L E V E L " + state.getLevel());
45 | }
46 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/state/PressSpaceToPlay.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.state;
2 |
3 | import java.awt.*;
4 | import javagames.util.Matrix3x3f;
5 | import javagames.util.Utility;
6 |
7 | public class PressSpaceToPlay extends AttractState {
8 |
9 | @Override
10 | protected AttractState getState() {
11 | return new HighScore();
12 | }
13 |
14 | public void render(Graphics2D g, Matrix3x3f view) {
15 | super.render(g, view);
16 | int width = app.getScreenWidth();
17 | int height = app.getScreenHeight();
18 | g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
19 | RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
20 | g.setFont(new Font("Arial", Font.PLAIN, 20));
21 | g.setColor(Color.GREEN);
22 | String[] msg = {
23 | "S P A C E R O C K S",
24 | "",
25 | "",
26 | "",
27 | "P R E S S S P A C E T O P L A Y",
28 | "",
29 | "P R E S S E S C T O E X I T"
30 | };
31 | Utility.drawCenteredString(g, width, height / 3, msg);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/state/Score.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.state;
2 |
3 | public class Score implements Comparable {
4 |
5 | public String name = "";
6 | public int score = 0;
7 |
8 | public Score(String name, int score) {
9 | this.name = name;
10 | this.score = score;
11 | }
12 |
13 | public int compareTo(Score o) {
14 | if (score == o.score)
15 | return 0;
16 | if (score < o.score)
17 | return -1;
18 | return 1;
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/state/State.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.state;
2 |
3 | import java.awt.Graphics2D;
4 | import javagames.completegame.CompleteGame;
5 | import javagames.util.Matrix3x3f;
6 |
7 | public class State {
8 |
9 | protected StateController controller;
10 | protected CompleteGame app;
11 |
12 | public void setController(StateController controller) {
13 | this.controller = controller;
14 | app = (CompleteGame) controller.getAttribute("app");
15 | }
16 |
17 | protected StateController getController() {
18 | return controller;
19 | }
20 |
21 | public void enter() {
22 |
23 | }
24 |
25 | public void processInput(float delta) {
26 | }
27 |
28 | public void updateObjects(float delta) {
29 | }
30 |
31 | public void render(Graphics2D g, Matrix3x3f view) {
32 | }
33 |
34 | public void exit() {
35 |
36 | }
37 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/completegame/state/StateController.java:
--------------------------------------------------------------------------------
1 | package javagames.completegame.state;
2 |
3 | import java.awt.*;
4 | import java.util.*;
5 | import javagames.util.Matrix3x3f;
6 |
7 | public class StateController {
8 |
9 | private Map attributes;
10 | private State currentState;
11 |
12 | public StateController() {
13 | attributes = Collections.synchronizedMap(new HashMap());
14 | }
15 |
16 | public void setState(State newState) {
17 | if (currentState != null) {
18 | currentState.exit();
19 | }
20 | if (newState != null) {
21 | newState.setController(this);
22 | newState.enter();
23 | }
24 | currentState = newState;
25 | }
26 |
27 | public void processInput(float delta) {
28 | currentState.processInput(delta);
29 | }
30 |
31 | public void updateObjects(float delta) {
32 | currentState.updateObjects(delta);
33 | }
34 |
35 | public void render(Graphics2D g, Matrix3x3f view) {
36 | g.setRenderingHint(
37 | RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
38 | );
39 | currentState.render(g, view);
40 | }
41 |
42 | public Object getAttribute(String name) {
43 | return attributes.get(name);
44 | }
45 |
46 | public Object removeAttribute(String name) {
47 | return attributes.remove(name);
48 | }
49 |
50 | public void setAttribute(String name, Object attribute) {
51 | attributes.put(name, attribute);
52 | }
53 |
54 | public Set getAttributeNames() {
55 | return attributes.keySet();
56 | }
57 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/sound/BlockingAudioListener.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public interface BlockingAudioListener {
4 |
5 | public void audioFinished();
6 |
7 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/sound/BlockingDataLine.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public class BlockingDataLine extends AudioStream {
4 |
5 | private AudioDataLine stream;
6 |
7 | public BlockingDataLine(byte[] soundData) {
8 | super(soundData);
9 | }
10 |
11 | @Override
12 | public void open() {
13 | lock.lock();
14 | try {
15 | stream = new AudioDataLine(soundData);
16 | stream.initialize();
17 | stream.addLineListener(this);
18 | stream.open();
19 | while (!open) {
20 | cond.await();
21 | }
22 | //UPDATE
23 | createControls( stream.getLine() );
24 | //UPDATE
25 | System.out.println("open");
26 | } catch (InterruptedException ex) {
27 | ex.printStackTrace();
28 | } finally {
29 | lock.unlock();
30 | }
31 | }
32 |
33 | @Override
34 | public void start() {
35 | lock.lock();
36 | try {
37 | stream.start();
38 | while (!started) {
39 | cond.await();
40 | }
41 | System.out.println("started");
42 | } catch (InterruptedException ex) {
43 | ex.printStackTrace();
44 | } finally {
45 | lock.unlock();
46 | }
47 | }
48 |
49 | @Override
50 | public void loop(int count) {
51 | lock.lock();
52 | try {
53 | stream.loop(count);
54 | while (!started) {
55 | cond.await();
56 | }
57 | System.out.println("started");
58 | } catch (InterruptedException ex) {
59 | ex.printStackTrace();
60 | } finally {
61 | lock.unlock();
62 | }
63 | }
64 |
65 | @Override
66 | public void restart() {
67 | stream.reset();
68 | }
69 |
70 | @Override
71 | public void stop() {
72 | lock.lock();
73 | try {
74 | stream.stop();
75 | while (started) {
76 | cond.await();
77 | }
78 | System.out.println("stopped");
79 | } catch (InterruptedException ex) {
80 | ex.printStackTrace();
81 | } finally {
82 | lock.unlock();
83 | }
84 | }
85 |
86 | @Override
87 | public void close() {
88 | lock.lock();
89 | try {
90 | stream.close();
91 | while (open) {
92 | cond.await();
93 | }
94 | //UPDATE
95 | clearControls();
96 | //UPDATE
97 | System.out.println("closed");
98 | } catch (InterruptedException ex) {
99 | ex.printStackTrace();
100 | } finally {
101 | lock.unlock();
102 | }
103 | }
104 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/sound/LoopEvent.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public class LoopEvent extends SoundEvent {
4 |
5 | public static final String STATE_WAITING = "waiting";
6 | public static final String STATE_RUNNING = "running";
7 | public static final String EVENT_FIRE = "fire";
8 | public static final String EVENT_DONE = "done";
9 | private String currentState;
10 |
11 | public LoopEvent(AudioStream audio) {
12 | super(audio);
13 | currentState = STATE_WAITING;
14 | }
15 |
16 | public void fire() {
17 | put(EVENT_FIRE);
18 | }
19 |
20 | public void done() {
21 | put(EVENT_DONE);
22 | }
23 |
24 | protected void processEvent(String event) throws InterruptedException {
25 | System.out.println("Got " + event + " event");
26 | if (currentState == STATE_WAITING) {
27 | if (event == EVENT_FIRE) {
28 | audio.open();
29 | audio.loop(AudioStream.LOOP_CONTINUOUSLY);
30 | currentState = STATE_RUNNING;
31 | }
32 | } else if (currentState == STATE_RUNNING) {
33 | if (event == EVENT_DONE) {
34 | audio.stop();
35 | audio.close();
36 | currentState = STATE_WAITING;
37 | }
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/sound/SoundEvent.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | import java.util.concurrent.BlockingQueue;
4 | import java.util.concurrent.LinkedBlockingQueue;
5 |
6 | public class SoundEvent implements Runnable {
7 |
8 | public static final String SHUT_DOWN = "shutdown";
9 | protected AudioStream audio;
10 | protected BlockingQueue queue;
11 | private Thread consumer;
12 |
13 | public SoundEvent(AudioStream audio) {
14 | this.audio = audio;
15 | }
16 |
17 | public void initialize() {
18 | audio.addListener(getListener());
19 | queue = new LinkedBlockingQueue();
20 | consumer = new Thread(this);
21 | consumer.start();
22 | }
23 |
24 | public void put(String event) {
25 | try {
26 | queue.put(event);
27 | } catch (InterruptedException e) {
28 | }
29 | }
30 |
31 | public void shutDown() {
32 | Thread temp = consumer;
33 | consumer = null;
34 | try {
35 | // send event to wake up consumer
36 | // and/or stop.
37 | queue.put(SHUT_DOWN);
38 | temp.join(10000L);
39 | System.out.println("Event shutdown!!!");
40 | } catch (InterruptedException ex) {
41 | }
42 | }
43 |
44 | @Override
45 | public void run() {
46 | while (Thread.currentThread() == consumer) {
47 | try {
48 | processEvent(queue.take());
49 | } catch (InterruptedException e) {
50 | }
51 | }
52 | }
53 |
54 | protected void processEvent(String event) throws InterruptedException {
55 | }
56 |
57 | protected void onAudioFinished() {
58 | }
59 |
60 | private BlockingAudioListener getListener() {
61 | return new BlockingAudioListener() {
62 | @Override
63 | public void audioFinished() {
64 | onAudioFinished();
65 | }
66 | };
67 | }
68 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/sound/SoundException.java:
--------------------------------------------------------------------------------
1 | package javagames.sound;
2 |
3 | public class SoundException extends RuntimeException {
4 |
5 | public SoundException(String message) {
6 | super(message);
7 | }
8 |
9 | public SoundException(String message, Throwable cause) {
10 | super(message, cause);
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/util/FrameRate.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | public class FrameRate {
5 |
6 | private String frameRate;
7 | private long lastTime;
8 | private long delta;
9 | private int frameCount;
10 |
11 | public void initialize() {
12 | lastTime = System.currentTimeMillis();
13 | frameRate = "FPS 0";
14 | }
15 |
16 | public void calculate() {
17 | long current = System.currentTimeMillis();
18 | delta += current - lastTime;
19 | lastTime = current;
20 | frameCount++;
21 | if( delta > 1000 ) {
22 | delta -= 1000;
23 | frameRate = String.format( "FPS %s", frameCount );
24 | frameCount = 0;
25 | }
26 | }
27 |
28 | public String getFrameRate() {
29 | return frameRate;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CH17/src/javagames/util/KeyboardInput.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 |
4 | import java.awt.event.*;
5 |
6 | public class KeyboardInput implements KeyListener {
7 |
8 | private boolean[] keys;
9 | private int[] polled;
10 |
11 | public KeyboardInput() {
12 | keys = new boolean[ 256 ];
13 | polled = new int[ 256 ];
14 | }
15 |
16 | public boolean keyDown( int keyCode ) {
17 | return polled[ keyCode ] > 0;
18 | }
19 |
20 | public boolean keyDownOnce( int keyCode ) {
21 | return polled[ keyCode ] == 1;
22 | }
23 |
24 | public synchronized void poll() {
25 | for( int i = 0; i < keys.length; ++i ) {
26 | if( keys[i] ) {
27 | polled[i]++;
28 | } else {
29 | polled[i] = 0;
30 | }
31 | }
32 | }
33 |
34 | public synchronized void keyPressed( KeyEvent e ) {
35 | int keyCode = e.getKeyCode();
36 | if( keyCode >= 0 && keyCode < keys.length ) {
37 | keys[ keyCode ] = true;
38 | }
39 | }
40 |
41 | public synchronized void keyReleased( KeyEvent e ) {
42 | int keyCode = e.getKeyCode();
43 | if( keyCode >= 0 && keyCode < keys.length ) {
44 | keys[ keyCode ] = false;
45 | }
46 | }
47 |
48 | public void keyTyped( KeyEvent e ) {
49 | // Not needed
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CH17/src/javagames/util/ResourceLoader.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.FileNotFoundException;
5 | import java.io.InputStream;
6 |
7 | public class ResourceLoader {
8 |
9 | public static InputStream load(Class> clazz, String filePath,
10 | String resPath) {
11 | // try the resource first
12 | InputStream in = null;
13 | if (!(resPath == null || resPath.isEmpty())) {
14 | in = clazz.getResourceAsStream(resPath);
15 | }
16 | if (in == null) {
17 | // try the file path
18 | try {
19 | in = new FileInputStream(filePath);
20 | } catch (FileNotFoundException e) {
21 | e.printStackTrace();
22 | }
23 | }
24 | return in;
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/util/Sprite.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.*;
4 | import java.awt.geom.AffineTransform;
5 | import java.awt.image.BufferedImage;
6 |
7 | public class Sprite {
8 |
9 | private BufferedImage image;
10 | private BufferedImage scaled;
11 | private Vector2f topLeft;
12 | private Vector2f bottomRight;
13 |
14 | public Sprite(BufferedImage image, Vector2f topLeft, Vector2f bottomRight) {
15 | this.image = image;
16 | this.topLeft = topLeft;
17 | this.bottomRight = bottomRight;
18 | }
19 |
20 | public void render(Graphics2D g, Matrix3x3f view) {
21 | render(g, view, new Vector2f(), 0.0f);
22 | }
23 |
24 | public void render(Graphics2D g, Matrix3x3f view, Vector2f position, float angle) {
25 | if (image != null) {
26 | Vector2f tl = view.mul(topLeft);
27 | Vector2f br = view.mul(bottomRight);
28 | int width = (int) Math.abs(br.x - tl.x);
29 | int height = (int) Math.abs(br.y - tl.y);
30 | if (scaled == null || width != scaled.getWidth() ||
31 | height != scaled.getHeight()) {
32 | scaled = Utility.scaleImage(image, width, height);
33 | }
34 | g.setRenderingHint(
35 | RenderingHints.KEY_INTERPOLATION,
36 | RenderingHints.VALUE_INTERPOLATION_BILINEAR
37 | );
38 | Vector2f screen = view.mul(position);
39 | AffineTransform transform =
40 | AffineTransform.getTranslateInstance(screen.x, screen.y);
41 | transform.rotate(-angle);
42 | transform.translate(-scaled.getWidth() / 2, -scaled.getHeight() / 2);
43 | g.drawImage(scaled, transform, null);
44 | }
45 | }
46 |
47 | public void scaleImage(Matrix3x3f view) {
48 | Vector2f screenTopLeft = view.mul(topLeft);
49 | Vector2f screenBottomRight = view.mul(bottomRight);
50 | int scaledWidth = (int) Math.abs(screenBottomRight.x - screenTopLeft.x);
51 | int scaledHeight = (int) Math.abs(screenBottomRight.y - screenTopLeft.y);
52 | scaled = Utility.scaleImage(image, scaledWidth, scaledHeight);
53 | }
54 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/util/Vector2f.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | public class Vector2f {
4 |
5 | public float x;
6 | public float y;
7 | public float w;
8 |
9 | public Vector2f() {
10 | this.x = 0.0f;
11 | this.y = 0.0f;
12 | this.w = 1.0f;
13 | }
14 |
15 | public Vector2f(Vector2f v) {
16 | this.x = v.x;
17 | this.y = v.y;
18 | this.w = v.w;
19 | }
20 |
21 | public Vector2f(float x, float y) {
22 | this.x = x;
23 | this.y = y;
24 | this.w = 1.0f;
25 | }
26 |
27 | public Vector2f(float x, float y, float w) {
28 | this.x = x;
29 | this.y = y;
30 | this.w = w;
31 | }
32 |
33 | public void translate(float tx, float ty) {
34 | x += tx;
35 | y += ty;
36 | }
37 |
38 | public void scale(float sx, float sy) {
39 | x *= sx;
40 | y *= sy;
41 | }
42 |
43 | public void rotate(float rad) {
44 | float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
45 | y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
46 | x = tmp;
47 | }
48 |
49 | public void shear(float sx, float sy) {
50 | float tmp = x + sx * y;
51 | y = y + sy * x;
52 | x = tmp;
53 | }
54 |
55 | public Vector2f add(Vector2f v) {
56 | return new Vector2f(x + v.x, y + v.y);
57 | }
58 |
59 | public Vector2f sub(Vector2f v) {
60 | return new Vector2f(x - v.x, y - v.y);
61 | }
62 |
63 | public Vector2f mul(float scalar) {
64 | return new Vector2f(scalar * x, scalar * y);
65 | }
66 |
67 | public Vector2f div(float scalar) {
68 | return new Vector2f(x / scalar, y / scalar);
69 | }
70 |
71 | public Vector2f inv() {
72 | return new Vector2f(-x, -y);
73 | }
74 |
75 | public Vector2f norm() {
76 | return div(len());
77 | }
78 |
79 | public float dot(Vector2f v) {
80 | return x * v.x + y * v.y;
81 | }
82 |
83 | public float len() {
84 | return (float) Math.sqrt(x * x + y * y);
85 | }
86 |
87 | public float lenSqr() {
88 | return x * x + y * y;
89 | }
90 |
91 | public Vector2f perp() {
92 | return new Vector2f(-y, x);
93 | }
94 |
95 | public float angle() {
96 | return (float) Math.atan2(y, x);
97 | }
98 |
99 | public static Vector2f polar(float angle, float radius) {
100 | return new Vector2f(radius * (float) Math.cos(angle), radius
101 | * (float) Math.sin(angle));
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return String.format("(%s,%s)", x, y);
107 | }
108 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/util/WindowFramework.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.awt.*;
4 | import java.awt.event.*;
5 |
6 | public class WindowFramework extends GameFramework {
7 |
8 | private Canvas canvas;
9 |
10 | @Override
11 | protected void createFramework() {
12 | canvas = new Canvas();
13 | canvas.setBackground(appBackground);
14 | canvas.setIgnoreRepaint(true);
15 | getContentPane().add(canvas);
16 | setLocationByPlatform(true);
17 | if (appMaintainRatio) {
18 | getContentPane().setBackground(appBorder);
19 | setSize(appWidth, appHeight);
20 | setLayout(null);
21 | getContentPane().addComponentListener(new ComponentAdapter() {
22 | public void componentResized(ComponentEvent e) {
23 | onComponentResized(e);
24 | }
25 | });
26 | } else {
27 | canvas.setSize(appWidth, appHeight);
28 | pack();
29 | }
30 | setTitle(appTitle);
31 | setupInput(canvas);
32 | setVisible(true);
33 | createBufferStrategy(canvas);
34 | canvas.requestFocus();
35 | }
36 |
37 | protected void onComponentResized(ComponentEvent e) {
38 | Dimension size = getContentPane().getSize();
39 | setupViewport(size.width, size.height);
40 | canvas.setLocation(vx, vy);
41 | canvas.setSize(vw, vh);
42 | }
43 |
44 | public int getScreenWidth() {
45 | return canvas.getWidth();
46 | }
47 |
48 | public int getScreenHeight() {
49 | return canvas.getHeight();
50 | }
51 |
52 | @Override
53 | protected void renderFrame(Graphics g) {
54 | g.clearRect(0, 0, getScreenWidth(), getScreenHeight());
55 | render(g);
56 | }
57 | }
--------------------------------------------------------------------------------
/CH17/src/javagames/util/XMLUtility.java:
--------------------------------------------------------------------------------
1 | package javagames.util;
2 |
3 | import java.io.*;
4 | import java.util.*;
5 | import javax.xml.parsers.*;
6 | import org.w3c.dom.*;
7 | import org.xml.sax.*;
8 |
9 | public class XMLUtility {
10 |
11 | public static Document parseDocument(InputStream inputStream)
12 | throws ParserConfigurationException, SAXException, IOException {
13 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
14 | DocumentBuilder builder = factory.newDocumentBuilder();
15 | Document document = builder.parse(new InputSource(inputStream));
16 | return document;
17 | }
18 |
19 | public static Document parseDocument(Reader reader)
20 | throws ParserConfigurationException, SAXException, IOException {
21 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
22 | DocumentBuilder builder = factory.newDocumentBuilder();
23 | Document document = builder.parse(new InputSource(reader));
24 | return document;
25 | }
26 |
27 | public static List getAllElements(Element element, String tagName) {
28 | ArrayList elements = new ArrayList();
29 | NodeList nodes = element.getElementsByTagName(tagName);
30 | for (int i = 0; i < nodes.getLength(); i++) {
31 | elements.add((Element) nodes.item(i));
32 | }
33 | return elements;
34 | }
35 |
36 | public static List getElements(Element element, String tagName) {
37 | ArrayList elements = new ArrayList();
38 | NodeList children = element.getChildNodes();
39 | for (int i = 0; i < children.getLength(); i++) {
40 | Node node = children.item(i);
41 | if (node.getNodeType() == Node.ELEMENT_NODE) {
42 | String nodeName = node.getNodeName();
43 | if (nodeName != null && nodeName.equals(tagName)) {
44 | elements.add((Element) node);
45 | }
46 | }
47 | }
48 | return elements;
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/CH17/testing.txt:
--------------------------------------------------------------------------------
1 | My idea is:
2 |
3 | OS-Version Java Version Date Results
4 |
5 | Windows 7 1.0.7_71 14JAN2015 success
6 | Windows 7 1.0.8_25 15JAN2015 success
7 |
8 |
9 | Ubuntu 14.04 1.0.7_71 TBD not done
10 | Ubuntu 14.04 1.0.8_25 TBD not done
11 |
12 |
13 | OSX Yosemite 1.0.7_71 TBD not done
14 | OSX Yosemite 1.0.8_25 TBD not done
15 |
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Fundamental-2D-Game-Programming-With-Java
2 | Source code examples for the book "Fundamental 2D Game Programming with Java"
3 |
--------------------------------------------------------------------------------