├── .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 | --------------------------------------------------------------------------------