├── README.md ├── java4k.txt └── src └── java4k ├── Game.java ├── GamePanel.java ├── Launcher.java ├── apohockey4k ├── W.java ├── W.png └── readme.txt ├── apoone4k ├── A.java ├── A.png └── readme.txt ├── boing4k ├── a.java ├── a.png └── readme.txt ├── boxbot4k ├── B.java ├── B.png └── readme.txt ├── castlevania4k ├── a.java ├── a.png └── readme.txt ├── crackattack4k ├── Crack_Attack_4K.png ├── a.java ├── a.png └── readme.txt ├── demonattack4k ├── a.java ├── a.png └── readme.txt ├── di4klo ├── A.java ├── A.png └── readme.txt ├── diez ├── Z.java ├── Z.png └── readme.txt ├── dord ├── a.java ├── a.png └── readme.txt ├── doubledragon4k ├── a.java ├── a.png └── readme.txt ├── flap4kanabalt ├── V.gif ├── V.java └── readme.txt ├── fzero4k ├── M.java ├── M.jpg └── readme.txt ├── gradius4k ├── a.java ├── a.png └── readme.txt ├── greenballs ├── G.java ├── G.png └── readme.txt ├── i4kopter ├── I4Kopter.gif ├── I4Kopter.java ├── i4kopter.gif └── readme.txt ├── inthedark4k ├── A.java ├── A.jpg └── readme.txt ├── jackal4k ├── a.java ├── a.png └── readme.txt ├── junglehunt4k ├── a.java ├── a.png └── readme.txt ├── keystonekapers4k ├── a.java ├── a.png └── readme.txt ├── laserpinball ├── a.java ├── a.png └── readme.txt ├── legendofzelda4k ├── a.java ├── a.png └── readme.txt ├── magewars4k ├── M.java ├── M.png └── readme.txt ├── mcjob ├── a.java ├── a.png └── readme.txt ├── myprecious ├── R.java ├── R.png └── readme.txt ├── mysterymash ├── M.java ├── M.png └── readme.txt ├── on ├── O.java ├── O.png └── readme.txt ├── outrun4k ├── a.java ├── a.png └── readme.txt ├── pinball4k ├── a ├── a.java ├── a.jpg ├── editor │ ├── Arrow.java │ ├── Bezier.java │ ├── Editor.java │ ├── Flipper.java │ ├── GroupList.java │ ├── GroupUI.java │ ├── Handle.java │ ├── Level.java │ ├── LevelObject.java │ ├── LevelPanel.java │ ├── Line.java │ ├── ObjectProperties.java │ ├── ObjectPropertiesUI.java │ ├── PaintUtil.java │ ├── QuadBezier.java │ └── Sircle.java └── readme.txt ├── pitfall4k ├── a.java ├── a.png └── readme.txt ├── porta4k ├── P.java ├── P.jpg └── readme.txt ├── rainbowroad ├── a.java ├── a.png └── readme.txt ├── s23 ├── A.java ├── A.png └── readme.txt ├── scramble ├── G.java ├── G.png └── readme.txt ├── spacedevastation ├── A.java ├── A.png └── readme.txt ├── supermarioland4k ├── a.java ├── a.png └── readme.txt ├── thebattleforhoth4k ├── a.java ├── a.png └── readme.txt ├── wolfenstein4k ├── a.java ├── a.png └── readme.txt └── yoshiscoins4k ├── a.java ├── a.png └── readme.txt /README.md: -------------------------------------------------------------------------------- 1 | This repository was created in 2015 for historic purposes. Since then, one of the main authors (Mike Birken) wrote some very interesting [development notes](https://meatfighter.com/java4k/) with a similar package. 2 | -------------------------------------------------------------------------------- /java4k.txt: -------------------------------------------------------------------------------- 1 | Done 2 | ---- 3 | 4 | http://www.java4k.com/index.php?action=games&method=view&gid=330 5 | http://www.java4k.com/index.php?action=games&method=view&gid=326 6 | http://www.java4k.com/index.php?action=games&method=view&gid=348 7 | http://www.java4k.com/index.php?action=games&method=view&gid=337 8 | http://www.java4k.com/index.php?action=games&method=view&gid=311 9 | http://www.java4k.com/index.php?action=games&method=view&gid=339 10 | http://www.java4k.com/index.php?action=games&method=view&gid=349 11 | http://www.java4k.com/index.php?action=games&method=view&gid=324 no sources 12 | http://www.java4k.com/index.php?action=games&method=view&gid=331 13 | http://www.java4k.com/index.php?action=games&method=view&gid=341 14 | http://www.java4k.com/index.php?action=games&method=view&gid=444 15 | http://www.java4k.com/index.php?action=games&method=view&gid=465 16 | http://www.java4k.com/index.php?action=games&method=view&gid=451 17 | http://www.java4k.com/index.php?action=games&method=view&gid=467 no sources 18 | http://www.java4k.com/index.php?action=games&method=view&gid=462 19 | http://www.java4k.com/index.php?action=games&method=view&gid=213 20 | http://www.java4k.com/index.php?action=games&method=view&gid=258 21 | http://www.java4k.com/index.php?action=games&method=view&gid=201 not GPL 22 | http://www.java4k.com/index.php?action=games&method=view&gid=176 23 | http://www.java4k.com/index.php?action=games&method=view&gid=491 24 | http://www.java4k.com/index.php?action=games&method=view&gid=483 25 | http://www.java4k.com/index.php?action=games&method=view&gid=418 26 | http://www.java4k.com/index.php?action=games&method=view&gid=408 27 | http://www.java4k.com/index.php?action=games&method=view&gid=478 28 | http://www.java4k.com/index.php?action=games&method=view&gid=455 29 | http://www.java4k.com/index.php?action=games&method=view&gid=368 30 | http://www.java4k.com/index.php?action=games&method=view&gid=380 31 | http://www.java4k.com/index.php?action=games&method=view&gid=358 no sources 32 | http://www.java4k.com/index.php?action=games&method=view&gid=354 no sources 33 | http://www.java4k.com/index.php?action=games&method=view&gid=389 34 | http://www.java4k.com/index.php?action=games&method=view&gid=377 35 | http://www.java4k.com/index.php?action=games&method=view&gid=372 36 | http://www.java4k.com/index.php?action=games&method=view&gid=394 37 | http://www.java4k.com/index.php?action=games&method=view&gid=371 no sources 38 | http://www.java4k.com/index.php?action=games&method=view&gid=356 no sources 39 | http://www.java4k.com/index.php?action=games&method=view&gid=332 40 | http://www.java4k.com/index.php?action=games&method=view&gid=338 41 | http://www.java4k.com/index.php?action=games&method=view&gid=335 42 | http://www.java4k.com/index.php?action=games&method=view&gid=352 no sources 43 | http://www.java4k.com/index.php?action=games&method=view&gid=327 44 | http://www.java4k.com/index.php?action=games&method=view&gid=319 no sources 45 | http://www.java4k.com/index.php?action=games&method=view&gid=340 46 | http://www.java4k.com/index.php?action=games&method=view&gid=329 47 | http://www.java4k.com/index.php?action=games&method=view&gid=281 48 | 49 | To do 50 | ----- 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/java4k/Game.java: -------------------------------------------------------------------------------- 1 | package java4k; 2 | 3 | import java.awt.AWTEvent; 4 | import java.awt.Dimension; 5 | 6 | import javax.swing.JPanel; 7 | 8 | public interface Game { 9 | 10 | public void start(); 11 | 12 | public void stop(); 13 | 14 | public JPanel getPanel(); 15 | 16 | public Dimension getPreferredSize(); 17 | 18 | public void processAWTEvent(AWTEvent e); 19 | 20 | // public void updateGame(); 21 | // public void repaintGame(); // TODO override paintComponent() in GamePanel 22 | 23 | /* 24 | while(running) { 25 | repaint(); 26 | } 27 | 28 | 29 | 30 | */ 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/java4k/GamePanel.java: -------------------------------------------------------------------------------- 1 | package java4k; 2 | 3 | import java.awt.AWTEvent; 4 | import java.awt.event.KeyEvent; 5 | import java.awt.event.KeyListener; 6 | import java.awt.event.MouseEvent; 7 | import java.awt.event.MouseListener; 8 | import java.awt.event.MouseMotionListener; 9 | 10 | import javax.swing.JPanel; 11 | 12 | public abstract class GamePanel extends JPanel implements Game, MouseListener, MouseMotionListener, KeyListener, Runnable { 13 | 14 | protected volatile boolean running = true; 15 | protected boolean continuousRepaint = false; 16 | 17 | public GamePanel(boolean continuousRepaint) { 18 | this.continuousRepaint = continuousRepaint; 19 | addMouseListener(this); 20 | addMouseMotionListener(this); 21 | addKeyListener(this); 22 | } 23 | 24 | public GamePanel() { 25 | this(false); 26 | } 27 | 28 | public void start() { 29 | if (continuousRepaint) { 30 | new Thread(this).start(); 31 | } else { 32 | repaint(); 33 | } 34 | } 35 | 36 | public void stop() { 37 | running = false; 38 | } 39 | 40 | public void run() { 41 | while(running) { 42 | repaint(); 43 | } 44 | } 45 | 46 | @Override 47 | public void mouseClicked(MouseEvent e) { 48 | processAWTEvent(e); 49 | } 50 | 51 | @Override 52 | public void mouseEntered(MouseEvent e) { 53 | processAWTEvent(e); 54 | 55 | } 56 | 57 | @Override 58 | public void mouseExited(MouseEvent e) { 59 | processAWTEvent(e); 60 | } 61 | 62 | @Override 63 | public void mousePressed(MouseEvent e) { 64 | processAWTEvent(e); 65 | } 66 | 67 | @Override 68 | public void mouseReleased(MouseEvent e) { 69 | processAWTEvent(e); 70 | } 71 | 72 | @Override 73 | public void mouseDragged(MouseEvent e) { 74 | processAWTEvent(e); 75 | } 76 | 77 | @Override 78 | public void mouseMoved(MouseEvent e) { 79 | processAWTEvent(e); 80 | } 81 | 82 | @Override 83 | public void keyPressed(KeyEvent e) { 84 | processAWTEvent(e); 85 | } 86 | 87 | @Override 88 | public void keyReleased(KeyEvent e) { 89 | processAWTEvent(e); 90 | } 91 | 92 | @Override 93 | public void keyTyped(KeyEvent e) { 94 | processAWTEvent(e); 95 | } 96 | 97 | @Override 98 | public JPanel getPanel() { 99 | return this; 100 | } 101 | 102 | @Override 103 | public void processAWTEvent(AWTEvent e) { 104 | // Do nothing 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/java4k/Launcher.java: -------------------------------------------------------------------------------- 1 | package java4k; 2 | 3 | import java.awt.Component; 4 | import java.awt.Dimension; 5 | import java.awt.FlowLayout; 6 | import java.awt.Font; 7 | import java.awt.event.MouseAdapter; 8 | import java.awt.event.MouseEvent; 9 | import java.awt.event.WindowAdapter; 10 | import java.awt.event.WindowEvent; 11 | import java.awt.image.BufferedImage; 12 | import java.io.BufferedReader; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.io.InputStreamReader; 16 | 17 | import javax.imageio.ImageIO; 18 | import javax.swing.DefaultListCellRenderer; 19 | import javax.swing.DefaultListModel; 20 | import javax.swing.ImageIcon; 21 | import javax.swing.JFrame; 22 | import javax.swing.JLabel; 23 | import javax.swing.JList; 24 | import javax.swing.JPanel; 25 | import javax.swing.JScrollPane; 26 | import javax.swing.JTextArea; 27 | import javax.swing.SwingUtilities; 28 | 29 | public class Launcher { 30 | 31 | private static final Class[] GAME_CLASSES = { java4k.apohockey4k.W.class, java4k.apoone4k.A.class, java4k.boing4k.a.class, java4k.boxbot4k.B.class, java4k.castlevania4k.a.class, 32 | java4k.crackattack4k.a.class, java4k.demonattack4k.a.class, java4k.di4klo.A.class, java4k.diez.Z.class, java4k.dord.a.class, java4k.doubledragon4k.a.class, java4k.flap4kanabalt.V.class, 33 | java4k.fzero4k.M.class, java4k.gradius4k.a.class, java4k.greenballs.G.class, java4k.i4kopter.I4Kopter.class, java4k.inthedark4k.A.class, java4k.jackal4k.a.class, 34 | java4k.junglehunt4k.a.class, java4k.keystonekapers4k.a.class, java4k.laserpinball.a.class, java4k.legendofzelda4k.a.class, java4k.magewars4k.M.class, java4k.mcjob.a.class, 35 | java4k.myprecious.R.class, java4k.mysterymash.M.class, java4k.on.O.class, java4k.outrun4k.a.class, java4k.pinball4k.a.class, java4k.pitfall4k.a.class, java4k.porta4k.P.class, 36 | java4k.rainbowroad.a.class, java4k.s23.A.class, java4k.scramble.G.class, java4k.spacedevastation.A.class, java4k.supermarioland4k.a.class, java4k.thebattleforhoth4k.a.class, 37 | java4k.wolfenstein4k.a.class, java4k.yoshiscoins4k.a.class }; 38 | 39 | private static final DefaultListModel gameListModel = new DefaultListModel(); 40 | private JTextArea textArea; 41 | 42 | public Launcher() throws IOException { 43 | parseGameInfos(); 44 | } 45 | 46 | private void startUI() { 47 | JList list = new JList(gameListModel); 48 | list.setCellRenderer(new GameListRenderer()); 49 | list.addMouseListener(new MouseAdapter() { 50 | public void mouseClicked(MouseEvent evt) { 51 | JList list = (JList) evt.getSource(); 52 | if (evt.getClickCount() == 1) { 53 | int index = list.locationToIndex(evt.getPoint()); 54 | GameInfo gameInfo = gameListModel.elementAt(index); 55 | textArea.setText(gameInfo.description); 56 | textArea.setCaretPosition(0); 57 | } else if (evt.getClickCount() == 2) { 58 | // Double-click detected 59 | int index = list.locationToIndex(evt.getPoint()); 60 | GameInfo gameInfo = gameListModel.elementAt(index); 61 | 62 | try { 63 | // Method startMethod = gameInfo.gameClass.getMethod("main", String[].class); //stringArray.getClass() 64 | // Object instance = gameInfo.gameClass.newInstance(); 65 | // String[] params = null; 66 | // startMethod.invoke(instance, (Object) params); 67 | 68 | Game game = (Game) gameInfo.gameClass.newInstance(); 69 | startGame(game, gameInfo); 70 | 71 | } catch (InstantiationException e) { 72 | e.printStackTrace(); 73 | } catch (IllegalAccessException e) { 74 | e.printStackTrace(); 75 | } catch (SecurityException e) { 76 | e.printStackTrace(); 77 | } catch (IllegalArgumentException e) { 78 | e.printStackTrace(); 79 | } /*catch (InvocationTargetException e) { 80 | e.printStackTrace(); 81 | } catch (NoSuchMethodException e) { 82 | e.printStackTrace(); 83 | }*/ 84 | } 85 | } 86 | }); 87 | 88 | JScrollPane listScroll = new JScrollPane(list); 89 | listScroll.setPreferredSize(new Dimension(350, 400)); 90 | 91 | textArea = new JTextArea(); 92 | textArea.setEditable(false); 93 | textArea.setLineWrap(true); 94 | textArea.setWrapStyleWord(true); 95 | JScrollPane textScroll = new JScrollPane(textArea); 96 | textScroll.setPreferredSize(new Dimension(400, 400)); 97 | 98 | JFrame frame = new JFrame("Java 4K games"); 99 | frame.setLayout(new FlowLayout()); 100 | frame.add(listScroll); 101 | frame.add(textScroll); 102 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 103 | frame.pack(); 104 | frame.setLocationRelativeTo(null); 105 | frame.setVisible(true); 106 | } 107 | 108 | private void startGame(final Game game, GameInfo info) { 109 | javax.swing.JFrame frame = new javax.swing.JFrame(info.name); 110 | frame.addWindowListener(new WindowAdapter() { 111 | @Override 112 | public void windowClosing(WindowEvent arg0) { 113 | game.stop(); 114 | } 115 | }); 116 | frame.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); 117 | 118 | JPanel panel = game.getPanel(); 119 | frame.add(panel, java.awt.BorderLayout.CENTER); 120 | 121 | frame.setResizable(false); 122 | frame.pack(); 123 | frame.setLocationRelativeTo(null); 124 | frame.setVisible(true); 125 | panel.requestFocusInWindow(); 126 | 127 | game.start(); 128 | } 129 | 130 | private void parseGameInfos() throws IOException { 131 | 132 | for (int i = 0; i < GAME_CLASSES.length; i++) { 133 | Class gameClass = GAME_CLASSES[i]; 134 | BufferedReader in = new BufferedReader(new InputStreamReader(gameClass.getResourceAsStream("readme.txt"))); 135 | GameInfo gameInfo = new GameInfo(); 136 | gameInfo.gameClass = gameClass; 137 | gameInfo.name = in.readLine().trim(); 138 | in.readLine(); // Skip next line 139 | 140 | StringBuffer textBuffer = new StringBuffer(); 141 | String s; 142 | while ((s = in.readLine()) != null) { 143 | textBuffer.append(s); 144 | textBuffer.append("\n"); 145 | } 146 | gameInfo.description = textBuffer.toString(); 147 | 148 | // StringBuffer descriptionBuffer = new StringBuffer(); 149 | // StringBuffer instructionsBuffer = new StringBuffer(); 150 | // String s; 151 | // while(!(s = in.readLine()).contains("Description")) { 152 | // in.readLine(); 153 | // } 154 | // while((s = in.readLine()).contains("Description")) { 155 | // in.readLine(); 156 | // } 157 | // while(!(s = in.readLine()).contains("Instructions")) { 158 | // descriptionBuffer.append(in.readLine()); 159 | // } 160 | // while((s = in.readLine()).contains("Instructions")) { 161 | // in.readLine(); 162 | // } 163 | // while((s = in.readLine()) != null) { 164 | // instructionsBuffer.append(in.readLine()); 165 | // } 166 | 167 | // Load screenshots 168 | BufferedImage image; 169 | String className = gameClass.getSimpleName(); 170 | InputStream is = gameClass.getResourceAsStream(className + ".png"); 171 | if (is == null) { 172 | is = gameClass.getResourceAsStream(className + ".jpg"); 173 | } 174 | if (is == null) { 175 | is = gameClass.getResourceAsStream(className + ".gif"); 176 | } 177 | if (is != null) { 178 | image = ImageIO.read(is); 179 | } else { 180 | image = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB_PRE); 181 | } 182 | gameInfo.image = image; 183 | 184 | gameListModel.addElement(gameInfo); 185 | } 186 | 187 | } 188 | 189 | private class GameInfo { 190 | Class gameClass; 191 | BufferedImage image; 192 | String name; 193 | String description; 194 | //String instructions; 195 | } 196 | 197 | private class GameListRenderer extends DefaultListCellRenderer { 198 | 199 | Font font = new Font("helvitica", Font.BOLD, 12); 200 | 201 | @Override 202 | public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 203 | 204 | JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 205 | label.setText(((GameInfo) value).name); 206 | label.setIcon(new ImageIcon(((GameInfo) value).image)); 207 | label.setHorizontalTextPosition(JLabel.RIGHT); 208 | label.setFont(font); 209 | return label; 210 | } 211 | } 212 | 213 | public static void main(String[] args) { 214 | 215 | try { 216 | final Launcher launcher = new Launcher(); 217 | SwingUtilities.invokeLater(new Runnable() { 218 | public void run() { 219 | launcher.startUI(); 220 | } 221 | }); 222 | } catch (IOException e) { 223 | e.printStackTrace(); 224 | } 225 | 226 | 227 | } 228 | 229 | } 230 | -------------------------------------------------------------------------------- /src/java4k/apohockey4k/W.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/apohockey4k/W.java -------------------------------------------------------------------------------- /src/java4k/apohockey4k/W.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/apohockey4k/W.png -------------------------------------------------------------------------------- /src/java4k/apohockey4k/readme.txt: -------------------------------------------------------------------------------- 1 | ApoHockey 4k 2 | ============ 3 | 4 | Description 5 | ----------- 6 | 7 | ApoHockey4k is a stylish air hockey game in only 4k. 8 | 9 | 10 | Instructions 11 | ------------ 12 | 13 | Move your paddle with your mouse. 14 | Press 'delete' to restart the game. 15 | -------------------------------------------------------------------------------- /src/java4k/apoone4k/A.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/apoone4k/A.java -------------------------------------------------------------------------------- /src/java4k/apoone4k/A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/apoone4k/A.png -------------------------------------------------------------------------------- /src/java4k/apoone4k/readme.txt: -------------------------------------------------------------------------------- 1 | ApoOne 4k 2 | ========= 3 | 4 | Description 5 | ----------- 6 | 7 | Your goal is to reach the other side of each level. 8 | All you can do is jumping and please don't die. 9 | 10 | 11 | Instructions 12 | ------------ 13 | 14 | Jump with the spacebar or the cursor keys. 15 | -------------------------------------------------------------------------------- /src/java4k/boing4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/boing4k/a.png -------------------------------------------------------------------------------- /src/java4k/boing4k/readme.txt: -------------------------------------------------------------------------------- 1 | Boing 4K 2 | ======== 3 | 4 | Description 5 | ----------- 6 | 7 | You have 60 seconds to go from one end of the course to the other. 8 | Pay attention to the time remaining bar displayed at the bottom of the frame. 9 | If you run out of time, you'll have to restart the course. 10 | 11 | To beat the game, you need to conquer all 14 courses. Along the way, you'll encounter squares with different properties. 12 | Green circles make you bounce higher. Aqua bars do the opposite. Arrows force you to hop in a specified direction. 13 | Exclamation marks vanish after use. Question marks can do any of the above. Note, unmarked squares act as a kind of checkpoint. 14 | If you fall off the course, you'll return to the last unmarked square. 15 | 16 | Instructions 17 | ------------ 18 | 19 | Use the arrow keys or the WASD keys to move. Position your shadow on the square that you want to land on. -------------------------------------------------------------------------------- /src/java4k/boxbot4k/B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/boxbot4k/B.png -------------------------------------------------------------------------------- /src/java4k/boxbot4k/readme.txt: -------------------------------------------------------------------------------- 1 | BoxBot4k 2 | ======== 3 | 4 | Description 5 | ----------- 6 | 7 | The goal of the game to push boxes around a maze and try to put them in designated locations (squares with red pattern) 8 | by controlling a robot. 9 | Only one box may be pushed at a time, and boxes cannot be pulled. 10 | The game contains 50 levels. 11 | 12 | Instructions 13 | ------------ 14 | 15 | Game controls 16 | - Arrow keys: move the robot 17 | - Backspace: restart level 18 | - PgUp/PgDn: go to next/previous level -------------------------------------------------------------------------------- /src/java4k/castlevania4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/castlevania4k/a.png -------------------------------------------------------------------------------- /src/java4k/castlevania4k/readme.txt: -------------------------------------------------------------------------------- 1 | Castlevania 4k 2 | ============== 3 | 4 | Description 5 | ----------- 6 | 7 | Assuming the role of Simon Belmont, you enter Count Dracula's chambers with the Morning Star Vampire Killer Whip, 8 | the Cross Boomerang, the Triple Shot, unlimited hearts and unlimited lives. 9 | 10 | Instructions 11 | ------------ 12 | 13 | Left and Right -- Move 14 | Down -- Kneel 15 | S -- Whip 16 | A -- Boomerang 17 | Up or D or any other key -- Jump -------------------------------------------------------------------------------- /src/java4k/crackattack4k/Crack_Attack_4K.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/crackattack4k/Crack_Attack_4K.png -------------------------------------------------------------------------------- /src/java4k/crackattack4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/crackattack4k/a.png -------------------------------------------------------------------------------- /src/java4k/crackattack4k/readme.txt: -------------------------------------------------------------------------------- 1 | Crack Attack 4k 2 | =============== 3 | 4 | Description 5 | ----------- 6 | 7 | Arrange blocks in horizontal or vertical lines of 3 or more matching colors to clear them from the playfield. Any blocks above will fall into the gap. The stack rises steadily with new blocks added at the bottom. If the stack reaches the top, it's game over. The objective is to repeatedly clear blocks until the stack falls below a flashing line. 8 | 9 | Do not wait for blocks to vanish. Keep on moving. When you form a pattern, the blocks are not cleared instantaneously. Instead, they briefly flash and pop out of existence. During this process, the stack stops rising. Use that to your advantage. 10 | 11 | Clearing more than 3 blocks in a single move scores a Combo. Combos temporarily stop the stack from rising even after the blocks vanish such that the larger the Combo, the longer the delay. 12 | 13 | Since gravity acts on the blocks, chain reactions, or Chains for short, can occur as patterns form indirectly. With careful planning you can generate complex Chains. You can even take advantage of gravity delays and slip blocks into falling columns to form Chains. 14 | 15 | As you approach the flashing line, the stack rising speed increases. However, if it is rising too slowly for you or if it is halted due to a Combo or Chain, press the right mouse button to advance the stack. 16 | 17 | 18 | 19 | Instructions 20 | ------------ 21 | 22 | Click on the up and down arrows on the menu screen to adjust the starting level. Press the green button to start the game. 23 | 24 | When the game begins, use the mouse to position the cursor over 2 adjacent blocks within the same row. Press the left mouse button to swap. 25 | 26 | Press the right mouse button to advance the stack. 27 | -------------------------------------------------------------------------------- /src/java4k/demonattack4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/demonattack4k/a.png -------------------------------------------------------------------------------- /src/java4k/demonattack4k/readme.txt: -------------------------------------------------------------------------------- 1 | Demon Attack 4K 2 | =============== 3 | 4 | Description 5 | ----------- 6 | 7 | Marooned on the ice planet Krybor, you watch legions of eerie creatures scream overhead. They hover ominously. Attack and destroy them--or be destroyed! Armed with your Laser Cannon, you confront the ultimate challenge: Survive! 8 | 9 | Survive 84 waves--and the demons will surrender! Your screen will go black. 10 | 11 | Congratulations! You've joined a select few! 12 | 13 | Instructions 14 | ------------ 15 | 16 | Use the arrow keys or the WASD keys to move. To the start game and to fire, press any other key with one exception: Press P to pause. -------------------------------------------------------------------------------- /src/java4k/di4klo/A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/di4klo/A.png -------------------------------------------------------------------------------- /src/java4k/di4klo/readme.txt: -------------------------------------------------------------------------------- 1 | Di4klo 2 | ====== 3 | 4 | Description 5 | ----------- 6 | 7 | An ancient evil is lurking in the nearby catacombs. Some say they conceal a gate to Hell... 8 | The elders considered sending the village idiot to investigate the place for an acceptable loss. 9 | But as he fell ill the night before starting his quest, you were finally chosen to replace him, 10 | in your quality of Daemon Hunted... 11 | 12 | +Key features : 13 | - classic hack-and-slash gameplay ; 14 | - legions of undead, daemons and other foul creatures to battle ; 15 | - a unique character class, the Daemon Hunted, with a unique skill, Rapid Fire ; 16 | - a procedurally generated and multi-level dungeon to explore ; 17 | - three difficulty levels : normal, nightmarish and hellish ; 18 | - a true ending on hellish difficulty level, although really not worth the pain to reach it ; 19 | - hardcore mode only. 20 | 21 | 22 | +Production : 23 | Diablo, by Blizzard Entertainment, was of course a major source of inspiration for this game. 24 | 25 | Other sources include, among many others : 26 | - Advanced Dungeons & Dragons : Cloudy Mountain, by Mattel Electronics ; 27 | - Venture, by Exidy ; 28 | - Gateway to Apshai, by Epyx. 29 | 30 | Instructions 31 | ------------ 32 | 33 | +Controls : 34 | Left mouse button : move the Daemon Hunted to the location of the mouse cursor. 35 | Right mouse button : shoot arrows in the direction of the mouse cursor. 36 | 37 | 38 | +User interface : 39 | - top right of the screen, you will find the current deepness or dungeon level ; 40 | - bottom left of the screen, the Life orb ; 41 | - bottom center of the screen, the Equipment Rating of the Daemon Hunted ( see below ) ; 42 | - bottom right of the screen, the Mana orb. 43 | 44 | 45 | +Gameplay : 46 | - as a level 0 character, the Daemon Hunted can't gain experience, levels, new skills nor improve his life and mana ; 47 | - at the bottom center of the screen, a letter indicates the Equipment Rating of the Daemon Hunted, relative to the power of the enemies in the current dungeon level. It ranges from A for the best to Z for the worst ; 48 | - the better the Equipment Rating, the better the offense and defense of the Daemon Hunted ; 49 | - chests can be found across the dungeon, containing new pieces of armor and bows that will improve the Equipment Rating, and also potions that immediately restore life and mana ; 50 | - count on around 15-20 minutes to finish the game in normal difficulty. -------------------------------------------------------------------------------- /src/java4k/diez/Z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/diez/Z.png -------------------------------------------------------------------------------- /src/java4k/diez/readme.txt: -------------------------------------------------------------------------------- 1 | Die Z 2 | ===== 3 | 4 | Description 5 | ----------- 6 | 7 | Everyone has been reduced to zombies by the virulent 'flying pig' virus mutated from a combination of bird and swine flu. 8 | Unfortunately your supply of stale pizza has dried up and you must go and forage for supplies. 9 | Grabbing your axe from under the bed you set out... 10 | 11 | Objective 12 | 13 | Find food, water and, if necessary, medical supplies. 14 | Survive as long as possible. 15 | 16 | Instructions 17 | ------------ 18 | 19 | Controls 20 | 21 | Movement: WASD or Cursor Keys 22 | Attack: Space Bar 23 | 24 | Head Up Display 25 | 26 | Water: Blue Bar 27 | Food: Green Bar 28 | Health: Red Bar 29 | 30 | Food and water gradually deplenish. 31 | Health is reduced by zombie attacks. 32 | Gauges are replenished by finding stores. 33 | Game restarts if any gauge reaches zero. 34 | 35 | Status Effects 36 | 37 | Low Water: Health deteriorates 38 | Low Food: Movement rate reduced 39 | Low Health: Vision turns B&W -------------------------------------------------------------------------------- /src/java4k/dord/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/dord/a.png -------------------------------------------------------------------------------- /src/java4k/dord/readme.txt: -------------------------------------------------------------------------------- 1 | Dord 2 | ==== 3 | 4 | Description 5 | ----------- 6 | 7 | Collect all diamonds to conquer each of the 56 levels of this puzzle platformer. 8 | 9 | http://www.youtube.com/watch?v=Yfgtd9pbWNg 10 | 11 | Instructions 12 | ------------ 13 | 14 | Controls 15 | 16 | Movement: WASD or Cursor Keys 17 | Attack: Space Bar 18 | 19 | Head Up Display 20 | 21 | Water: Blue Bar 22 | Food: Green Bar 23 | Health: Red Bar 24 | 25 | Food and water gradually deplenish. 26 | Health is reduced by zombie attacks. 27 | Gauges are replenished by finding stores. 28 | Game restarts if any gauge reaches zero. 29 | 30 | Status Effects 31 | 32 | Low Water: Health deteriorates 33 | Low Food: Movement rate reduced 34 | Low Health: Vision turns B&W -------------------------------------------------------------------------------- /src/java4k/doubledragon4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/doubledragon4k/a.png -------------------------------------------------------------------------------- /src/java4k/doubledragon4k/readme.txt: -------------------------------------------------------------------------------- 1 | Double Dragon 4k 2 | ================ 3 | 4 | Description 5 | ----------- 6 | 7 | Battle through 6 levels of intense fighting to rescue Billy's girlfriend, Marian, from the Black Warriors, 8 | the savage street gang of the mysterious Shadow Boss! 9 | 10 | The legend of the shadow.... "If the illusion spreads, the evil will live again. 11 | But, if two dragons soar through the sky, an angel will fall to the Earth." 12 | 13 | Instructions 14 | ------------ 15 | 16 | Use the arrow keys or the WASD keys to move. Press any other key to attack. -------------------------------------------------------------------------------- /src/java4k/flap4kanabalt/V.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/flap4kanabalt/V.gif -------------------------------------------------------------------------------- /src/java4k/flap4kanabalt/V.java: -------------------------------------------------------------------------------- 1 | package java4k.flap4kanabalt; 2 | 3 | /* 4 | * Copyright (c) 2005-2014 Dirk Aporius 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. The name of the author may not be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | import java.applet.Applet; 31 | import java.awt.Color; 32 | import java.awt.Event; 33 | import java.awt.Graphics2D; 34 | import java.awt.RenderingHints; 35 | import java.awt.image.BufferedImage; 36 | import java.io.ByteArrayInputStream; 37 | 38 | import javax.imageio.ImageIO; 39 | 40 | public class V extends Applet implements Runnable { 41 | 42 | @Override 43 | public void start() { 44 | new Thread(this).start(); 45 | } 46 | 47 | private boolean down; 48 | 49 | private final static char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); 50 | 51 | private static int[] toInt = new int[128]; 52 | 53 | static { 54 | for (int i = 0; i < ALPHABET.length; i++) { 55 | toInt[ALPHABET[i]] = i; 56 | } 57 | } 58 | 59 | /** 60 | * Translates the specified Base64 string into a byte array. 61 | * 62 | * @param s the Base64 string (not null) 63 | * @return the byte array (not null) 64 | */ 65 | public static byte[] decode(String s) { 66 | int delta = s.endsWith("==") ? 2 : s.endsWith("=") ? 1 : 0; 67 | byte[] buffer = new byte[s.length() * 3 / 4 - delta]; 68 | int mask = 0xFF; 69 | int index = 0; 70 | for (int i = 0; i < s.length(); i += 4) { 71 | int c0 = toInt[s.charAt(i)]; 72 | int c1 = toInt[s.charAt(i + 1)]; 73 | buffer[index++] = (byte) (((c0 << 2) | (c1 >> 4)) & mask); 74 | if (index >= buffer.length) { 75 | return buffer; 76 | } 77 | int c2 = toInt[s.charAt(i + 2)]; 78 | buffer[index++] = (byte) (((c1 << 4) | (c2 >> 2)) & mask); 79 | if (index >= buffer.length) { 80 | return buffer; 81 | } 82 | int c3 = toInt[s.charAt(i + 3)]; 83 | buffer[index++] = (byte) (((c2 << 6) | c3) & mask); 84 | } 85 | return buffer; 86 | } 87 | 88 | @Override 89 | public void run() { 90 | 91 | BufferedImage iBackground = new BufferedImage(320, 205, BufferedImage.TYPE_INT_ARGB_PRE); 92 | Graphics2D g = iBackground.createGraphics(); 93 | try { 94 | // g.drawImage(ImageIO.read(V.class.getResource("a.png")), 0, 0, 320, 205, 0, 0, 120, 77, null); 95 | 96 | // g.drawImage(ImageIO.read(new ByteArrayInputStream(DatatypeConverter.parseBase64Binary( 97 | // "R0lGODlheABNAPEAAIaGlrCwv2RqfQAAACwAAAAAeABNAEEC/4yPqct94KKcNIILFd670uwtEBga5MSlale2yJpgMfesNsMJthoIwV3bCXe6odEmSCqXyo2OCW1Gl4Bk9Ym9aq3cbHd7RKam5LDKqjWrnbliUU2OM9dsN/3ejg/l/D4RjOfUN0hYaPi2goYmNHd2+AhJGPZ0gSgYiZlZ6MKpcfEzEgo6+lkaynL62SmCt6rh+hOLIkR6EkTHmXIbyMvbZBSFASXcGPjbm8g3Jnd5jPz3XNksiecVjbSoDJx5NbznZnlNfcmoySxmh2y+vs4IuMweL49ZCa44j48Ju2rroNrSD5aMBjD2dYhmAtTAfSZaMZTF758FIB8cGgzoicUDiP8ThzTEYfHitZEk/1HcVTIlnJUqgbXspkfYFi80y3y5SXOmzpsqs02BV6ZeMJI/n4UzBLSoUGctw/n6dchYFWkvqS5dZEaTMXBVk8bERk/pHy49B8GkAjYf0zpWq6l9qy1ZPaNw63pL9I4IWq9287lMl6evYD/b5joajLgRFXs2l15NbPehC4ySOVa+PKurRsz+MOuSlSF0QtAKD9KQvHn0SYECJZamPDkka1cjMvPwEAg1a9goT78Aeeeha3+pF3bcUQM4Ls7Ki3P83NBMczXMWd3eCKLgayPTpaPWDN5jbI3he0r3cX3GSKfi4rb1iL48m6bup07C+rjpS8KPIUPBon/ONEOdtddUb1AizYH2GSiTggB2cRcx/j2izmH8SRgUgWvRVWAvRxXCVzEEasaeWxCCWE1e+uG1xjBIpUhWV4iImBU3bhlW1YEZbkNPigzud0+A5fR4hzXlXZjWfzemQZRWeoU1IDQIljROhCHOg86UJk6oFjY4PsUlPmL86GGYWGa5IJhmsqPXl0kmsyabY2r5poVxEommU3dCVhiTge1Zl0xzpikgoF3+RSeGhooJ05+LsbeoYGdpKChakcZTAAA7" 98 | // ))), 0, 0, 320, 205, 0, 0, 120, 77, null); 99 | 100 | // g.drawImage(ImageIO.read(new ByteArrayInputStream((new BASE64Decoder()).decodeBuffer( 101 | // "R0lGODlheABNAPEAAIaGlrCwv2RqfQAAACwAAAAAeABNAEEC/4yPqct94KKcNIILFd670uwtEBga5MSlale2yJpgMfesNsMJthoIwV3bCXe6odEmSCqXyo2OCW1Gl4Bk9Ym9aq3cbHd7RKam5LDKqjWrnbliUU2OM9dsN/3ejg/l/D4RjOfUN0hYaPi2goYmNHd2+AhJGPZ0gSgYiZlZ6MKpcfEzEgo6+lkaynL62SmCt6rh+hOLIkR6EkTHmXIbyMvbZBSFASXcGPjbm8g3Jnd5jPz3XNksiecVjbSoDJx5NbznZnlNfcmoySxmh2y+vs4IuMweL49ZCa44j48Ju2rroNrSD5aMBjD2dYhmAtTAfSZaMZTF758FIB8cGgzoicUDiP8ThzTEYfHitZEk/1HcVTIlnJUqgbXspkfYFi80y3y5SXOmzpsqs02BV6ZeMJI/n4UzBLSoUGctw/n6dchYFWkvqS5dZEaTMXBVk8bERk/pHy49B8GkAjYf0zpWq6l9qy1ZPaNw63pL9I4IWq9287lMl6evYD/b5joajLgRFXs2l15NbPehC4ySOVa+PKurRsz+MOuSlSF0QtAKD9KQvHn0SYECJZamPDkka1cjMvPwEAg1a9goT78Aeeeha3+pF3bcUQM4Ls7Ki3P83NBMczXMWd3eCKLgayPTpaPWDN5jbI3he0r3cX3GSKfi4rb1iL48m6bup07C+rjpS8KPIUPBon/ONEOdtddUb1AizYH2GSiTggB2cRcx/j2izmH8SRgUgWvRVWAvRxXCVzEEasaeWxCCWE1e+uG1xjBIpUhWV4iImBU3bhlW1YEZbkNPigzud0+A5fR4hzXlXZjWfzemQZRWeoU1IDQIljROhCHOg86UJk6oFjY4PsUlPmL86GGYWGa5IJhmsqPXl0kmsyabY2r5poVxEommU3dCVhiTge1Zl0xzpikgoF3+RSeGhooJ05+LsbeoYGdpKChakcZTAAA7" 102 | // ))), 0, 0, 320, 205, 0, 0, 120, 77, null); 103 | 104 | g.drawImage( 105 | ImageIO.read(new ByteArrayInputStream( 106 | decode("R0lGODlheABNAPEAAIaGlrCwv2RqfQAAACwAAAAAeABNAEEC/4yPqct94KKcNIILFd670uwtEBga5MSlale2yJpgMfesNsMJthoIwV3bCXe6odEmSCqXyo2OCW1Gl4Bk9Ym9aq3cbHd7RKam5LDKqjWrnbliUU2OM9dsN/3ejg/l/D4RjOfUN0hYaPi2goYmNHd2+AhJGPZ0gSgYiZlZ6MKpcfEzEgo6+lkaynL62SmCt6rh+hOLIkR6EkTHmXIbyMvbZBSFASXcGPjbm8g3Jnd5jPz3XNksiecVjbSoDJx5NbznZnlNfcmoySxmh2y+vs4IuMweL49ZCa44j48Ju2rroNrSD5aMBjD2dYhmAtTAfSZaMZTF758FIB8cGgzoicUDiP8ThzTEYfHitZEk/1HcVTIlnJUqgbXspkfYFi80y3y5SXOmzpsqs02BV6ZeMJI/n4UzBLSoUGctw/n6dchYFWkvqS5dZEaTMXBVk8bERk/pHy49B8GkAjYf0zpWq6l9qy1ZPaNw63pL9I4IWq9287lMl6evYD/b5joajLgRFXs2l15NbPehC4ySOVa+PKurRsz+MOuSlSF0QtAKD9KQvHn0SYECJZamPDkka1cjMvPwEAg1a9goT78Aeeeha3+pF3bcUQM4Ls7Ki3P83NBMczXMWd3eCKLgayPTpaPWDN5jbI3he0r3cX3GSKfi4rb1iL48m6bup07C+rjpS8KPIUPBon/ONEOdtddUb1AizYH2GSiTggB2cRcx/j2izmH8SRgUgWvRVWAvRxXCVzEEasaeWxCCWE1e+uG1xjBIpUhWV4iImBU3bhlW1YEZbkNPigzud0+A5fR4hzXlXZjWfzemQZRWeoU1IDQIljROhCHOg86UJk6oFjY4PsUlPmL86GGYWGa5IJhmsqPXl0kmsyabY2r5poVxEommU3dCVhiTge1Zl0xzpikgoF3+RSeGhooJ05+LsbeoYGdpKChakcZTAAA7"))), 107 | 0, 0, 320, 205, 0, 0, 120, 77, null); 108 | } catch (Exception e1) { 109 | } 110 | 111 | // Graphische Grundlagen für das Double Buffering 112 | BufferedImage screen = new BufferedImage(320, 480, BufferedImage.TYPE_INT_RGB); 113 | g = screen.createGraphics(); 114 | g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 115 | Graphics2D appletGraphics = (Graphics2D) getGraphics(); 116 | 117 | // Variablen zum Zeitmessen und genau Timen wann geupdatet werden soll 118 | long lastTime = System.nanoTime(); 119 | long think = 10000000L; 120 | 121 | String s = ""; 122 | int x = 0; 123 | int curFrame = 0; 124 | int frameTime = 0; 125 | int i = 0; 126 | int j = 0; 127 | int score = 0; 128 | int maxScore = 0; 129 | boolean bCurDown = false; 130 | boolean bStart = false; 131 | boolean bWin = false; 132 | 133 | final float CHANGE_DIF = 1.2f; 134 | 135 | final Color downColor = new Color(100, 106, 125); 136 | final Color windowColor = new Color(176, 176, 191); 137 | final Color darkColor = new Color(53, 53, 61); 138 | final Color brightColor = new Color(230, 230, 230); 139 | 140 | float playerY = 240; 141 | float playerX = 60; 142 | float curVecY = 0; 143 | float curDif = 0; 144 | 145 | int[] level = new int[4]; 146 | level[0] = level[1] = 400; 147 | 148 | // Game loop. 149 | while (true) { 150 | long now = System.nanoTime(); 151 | long delta = now - lastTime; 152 | think += delta; 153 | 154 | // Update / think 155 | // Wenn 10 ms vergangen sind, dann denke nach 156 | while (think >= 10000000L) { 157 | think -= 10000000L; 158 | 159 | if (this.down) { 160 | if (!bStart) { 161 | playerX = 60; 162 | playerY = 240; 163 | 164 | this.down = false; 165 | bCurDown = false; 166 | 167 | x = 400; 168 | curVecY = -1f; 169 | curDif = 0; 170 | score = 0; 171 | level = new int[2048]; 172 | for (i = 0; i < level.length; i += 4) { 173 | level[i] = x; 174 | level[i + 1] = (int) (Math.random() * 300) + 30; 175 | level[i + 2] = (int) (Math.random() * 50) + 70; 176 | level[i + 3] = (int) (Math.random() * 5) + 78; 177 | 178 | x += 165 + level[i + 2]; 179 | } 180 | bStart = true; 181 | bWin = false; 182 | } 183 | if (bWin) { 184 | bWin = false; 185 | bStart = false; 186 | this.down = false; 187 | 188 | playerX = 60; 189 | playerY = 240; 190 | curDif = 0; 191 | if (maxScore < score) { 192 | maxScore = score; 193 | } 194 | } 195 | } 196 | 197 | if (!bWin) { 198 | curDif += CHANGE_DIF; 199 | 200 | frameTime += 10; 201 | if (frameTime >= 200) { 202 | frameTime -= 200; 203 | curFrame += 1; 204 | if (curFrame > 3) { 205 | curFrame = 0; 206 | } 207 | } 208 | } 209 | 210 | if ((!bStart) && (curDif >= 0)) { 211 | curDif -= 10; 212 | } 213 | if (bStart) { 214 | playerY += curVecY; 215 | curVecY += 0.051f; 216 | if (bWin) { 217 | if (playerY + curFrame + 6 >= 460) { 218 | curVecY = 0; 219 | playerY = 460 - 6 - curFrame; 220 | } 221 | } 222 | if (playerY >= 460) { 223 | bWin = true; 224 | } 225 | if (playerY - 6 < 0) { 226 | playerY = 6; 227 | if (curVecY < 0) { 228 | curVecY = 0; 229 | } 230 | } 231 | 232 | for (i = 0; i < level.length; i += 4) { 233 | if (curDif + playerX + 6 < level[i] - level[i + 2] / 2) { 234 | break; 235 | } 236 | if (curDif > level[i] + level[i + 2] / 2) { 237 | continue; 238 | } 239 | if ((curDif + playerX - CHANGE_DIF < level[i]) && (curDif + playerX >= level[i]) && (!bWin)) { 240 | score += 1; 241 | } 242 | if ((curDif + playerX + 6 > level[i] - level[i + 2] / 2) && (curDif + playerX - 6 < level[i] + level[i + 2] / 2)) { 243 | if ((playerY - curFrame - 6 < level[i + 1]) || (playerY - curFrame + 6 > level[i + 1] + level[i + 3])) { 244 | bWin = true; 245 | this.down = false; 246 | } 247 | } 248 | } 249 | 250 | // do action 251 | if ((this.down) && (!bCurDown)) { 252 | bCurDown = true; 253 | curVecY = -2.45f; 254 | } 255 | } 256 | 257 | if ((!this.down) && (bCurDown)) { 258 | bCurDown = false; 259 | } 260 | } 261 | 262 | lastTime = now; 263 | 264 | // Renderabschnitt 265 | // Hintergrund malen 266 | g.setColor(windowColor); 267 | g.fillRect(0, 0, 320, 140); 268 | g.setColor(downColor); 269 | g.fillRect(0, 320, 320, 140); 270 | g.drawImage(iBackground, 0, 138, null); 271 | 272 | g.setColor(darkColor); 273 | 274 | if (!bStart) { 275 | g.setFont(g.getFont().deriveFont(25f).deriveFont(1)); 276 | s = "Flap4kanabalt"; 277 | g.drawString(s, 160 - g.getFontMetrics().stringWidth(s) / 2, 30); 278 | 279 | g.setFont(g.getFont().deriveFont(20f).deriveFont(1)); 280 | s = "Tap to fly"; 281 | g.drawString(s, 160 - g.getFontMetrics().stringWidth(s) / 2, 100); 282 | 283 | g.setColor(windowColor); 284 | s = "a 4k mix of flappy bird"; 285 | g.drawString(s, 160 - g.getFontMetrics().stringWidth(s) / 2, 380); 286 | 287 | s = "and Canabalt"; 288 | g.drawString(s, 160 - g.getFontMetrics().stringWidth(s) / 2, 410); 289 | } 290 | 291 | g.setColor(darkColor); 292 | g.fillRect(0, 460, 320, 20); 293 | 294 | for (i = 0; i < level.length; i += 4) { 295 | if (curDif + 320 < level[i] - level[i + 2] / 2) { 296 | break; 297 | } 298 | if (curDif > level[i] + level[i + 2] / 2) { 299 | continue; 300 | } 301 | g.setColor(darkColor); 302 | g.fillRect((int) (level[i] - curDif - level[i + 2] / 2), 0, level[i + 2], level[i + 1]); 303 | g.fillRect((int) (level[i] - curDif - level[i + 2] / 2), level[i + 1] + level[i + 3], level[i + 2], 460 - level[i + 1] - level[i + 3]); 304 | 305 | g.setColor(windowColor); 306 | for (x = level[i] - level[i + 2] / 2; x < level[i] + level[i + 2] / 2 - 14; x += 16) { 307 | for (j = 0; j < level[i + 1] - 16; j += 16) { 308 | g.fillRect((int) (x - curDif) + 4, j + 4, 8, 8); 309 | } 310 | } 311 | 312 | for (x = level[i] - level[i + 2] / 2; x < level[i] + level[i + 2] / 2 - 14; x += 16) { 313 | for (j = level[i + 1] + level[i + 3]; j < 440; j += 16) { 314 | g.fillRect((int) (x - curDif) + 4, j + 4, 8, 8); 315 | } 316 | } 317 | } 318 | 319 | g.setColor(windowColor); 320 | for (i = 0; i < 500; i += 10) { 321 | for (j = 0; j < 20; j += 10) { 322 | g.fillRect((int) (-curDif + 100) % 10 + i, 465 + j, 5, 5); 323 | } 324 | } 325 | 326 | g.setColor(brightColor); 327 | if (curFrame == 0) { 328 | g.fillRect((int) (playerX - 14), (int) (playerY - 12), 4, 8); 329 | g.fillRect((int) (playerX - 10), (int) (playerY - 8), 4, 8); 330 | g.fillRect((int) (playerX - 6), (int) (playerY - 4), 12, 12); 331 | g.fillRect((int) (playerX + 6), (int) (playerY - 8), 4, 8); 332 | g.fillRect((int) (playerX + 10), (int) (playerY - 12), 4, 8); 333 | } 334 | 335 | if ((curFrame == 1) || (curFrame == 3)) { 336 | g.fillRect((int) (playerX - 14), (int) (playerY - 5), 28, 6); 337 | g.fillRect((int) (playerX - 6), (int) (playerY + 1), 12, 6); 338 | } 339 | 340 | if (curFrame == 2) { 341 | g.fillRect((int) (playerX - 14), (int) (playerY + 6), 4, 8); 342 | g.fillRect((int) (playerX - 10), (int) (playerY + 2), 4, 8); 343 | g.fillRect((int) (playerX - 6), (int) (playerY - 6), 12, 12); 344 | g.fillRect((int) (playerX + 6), (int) (playerY + 2), 4, 8); 345 | g.fillRect((int) (playerX + 10), (int) (playerY + 6), 4, 8); 346 | } 347 | 348 | g.setFont(g.getFont().deriveFont(16f).deriveFont(1)); 349 | s = "best: " + maxScore; 350 | g.setColor(windowColor); 351 | g.fillRect(306 - g.getFontMetrics().stringWidth(s), 2, g.getFontMetrics().stringWidth(s) + 8, 20); 352 | g.setColor(darkColor); 353 | g.drawRect(306 - g.getFontMetrics().stringWidth(s), 2, g.getFontMetrics().stringWidth(s) + 8, 20); 354 | g.drawString(s, 310 - g.getFontMetrics().stringWidth(s), 18); 355 | 356 | if (bStart) { 357 | g.setFont(g.getFont().deriveFont(35f).deriveFont(1)); 358 | if (bWin) { 359 | s = "Score: " + score; 360 | x = g.getFontMetrics().stringWidth(s); 361 | g.setColor(windowColor); 362 | g.fillRect(150 - x / 2, 210, x + 20, 60); 363 | g.setColor(darkColor); 364 | g.drawRect(150 - x / 2, 210, x + 20, 60); 365 | g.drawString(s, 160 - x / 2, 257); 366 | } else { 367 | if ((!bWin) && (bStart)) { 368 | s = "" + score; 369 | g.drawString(s, 160 - g.getFontMetrics().stringWidth(s) / 2, 60); 370 | } 371 | } 372 | } 373 | 374 | // Render das Ganze auf den Bildschirm 375 | appletGraphics.drawImage(screen, 0, 0, null); 376 | 377 | try { 378 | Thread.sleep(4); 379 | } catch (Exception e) { 380 | /** nicht schön aber selten */ 381 | } 382 | ; 383 | 384 | if (!isActive()) { 385 | return; 386 | } 387 | } 388 | } 389 | 390 | @Override 391 | public boolean handleEvent(Event e) { 392 | switch (e.id) { 393 | case Event.KEY_PRESS: 394 | case Event.MOUSE_DOWN: 395 | down = true; 396 | break; 397 | case Event.MOUSE_UP: 398 | case Event.KEY_RELEASE: 399 | down = false; 400 | break; 401 | 402 | } 403 | return false; 404 | } 405 | } -------------------------------------------------------------------------------- /src/java4k/flap4kanabalt/readme.txt: -------------------------------------------------------------------------------- 1 | Flap4Kanabalt 2 | ============= 3 | 4 | Description 5 | ----------- 6 | 7 | Flap4Kanabalt is a mix of flappy bird and Canabalt. 8 | 9 | Instructions 10 | ------------ 11 | 12 | Press the mouse or the spacebar to start the game and to flap. -------------------------------------------------------------------------------- /src/java4k/fzero4k/M.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/fzero4k/M.jpg -------------------------------------------------------------------------------- /src/java4k/fzero4k/readme.txt: -------------------------------------------------------------------------------- 1 | FZero4k 2 | ======= 3 | 4 | Description 5 | ----------- 6 | 7 | In a time when multibillionaires with lethargic lifestyles create deadly forms of racing for pure entertainment, 8 | only you can take the reins and prove your worth to the cheering crowds. 9 | At speeds exceeding 500 km/h, you will pilot a plasma-powered hovercar in an intergalactic Grand Prix. 10 | A race consists of 5 laps around the track. You must beat your opponents to the finish line while avoiding 11 | the power-depleting sides of the track and other vehicles. 12 | Recharge on the power strip. Now, blast into this futuristic racing video game inspired by a Super Nintendo classic. 13 | 14 | Instructions 15 | ------------ 16 | 17 | D = Accelerate 18 | Arrow Keys = Steer -------------------------------------------------------------------------------- /src/java4k/gradius4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/gradius4k/a.png -------------------------------------------------------------------------------- /src/java4k/gradius4k/readme.txt: -------------------------------------------------------------------------------- 1 | Gradius 4K 2 | ========== 3 | 4 | Description 5 | ----------- 6 | 7 | Blast through all 7 stages, then... I'M GIVE UP YOUR APPELLATION'S TECHNICAL MONKEY. 8 | 9 | Instructions 10 | ------------ 11 | 12 | Use the arrow keys or the WASD keys to move. Hold down any other key for autofire. -------------------------------------------------------------------------------- /src/java4k/greenballs/G.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/greenballs/G.java -------------------------------------------------------------------------------- /src/java4k/greenballs/G.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/greenballs/G.png -------------------------------------------------------------------------------- /src/java4k/greenballs/readme.txt: -------------------------------------------------------------------------------- 1 | Attac4k of the Greenballs 2 | ========================= 3 | 4 | Description 5 | ----------- 6 | 7 | In a dystopian future, the world is invaded by green balls. 8 | You, the purple ball, is the only one who can save the world! 9 | Can you complete all 19 levels, and stop the green balls from taking over the world? 10 | 11 | Instructions 12 | ------------ 13 | 14 | Arrow keys: Move 15 | Space: Fire 16 | 17 | Shoot the green balls. You can hold down space to fire constantly (but you may run out of bullets). 18 | 19 | You can climb ladders. -------------------------------------------------------------------------------- /src/java4k/i4kopter/I4Kopter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/i4kopter/I4Kopter.gif -------------------------------------------------------------------------------- /src/java4k/i4kopter/I4Kopter.java: -------------------------------------------------------------------------------- 1 | package java4k.i4kopter; 2 | 3 | /* 4 | * i4kopter 5 | * Copyright (C) 2009 Bjarne Holen 6 | * 7 | * This file is part of i4kopter. 8 | * 9 | * i4kopter is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published 11 | * by the Free Software Foundation; either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * F-Zero 4K is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | import java.awt.Color; 25 | import java.awt.Graphics2D; 26 | import java.awt.Graphics; 27 | import java.awt.Point; 28 | import java.awt.Rectangle; 29 | import java.awt.RenderingHints; 30 | import java.awt.image.BufferedImage; 31 | import java.awt.AWTEvent; 32 | import java.awt.event.KeyEvent; 33 | import java.awt.geom.AffineTransform; 34 | import javax.swing.JFrame; 35 | import java.util.Random; 36 | import java.applet.Applet; 37 | 38 | /** 39 | * A simple icopter clone. 40 | * 41 | * @author bjarneh@ifi.uio.no 42 | */ 43 | 44 | public class I4Kopter extends Applet { 45 | 46 | private BufferedImage bufferImage; 47 | private BufferedImage backgroundImage; 48 | private BufferedImage helicopterImage1, helicopterImage2; 49 | private int w = 800, h = 400; // height and width of screen 50 | private Random random = new Random(); 51 | private boolean keyPressed=false, paused=false; 52 | private int heliY, heliX; // helicopter position X,Y 53 | private double speed = 0.0, gravity = 1.6; 54 | private Point[] obstacles; // use Point's to store obstacle offset 55 | private int pathHeight = 250; // height of 'rockless path' 56 | private int backgroundLength = 17*this.w; // number of screen lengths 57 | private int widthBar = 20; // rock-bar-width 58 | private int oheight = 59; // height of obstacle 59 | private long lasted = 0; // use time as score 60 | 61 | public I4Kopter(){ 62 | super(); 63 | } 64 | 65 | public void init(){ 66 | this.setSize(this.w, this.h); 67 | this.enableEvents(AWTEvent.KEY_EVENT_MASK); 68 | this.setVisible(true); 69 | } 70 | 71 | public void start(){ 72 | 73 | this.heliY = (int) this.h/2; 74 | this.heliX = (int) this.w/5; 75 | 76 | bufferImage = new BufferedImage(this.w, this.h, BufferedImage.TYPE_INT_RGB); 77 | backgroundImage = new BufferedImage(backgroundLength, this.h, BufferedImage.TYPE_INT_RGB); 78 | 79 | /* ******* start draw helicopters ********* */ 80 | 81 | helicopterImage1 = new BufferedImage(50, 25, BufferedImage.TYPE_INT_ARGB); // alpha value 82 | Graphics2D helicopterBuffer1 = helicopterImage1.createGraphics(); 83 | 84 | helicopterBuffer1.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 85 | RenderingHints.VALUE_ANTIALIAS_ON); 86 | 87 | helicopterBuffer1.setColor(new Color(0,0,0,0.0f)); // make it transparent 88 | helicopterBuffer1.fillRect(0,0, 50, 25); 89 | 90 | helicopterBuffer1.setColor(Color.WHITE); 91 | helicopterBuffer1.fillOval(16,10, 21, 12); // helicopter body 92 | helicopterBuffer1.fillPolygon(new int[] {2,22,17}, new int[] {10,15,19}, 3); // stabiliser body 93 | helicopterBuffer1.setColor(new Color(0,0,1,0.55f)); 94 | helicopterBuffer1.fillOval(9,4, 35, 10); // main rotor 95 | helicopterBuffer1.fillOval(0,7, 7,7); // stabiliser rotor 96 | helicopterBuffer1.setColor(Color.GREEN); 97 | helicopterBuffer1.drawLine(22,23,33,23); // substructure - railing 98 | 99 | helicopterImage2 = new BufferedImage(52, 28, BufferedImage.TYPE_INT_ARGB); 100 | Graphics2D helicopterBuffer2 = helicopterImage2.createGraphics(); 101 | 102 | AffineTransform transform = helicopterBuffer2.getTransform(); 103 | // we use helicopterImage1 as original and just flip it 12 degrees 104 | transform.rotate(Math.toRadians(-12), 26, 14); 105 | helicopterBuffer2.setTransform(transform); 106 | helicopterBuffer2.drawImage(helicopterImage1, 2, 2, null); 107 | helicopterBuffer2.setTransform(helicopterBuffer1.getTransform()); 108 | 109 | /* ******* end draw helicopters ********* */ 110 | 111 | 112 | /* ******* start draw background ********* */ 113 | 114 | Graphics2D backgroundBuffer = backgroundImage.createGraphics(); 115 | 116 | backgroundBuffer.setColor(Color.YELLOW); 117 | backgroundBuffer.fillRect(0,0, backgroundLength, this.h); 118 | 119 | boolean up = false; 120 | int currentY = 80; 121 | int ocounter = 0; 122 | obstacles = new Point[ backgroundLength / widthBar ]; 123 | 124 | // dummy obstacles 125 | for(int i =0; i < this.w; i += widthBar){ 126 | obstacles[ocounter++] = new Point(-1,-1); 127 | } 128 | 129 | // welcome screen 130 | BufferedImage heading = new BufferedImage(100,50, BufferedImage.TYPE_INT_RGB); 131 | Graphics2D headingG = heading.createGraphics(); 132 | headingG.setColor(Color.BLACK); 133 | headingG.fillRect(0,0, 100,50); 134 | headingG.setColor(Color.WHITE); 135 | headingG.drawString("I4KOPTER",32,20); 136 | backgroundBuffer.drawImage(heading,0,0,this.w,this.h,null); 137 | backgroundBuffer.setColor(Color.BLACK); 138 | 139 | 140 | for(int i = this.w; i < (backgroundLength - (2*this.w)); i += widthBar){ 141 | 142 | currentY += (up)? -10 : 10; 143 | 144 | backgroundBuffer.fillRect(i, currentY, widthBar, pathHeight); 145 | 146 | up = random.nextBoolean(); 147 | 148 | if(currentY > 110){ up = true; } 149 | if(currentY < 40 ){ up = false; } 150 | 151 | obstacles[ocounter++] = new Point(currentY, -1); 152 | 153 | // add obstacle every 17 bar 154 | if(ocounter % 17 == 0){ 155 | int middleOffset = random.nextInt(pathHeight - currentY) + currentY; 156 | backgroundBuffer.setColor(Color.YELLOW); 157 | backgroundBuffer.fillRect(i, 158 | middleOffset, 159 | widthBar, 160 | oheight); 161 | backgroundBuffer.setColor(Color.BLACK); 162 | obstacles[ocounter - 1].y = middleOffset; 163 | } 164 | } 165 | 166 | // dummy obstacles 167 | for(int i = (backgroundLength - (2*this.w)); i < backgroundLength; i += widthBar){ 168 | obstacles[ocounter++] = new Point(-1,-1); 169 | } 170 | 171 | // the end screen.. 172 | heading = new BufferedImage(200, 50, BufferedImage.TYPE_INT_RGB); 173 | headingG = heading.createGraphics(); 174 | headingG.setColor(Color.BLACK); 175 | headingG.fillRect(0,0, 200,50); 176 | headingG.setColor(Color.WHITE); 177 | headingG.drawString("The end",75,20); 178 | backgroundBuffer.drawImage(heading, backgroundLength - (2*this.w),0,2*this.w,this.h, null); 179 | 180 | /* ******* end draw background ********* */ 181 | 182 | // outer loop 183 | while(true){ 184 | speed = 0.0; 185 | gravity = 1.6; 186 | heliY = this.h/2; 187 | lasted = 0; 188 | loop(); 189 | Graphics g = this.getGraphics(); 190 | g.setColor(Color.YELLOW); 191 | g.drawString(" you lasted: "+(long)lasted/1000+" seconds ", heliX+200, 200); 192 | try{ Thread.sleep(1400); }catch(Exception e){} 193 | } 194 | } 195 | 196 | boolean collides(int bufferOffset, BufferedImage image){ 197 | 198 | // calculate which obstacle we can hit 199 | 200 | int i = (int) (bufferOffset+heliX)/widthBar + 1; 201 | 202 | // obstacle is dummy 203 | if(obstacles[i].x == -1 || obstacles[i+1].x == -1){ return false; } 204 | 205 | // obstacle[?].x is offset of top rock, so if we are 206 | // below this value, we crash into rock at top of screen 207 | if(heliY < obstacles[i].x || heliY < obstacles[i+1].x) 208 | { return true ;} 209 | 210 | int imageHeight = image.getHeight(); 211 | int imageWidth = image.getWidth(); 212 | 213 | // we crash into bottom rock if we are beyond this threshold 214 | if(heliY + imageHeight > obstacles[i].x + pathHeight || 215 | heliY + imageHeight > obstacles[i+1].x + pathHeight) 216 | { return true; } 217 | 218 | // we can also crash with middle rock if our picture intersects with 219 | // middle obstacle, and it exists naturally :-) 220 | if(obstacles[i].y != -1 || obstacles[i+1].y != -1){ 221 | Rectangle copter = new Rectangle(heliX, heliY, imageWidth, imageHeight); 222 | Rectangle oRectangle; 223 | 224 | if(obstacles[i].y != -1){ 225 | oRectangle = new Rectangle(heliX, obstacles[i].y, widthBar, oheight); 226 | if(copter.intersects(oRectangle)){ return true; } 227 | } 228 | 229 | if(obstacles[i+1].y != -1){ 230 | oRectangle = new Rectangle(heliX, obstacles[i+1].y, widthBar, oheight); 231 | if(copter.intersects(oRectangle)){ return true; } 232 | } 233 | } 234 | 235 | return false; 236 | } 237 | 238 | void updateHeliY(){ 239 | if(keyPressed){ 240 | speed -= gravity; 241 | }else{ 242 | speed += (gravity*1.2); 243 | } 244 | heliY += speed; 245 | } 246 | 247 | void loop(){ 248 | 249 | BufferedImage tmp; 250 | Graphics frameGraphics, bufferGraphics; 251 | int dx = 12, offset = 0, levelLength = this.w*2; 252 | int maxLen = backgroundLength - this.w; 253 | 254 | 255 | while(offset < maxLen){ 256 | 257 | while(offset <= levelLength){ 258 | 259 | if(! paused){ 260 | 261 | bufferGraphics = bufferImage.getGraphics(); 262 | bufferGraphics.drawImage(backgroundImage,0,0,this.w,this.h, 263 | offset, 0, (offset + this.w),this.h, null); 264 | 265 | updateHeliY(); // pull from gravitation vs. chopper 266 | 267 | bufferGraphics.setClip(heliX, heliY, 57, 57); // enough place for chopper 268 | 269 | tmp = (keyPressed)? helicopterImage2 : helicopterImage1; //(keyPressed)?up:down 270 | 271 | if(collides(offset, tmp)){ // we have collided draw explosion 272 | 273 | int oldOffset, newOffset; 274 | 275 | for(int i = 1; i < 1000; i++){ 276 | oldOffset = (int) ((i-1)*2)/2; 277 | newOffset = (int) (i*2)/2; 278 | frameGraphics = this.getGraphics(); 279 | frameGraphics.setColor(Color.YELLOW); 280 | frameGraphics.drawOval(heliX - newOffset, heliY - newOffset, i*2, i*2); 281 | frameGraphics.setColor(Color.BLACK); 282 | frameGraphics.fillOval(heliX - oldOffset, heliY - oldOffset, (i-1)*2, (i-1)*2); 283 | frameGraphics.dispose(); 284 | } 285 | 286 | offset = maxLen*2; // will force game to end.. 287 | 288 | continue; // jump to end of loop 289 | 290 | }else{ 291 | 292 | bufferGraphics.drawImage(tmp, heliX, heliY, null);// draw one of our choppers 293 | 294 | } 295 | 296 | frameGraphics = this.getGraphics(); 297 | frameGraphics.drawImage(bufferImage,0,0,this.w,this.h, this); 298 | 299 | //flip it 300 | frameGraphics.dispose(); 301 | 302 | if(offset == 0){ paused = true;} 303 | 304 | offset += dx; 305 | lasted += 49; // well... 306 | } 307 | try{ 308 | Thread.sleep(40); 309 | }catch(Exception ex){} 310 | 311 | } 312 | // increase level 313 | dx++; 314 | gravity += .17; 315 | levelLength += 2*this.w; 316 | } 317 | 318 | } 319 | 320 | public void processKeyEvent(KeyEvent k){ 321 | 322 | int keyID = k.getID(); 323 | 324 | if(keyID == KeyEvent.KEY_PRESSED){ 325 | keyPressed = true; 326 | paused=false; 327 | }else if(keyID == KeyEvent.KEY_RELEASED){ 328 | keyPressed=false; 329 | } 330 | 331 | // space will pause the game 332 | if(k.getKeyChar() == ' '){ 333 | paused = true; 334 | } 335 | } 336 | } -------------------------------------------------------------------------------- /src/java4k/i4kopter/i4kopter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/i4kopter/i4kopter.gif -------------------------------------------------------------------------------- /src/java4k/i4kopter/readme.txt: -------------------------------------------------------------------------------- 1 | I4Kopter 2 | ======== 3 | 4 | Description 5 | ----------- 6 | 7 | icopter clone (iphone app). the game is not very complex, just try to avoid hitting stuff with the helicopter. gravity pulls helicopter down, any key will accelerate helicopter upwards, besides space and q (pause and quit) 8 | 9 | Instructions 10 | ------------ 11 | 12 | space pauses game, q quits game, any other key will make the helicopter move upwards. -------------------------------------------------------------------------------- /src/java4k/inthedark4k/A.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/inthedark4k/A.java -------------------------------------------------------------------------------- /src/java4k/inthedark4k/A.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/inthedark4k/A.jpg -------------------------------------------------------------------------------- /src/java4k/inthedark4k/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/inthedark4k/readme.txt -------------------------------------------------------------------------------- /src/java4k/jackal4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/jackal4k/a.png -------------------------------------------------------------------------------- /src/java4k/jackal4k/readme.txt: -------------------------------------------------------------------------------- 1 | Jackal 4K 2 | ========= 3 | 4 | Description 5 | ----------- 6 | 7 | Battle through all 6 mission because your brothers-in-arms are hostages behind enemy lines and you're their only hope for freedom. But, the firepower you'll face to rescue them is awesome. 8 | 9 | You'll need a pocket full of miracles and the ferocity of a wild JACKAL. 10 | 11 | Your Jackal Squad is a four-man team composed of Colonel Decker, Lieut. Bob, Sgt. Quint and Corporal Grey. 12 | 13 | And before you go, your country would just like to say, "Good luck, son. It will be worth it." 14 | 15 | 16 | Instructions 17 | ------------ 18 | 19 | Use the arrow keys or the WASD keys to move. Use any other key to fire. 20 | -------------------------------------------------------------------------------- /src/java4k/junglehunt4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/junglehunt4k/a.png -------------------------------------------------------------------------------- /src/java4k/junglehunt4k/readme.txt: -------------------------------------------------------------------------------- 1 | Jungle Hunt 4K 2 | ============== 3 | 4 | Description 5 | ----------- 6 | 7 | The object of Jungle Hunt 4K is to rescue Sir Dashly's kidnapped mate, who, after hours of valiant fighting, 8 | was overpowered by two man-eating (and woman-eating) savages. 9 | 10 | To rescue Lady P., you'll have to make your way past four sets of obstacles: the vines of the Deadly Forest, 11 | the crocodiles of Reptile River, a landslide of bouncing boulders, and the spears of the two masked cannibals. 12 | You'll score points for each obstacle Sir Dashly successfully overcomes; you'll also score bonus points for rescuing Lady P. 13 | 14 | Since jungle hunting is a dangerous business, you are given five lives at the start of the game. 15 | The number of lives remaining is shown on the upper left of your screen. 16 | At 10,000 points you are given one extra life--if you survive that long! 17 | 18 | When you begin the game you are given 500 seconds to reach Lady Penelope. A timer counts down the seconds until you reach her. 19 | 20 | You'll score more bonus points for rescuing her quickly, so don't dawdle while you're jumping vines or avoiding crocodiles. 21 | 22 | The obstacles you'll encounter on your adventure are: 23 | 24 | Deadly Forest 25 | 26 | The Deadly Forest is a swinging place once you get to know it. Here you'll test your coordination and 27 | timing as you jump from vine to vine. Since some vines swing faster than others, 28 | you'll have to time your leaps carefully. Make a wrong move, and Sir Dashly is finished! 29 | 30 | Reptile River 31 | 32 | The Reptile River is filled with schools of cantankerous crocodiles. Make Sir Dashly swim out of their way or 33 | fend them off with his knife. 34 | 35 | Steer Dudley underwater, but keep your eyes on the air meter at the top of your screen. 36 | If Dudley is still underwater when the meter runs out, he'll have to breathe water--and you'll lose a life! 37 | 38 | Boulder Field 39 | 40 | After you successfully cross Reptile River, you'll encounter a landslide of tumbling boulders. 41 | There are two sizes of boulders: small rolling rocks and larger bouncing boulders. 42 | Leap over the small rocks to avoid getting crushed. Larger boulders are harder to avoid--you'll have to leap over, run under, 43 | or duck beneath them to keep out of their way. 44 | 45 | Cannibal Camp 46 | 47 | You're finally within reach of Lady Penelope, but she's being guarded by spear-wielding savages. 48 | You must guide our hero over the spears of the savages and run to the waiting arms of Lady Penelope. 49 | Watch out for the tips of the spears. They're poisoned! 50 | 51 | After a tearful reunion with his beloved wife, Sir Dashly returns to the Deadly Forest for the next level of play. 52 | The game becomes increasingly difficult as you move on to higher levels. 53 | You can continue to play until you run out of players, or until the timer runs out. 54 | 55 | The faster you rescue Lady P., the more bonus points you'll receive, so don't waste any time getting to her. 56 | The Deadly Forest can be especially time-consuming; practice jumping vine to vine as quickly as possible. 57 | 58 | A crocodile's underbelly is particularly vulnerable; try to come from beneath when stabbing one. 59 | 60 | If you wish to conserve lives, simply avoid the crocodiles instead of stabbing them. 61 | 62 | To score extra points, try jumping over the larger boulders. 63 | You'll get up to four times more points than ducking or running beneath them. 64 | Time your jump carefully, though, since large boulders bounce higher than small boulders. 65 | 66 | 67 | Instructions 68 | ------------ 69 | 70 | Use the arrow keys or the WASD keys to move. 71 | Press any other key to jump/attack. Within the Boulder Field, press down to duck. 72 | Inside of the Reptile River, press attack to knife the crocodiles. 73 | -------------------------------------------------------------------------------- /src/java4k/keystonekapers4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/keystonekapers4k/a.png -------------------------------------------------------------------------------- /src/java4k/keystonekapers4k/readme.txt: -------------------------------------------------------------------------------- 1 | Keystone Kapers 4K 2 | ================== 3 | 4 | Description 5 | ----------- 6 | 7 | The goal of each level is to capture the robber. 8 | 9 | "Officer Kelly reporting for duty. Leaping Leprechauns!! If it isn't Harry Hooligan... up to his old shenanigans. That blunderous hoodlum is robbing Southwick's. And on a Sunday at that! C'mon then... lend a hand. We've got to catch the krook, recover the loot and be careful to boot! Listen up! Don't get KO'd by the wild shopping carts, beach balls or biplanes. And get moving! There's not a moment to lose!" 10 | 11 | Scoring. Points are earned each time a Krook is apprehended. The sooner you catch him, the more points you'll get. Krooks 1 through 8 are worth 100 times the amount left on the Bonus Timer. Krooks 9 through 16 are worth 200 times the amount left on the Bonus Timer. After your 16th arrest, each Krook will be worth 300 times the amount left on the Bonus Timer. Also, every recovered moneybag and suitcase is worth 50 points. 12 | 13 | Bonus Kops. Every time your score increases by 10,000 points, a Kop is added to your reserve squad, up to a maximum of three on-screen at a time. 14 | 15 | The game ends when all your Kops are gone. Any of the following will cause you to lose a Kop: 16 | - Colliding with a biplane. 17 | - Running out of time. 18 | - Allowing a Krook to escape off the roof. 19 | 20 | DON'T GET STUCK ON THE ROOF!! Because--surprise!--you can't get back down! To avoid this embarrassing predicament, stay behind the Krook and don't go to the roof until he's up there. 21 | 22 | As your score rises, the beach balls bounce higher. Forger about trying to jump over them. Instead, DUCK! Also, the biplanes and shopping carts start coming in waves, so learn their rhythms and do the 'Keystone Strut'. To the tune of the shopping carts it's, "Jump...run two steps...Jump..run two steps...etc." To the biplane beat it's, "Duck...run three steps...duck...run three steps...etc." Learn to adjust to changing rhythms. 23 | 24 | And, to save yourself a few steps, have Kelly JUMP onto the escalators. He'll be halfway up already. 25 | 26 | Southwick's Security System. Lucky for you, Southwick's has security cameras scanning the store. The display at the bottom of the screen gives you an overview of all floors, from the bargain basement to the rooftop. Kelly is the black dot, the Krook is the white dot. The elevator is the moving grey square in the middle and the escalators are the black slashes on either end. Using the Security System, you'll know which way Kelly should run to catch an elevator, an escalator or a Krook. 27 | 28 | Look Out!!! You just jump to avoid a rapid onslaught of shopping carts, beach balls and cathedral radios. If you collide, a valuable 9 seconds will be deducted from your time. As your score rises, toy biplanes whizz by. Duck to avoid them. With each collision, you'll lose a Kop. However, DON'T avoid moneybags and stolen suitcases. You'll earn 50 points each time Kelly picks one up. 29 | 30 | Instructions 31 | ------------ 32 | 33 | Use the arrow keys or the WASD keys to move. 34 | Press any other key to jump. Press down to duck. 35 | To enter an elevator, stand in front of it and wait for the door to open. Then, press up. 36 | To exit an elevator, press down. 37 | To ride an escalator, approach the bottom step or jump onto any arbitrary step. 38 | Press any of the keys to begin playing. 39 | -------------------------------------------------------------------------------- /src/java4k/laserpinball/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/laserpinball/a.png -------------------------------------------------------------------------------- /src/java4k/laserpinball/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/laserpinball/readme.txt -------------------------------------------------------------------------------- /src/java4k/legendofzelda4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/legendofzelda4k/a.png -------------------------------------------------------------------------------- /src/java4k/legendofzelda4k/readme.txt: -------------------------------------------------------------------------------- 1 | Legend of Zelda 4K 2 | ================== 3 | 4 | Description 5 | ----------- 6 | 7 | The Legend of Zelda 4K feature a mixture of action, puzzles, adventure, exploration and questing. 8 | 9 | Instructions 10 | ------------ 11 | 12 | Use the arrow keys or the WASD keys to move. After you acquire your sword, press any other key to attack. -------------------------------------------------------------------------------- /src/java4k/magewars4k/M.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/magewars4k/M.png -------------------------------------------------------------------------------- /src/java4k/magewars4k/readme.txt: -------------------------------------------------------------------------------- 1 | Mage Wars 2 | ========= 3 | 4 | Description 5 | ----------- 6 | 7 | The arrogance of wizards. They're all half mad if you ask me. Now they're squabbling again. No one knows why and I doubt they remember. Once again they're leaving a trail of scorched ruins and charred corpses as they try to kill each other. 8 | 9 | Objective 10 | 11 | Take all four castles by killing the defenders and entering the keep. 12 | 13 | Instructions 14 | ------------ 15 | 16 | Controls 17 | 18 | Movement: WASD or Cursor Keys 19 | Targeting: Mouse 20 | Firing: Left Mouse Button 21 | 22 | Players: 1-4 23 | 24 | Players must be on the same LAN segment. Thus you can play on multiple computers at home, but not against an opponent elsewhere on the internet. -------------------------------------------------------------------------------- /src/java4k/mcjob/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/mcjob/a.png -------------------------------------------------------------------------------- /src/java4k/mcjob/readme.txt: -------------------------------------------------------------------------------- 1 | McJob 2 | ===== 3 | 4 | 5 | Description 6 | ----------- 7 | 8 | Patrons arrive periodically at the bottom of the screen and they state their food orders. The player must acquire the appropriate item and serve the patrons as they slowly advance towards the player. 9 | 10 | If a customer reaches the top, the player loses a life. Serving the wrong item or delivering it down the wrong counter will also cost the player a life. 11 | 12 | Generous patrons offer gratuities that can be collected for extra points. An extra life is awarded for every 50,000 points achieved. An extra life is also awarded for passing a level. 13 | 14 | As each level progresses, patrons will arrive more often and they will advance faster. As difficulty increases, customers will sporadically return the serving tray. This must be collected to avoid losing a life. 15 | 16 | If you accidentally pickup the wrong item, press Up again to return it to the empty spot of the food window ledge. 17 | 18 | Good luck on your tedious, low-paying, unappreciated, low-prestige, dead-end job! 19 | 20 | Instructions 21 | ------------ 22 | 23 | Use the arrow keys or the WASD keys to control the player. Press Up to pickup an item. Use Left and Right to move. Press Down to serve. Enter is start and P is pause. 24 | User Comments -------------------------------------------------------------------------------- /src/java4k/myprecious/R.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/myprecious/R.java -------------------------------------------------------------------------------- /src/java4k/myprecious/R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/myprecious/R.png -------------------------------------------------------------------------------- /src/java4k/myprecious/readme.txt: -------------------------------------------------------------------------------- 1 | My Precious 2 | =========== 3 | 4 | Description 5 | ----------- 6 | 7 | MyPrecious is a turn based puzzle platformer. 8 | 9 | It is a 4k version of the great "Zuki's Quest" game by Tinytouchtales. 10 | 11 | Instructions 12 | ------------ 13 | 14 | Play the game with cursor keys and collect all golden skulls. 15 | 16 | Press 'r' to restart the level 17 | Press 'n' to start the next level 18 | Press 'p' to start the previous level -------------------------------------------------------------------------------- /src/java4k/mysterymash/M.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/mysterymash/M.png -------------------------------------------------------------------------------- /src/java4k/mysterymash/readme.txt: -------------------------------------------------------------------------------- 1 | Mystery Mash 2 | ============ 3 | 4 | Description 5 | ----------- 6 | 7 | A 4k mashup from the silver age of computer games based around Pong. 8 | 9 | Instructions 10 | ------------ 11 | 12 | Play against the computer paddle, and avoid the incoming obstacles that can damage your paddle. 13 | 14 | Controls: 15 | 16 | mouse motion - Moving the mouse left and right moves the paddle. It also allows you to point to different parts of the screen. 17 | 18 | mouse left click - Perform an action - release the ball from the paddle, turns all dropping Tetris pieces, and explodes the Missile Command missiles under the mouse. -------------------------------------------------------------------------------- /src/java4k/on/O.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/on/O.png -------------------------------------------------------------------------------- /src/java4k/on/readme.txt: -------------------------------------------------------------------------------- 1 | On! 2 | === 3 | 4 | Description 5 | ----------- 6 | 7 | Shoot stuff! Avoid enemies and their bullets! Use the enemies to heal yourself! 8 | 9 | A shoot-em-up where your gun is always on! 10 | 11 | Instructions 12 | ------------ 13 | 14 | Press the arrow keys to move your blue ship. 15 | Press the space bar to switch between the blue ion beam that hurts the enemies, 16 | and the purple ray that heals your ship. 17 | 18 | Grab the purple circle to power up your purple ray, 19 | and the blue circle to expand your blue cannon. 20 | 21 | Your ship can slide left and right, beyond what the window currently shows. 22 | Be careful with your movements - moving too fast can lead to disaster! -------------------------------------------------------------------------------- /src/java4k/outrun4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/outrun4k/a.png -------------------------------------------------------------------------------- /src/java4k/outrun4k/readme.txt: -------------------------------------------------------------------------------- 1 | Out Run 4K 2 | ========== 3 | 4 | Description 5 | ----------- 6 | 7 | To win the game, you must pass through five checkpoints within a set time limit. Your progress through the course and the time remaining before you must reach the next checkpoint is displayed at the top of the frame. 8 | 9 | 10 | Instructions 11 | ------------ 12 | 13 | To start or to restart the race, press Enter. Use the arrow keys or the WASD keys to move. Hold down any other key to accelerate. -------------------------------------------------------------------------------- /src/java4k/pinball4k/a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/pinball4k/a -------------------------------------------------------------------------------- /src/java4k/pinball4k/a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/pinball4k/a.jpg -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/Arrow.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.awt.Point; 6 | import java.io.DataInput; 7 | import java.io.IOException; 8 | import java.lang.reflect.Field; 9 | import java.util.ArrayList; 10 | 11 | public class Arrow extends LevelObject { 12 | public static final int radius = 40; 13 | public static int nextId = 1; 14 | public int id = nextId++; 15 | public int angle; 16 | private ArrowHandle handle; 17 | 18 | private Arrow outerInstance; 19 | 20 | public Arrow(Point p1, Point p2) { 21 | this.p = new Point(p1); 22 | int dx = p2.x - p1.x; 23 | int dy = p2.y - p1.y; 24 | angle = (int) Math.toDegrees(Math.atan2(dy, dx)); 25 | if (angle < 0) { 26 | angle += 360; 27 | } 28 | angle /= 2; 29 | 30 | outerInstance = this; 31 | handle = new ArrowHandle(); 32 | handles.add(handle); 33 | } 34 | 35 | /** 36 | * Draws itself to the specified graphics object 37 | * @param g where to draw 38 | */ 39 | public void draw(Graphics2D g, LevelPanel levelPanel) { 40 | g.setColor(Color.WHITE); 41 | g.fillArc(p.x, p.y, radius * 2, radius * 2, angle*2, 45); 42 | } 43 | 44 | /** 45 | * Draws the handles to the specified graphics object 46 | * @param g where to draw 47 | */ 48 | public void drawHandles(Graphics2D g, LevelPanel levelPanel) { 49 | handle.draw(g, levelPanel); 50 | } 51 | 52 | /** 53 | * The public properties to show in the editor ui. 54 | * @return the properties to show 55 | */ 56 | public Field[] getProperties() { 57 | return getFields("visible", "collidable", "score", "bounce", "behaviorId", "p", "angle"); 58 | } 59 | 60 | public int getSortValue() { 61 | return angle; 62 | } 63 | 64 | 65 | class ArrowHandle extends Handle { 66 | 67 | /** 68 | * Gets the center of the handle. 69 | * @return the center 70 | */ 71 | public Point getCenter() { 72 | return new Point(p.x+40, p.y+40); 73 | } 74 | 75 | /** 76 | * The handle is dragged to the specified location 77 | * @param pos where the handle was dragged to 78 | */ 79 | public void dragged(int dx, int dy) { 80 | p.translate(dx, dy); 81 | } 82 | 83 | /** 84 | * Gets the level object the hangle controlls. Can be null. 85 | * @return the level object 86 | */ 87 | public LevelObject getLevelObject() { 88 | return Arrow.this; 89 | } 90 | } 91 | 92 | /* 93 | * (non-Javadoc) 94 | * @see java.lang.Object#toString() 95 | */ 96 | public String toString() { 97 | return "Arrow(" + id + ")"; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/Bezier.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | 4 | import java.awt.Color; 5 | import java.awt.Graphics2D; 6 | import java.awt.Point; 7 | import java.awt.geom.Point2D; 8 | import java.lang.reflect.Field; 9 | 10 | public class Bezier extends LevelObject { 11 | public Point p2; 12 | public Point p3; 13 | public int subdivs = 8; 14 | 15 | private EndpointHandle p1Handle = new EndpointHandle(0); 16 | private EndpointHandle p2Handle = new EndpointHandle(1); 17 | private EndpointHandle p3Handle = new EndpointHandle(2); 18 | 19 | public Bezier(Point p1, Point p2, Point p3) { 20 | this.p = new Point(p1); 21 | this.p2 = new Point(p2); 22 | this.p3 = new Point(p3); 23 | 24 | handles.add(p1Handle); 25 | handles.add(p2Handle); 26 | handles.add(p3Handle); 27 | } 28 | 29 | /** 30 | * Draws itself to the specified graphics object 31 | * @param g where to draw 32 | */ 33 | public void draw(Graphics2D g, LevelPanel levelPanel) { 34 | g.setColor(Color.WHITE); 35 | float x0 = p.x; 36 | float y0 = p.y; 37 | float x1 = p2.x; 38 | float y1 = p2.y; 39 | float x2 = p3.x; 40 | float y2 = p3.y; 41 | 42 | //int subdivs = (int) Math.max(5, ((Math.abs(x2-x0) + Math.abs(y2-y0)) / 10)); 43 | 44 | float prevx = x0; 45 | float prevy = y0; 46 | for (int i=1; i<=subdivs; i++) { 47 | float t = i / (float) (subdivs); 48 | float t2 = t*t; 49 | float tinv = 1-t; 50 | float tinv2 = tinv*tinv; 51 | 52 | float x = tinv2 * x0 + 2*t*tinv*x1 + t2*x2; 53 | float y = tinv2 * y0 + 2*t*tinv*y1 + t2*y2; 54 | g.drawLine((int) prevx, (int) prevy, (int) x, (int) y); 55 | prevx = x; 56 | prevy = y; 57 | } 58 | } 59 | 60 | public Point2D.Float interpolate(float t) { 61 | float t2 = t*t; 62 | float tinv = 1-t; 63 | float tinv2 = tinv*tinv; 64 | 65 | float x = tinv2 * p.x + 2*t*tinv*p2.x + t2*p3.x; 66 | float y = tinv2 * p.y + 2*t*tinv*p2.y + t2*p3.y; 67 | return new Point2D.Float(x, y); 68 | } 69 | 70 | /** 71 | * Draws the handles to the specified graphics object 72 | * @param g where to draw 73 | */ 74 | public void drawHandles(Graphics2D g, LevelPanel levelPanel) { 75 | p1Handle.draw(g, levelPanel); 76 | p2Handle.draw(g, levelPanel); 77 | p3Handle.draw(g, levelPanel); 78 | } 79 | 80 | /** 81 | * The public properties to show in the editor ui. 82 | * @return the properties to show 83 | */ 84 | public Field[] getProperties() { 85 | return getFields("visible", "collidable", "isRollOver", "score", "bounce", "behaviorId", "p", "p2", "p3", "subdivs"); 86 | } 87 | 88 | /* 89 | * (non-Javadoc) 90 | * @see java.lang.Object#toString() 91 | */ 92 | public String toString() { 93 | return "Bezier (" + p.x + ", " + p.y + ")" + " (" + p2.x + ", " + p2.y + ")" + " (" + p3.x + ", " + p3.y + ")"; 94 | } 95 | 96 | /** 97 | * A handle for one of the lines. 98 | * @author tombr 99 | * 100 | */ 101 | class EndpointHandle extends Handle { 102 | int pointIdx = 0; 103 | EndpointHandle(int pointIdx) { 104 | this.pointIdx = pointIdx; 105 | } 106 | 107 | /** 108 | * Overrides Handle. Gets the endpoint. 109 | * @return the handles endpoint 110 | */ 111 | public Point getCenter() { 112 | if (pointIdx == 1) { 113 | return p2; 114 | } else if (pointIdx == 2) { 115 | return p3; 116 | } 117 | 118 | return p; 119 | } 120 | 121 | /** 122 | * The handle is dragged to the specified position. Moves the endpoin 123 | * the distance dragged. 124 | * @param p where the handle is dragged to 125 | */ 126 | public void dragged(int dx, int dy) { 127 | getCenter().translate(dx, dy); 128 | } 129 | 130 | /** 131 | * Gets the level object the hangle controlls. Can be null. 132 | * @return the level object 133 | */ 134 | public LevelObject getLevelObject() { 135 | return Bezier.this; 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/Editor.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.Dimension; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | import java.util.ArrayList; 8 | 9 | import javax.swing.JFrame; 10 | import javax.swing.JLabel; 11 | import javax.swing.JPanel; 12 | import javax.swing.JScrollPane; 13 | import javax.swing.JSplitPane; 14 | import javax.swing.border.BevelBorder; 15 | 16 | /** 17 | * Pinball level editor. 18 | * 19 | * @author tombr 20 | * 21 | */ 22 | public class Editor extends JFrame { 23 | 24 | ObjectPropertiesUI propsPnl = new ObjectPropertiesUI();; 25 | JPanel statusBar = new JPanel(); 26 | 27 | /** 28 | * Creates an editor. 29 | * 30 | */ 31 | public Editor() { 32 | super("Pinball Editor"); 33 | setSize(1400, 800); 34 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 35 | 36 | LevelPanel levelPnl = new LevelPanel(this); 37 | 38 | JScrollPane levelScroll = new JScrollPane(levelPnl); 39 | levelScroll.setMinimumSize(new Dimension(200, 100)); 40 | 41 | GroupUI groupsPnl = new GroupUI(levelPnl.level.groups, levelPnl); 42 | levelPnl.groupUI = groupsPnl; 43 | 44 | JSplitPane propsSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, propsPnl, groupsPnl); 45 | propsSplit.setDividerLocation(200); 46 | 47 | JSplitPane levelSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, levelScroll, propsSplit); 48 | levelSplit.setDividerLocation(1100); 49 | 50 | // setup status bar 51 | statusBar.setBorder(new BevelBorder(BevelBorder.LOWERED)); 52 | statusBar.add(new JLabel("Hello world")); 53 | 54 | getContentPane().setLayout(new BorderLayout()); 55 | getContentPane().add(levelSplit, BorderLayout.CENTER); 56 | getContentPane().add(levelPnl.getToolBar(), BorderLayout.NORTH); 57 | getContentPane().add(statusBar, BorderLayout.SOUTH); 58 | 59 | //setExtendedState(JFrame.MAXIMIZED_BOTH); 60 | setVisible(true); 61 | 62 | levelPnl.requestFocusInWindow(); 63 | } 64 | 65 | public void select(ArrayList selection) { 66 | /* 67 | ArrayList props = new ArrayList(); 68 | for (Handle handle : selection) { 69 | if (handle.getLevelObject() != null) { 70 | LevelObject levelObj = handle.getLevelObject(); 71 | //propsPnl.load(levelObj.properties); 72 | //break; 73 | if (props.contains(levelObj) == false) { 74 | props.add(levelObj.properties); 75 | } 76 | } 77 | } 78 | propsPnl.load(props); 79 | */ 80 | 81 | // print selected objects to status bar 82 | ArrayList uniqueObjs = new ArrayList(); 83 | String selectionStr = ""; 84 | for (Handle handle : selection) { 85 | LevelObject obj = handle.getLevelObject(); 86 | if (obj != null && !uniqueObjs.contains(obj)) { 87 | uniqueObjs.add(obj); 88 | selectionStr += "" + obj.toString() + " "; 89 | } 90 | } 91 | selectionStr = selectionStr.trim().equals("") ? "Nothing selected" : selectionStr; 92 | JLabel lbl = (JLabel) statusBar.getComponent(0); 93 | lbl.setText(selectionStr); 94 | 95 | 96 | propsPnl.setSelection(uniqueObjs); 97 | } 98 | 99 | /** 100 | * Main entry point of editor application. 101 | * @param args not used 102 | */ 103 | public static void main(String args[]) { 104 | new Editor(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/Flipper.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.awt.Point; 6 | import java.io.DataInput; 7 | import java.io.IOException; 8 | import java.lang.reflect.Field; 9 | import java.util.ArrayList; 10 | 11 | public class Flipper extends LevelObject { 12 | 13 | public static final float ANGLE_SCALE = 127 / (2 * (float) Math.PI); 14 | 15 | double angle = 0; 16 | public int length = 0; 17 | boolean leftFlipper = true; 18 | public int minAngle = 0; 19 | public int maxAngle = 0; 20 | 21 | private FlipperHandle handle = new FlipperHandle(); 22 | private Flipper outerInstance; 23 | 24 | 25 | /** 26 | * Creates a flipper with center at p1 extending out to p2 at the default 27 | * down state. 28 | * @param p1 the center of the flipper 29 | * @param p2 the flipper endpoint at resing pos 30 | */ 31 | public Flipper(Point p1, Point p2) { 32 | this.p = new Point(p1); 33 | length = (int) p1.distance(p2); 34 | leftFlipper = (p1.x < p2.x); 35 | int dx = p2.x - p1.x; 36 | int dy = p2.y - p1.y; 37 | angle = (float) Math.atan2(dy, dx); 38 | 39 | if (leftFlipper) { 40 | maxAngle = toPacked(angle); 41 | minAngle = toPacked(angle - Math.PI / 3); 42 | } else { 43 | minAngle = toPacked(angle); 44 | maxAngle = toPacked(angle + Math.PI / 3); 45 | } 46 | handles.add(handle); 47 | outerInstance = this; 48 | } 49 | 50 | public static double toAngle(int packedAngle) { 51 | return packedAngle / ANGLE_SCALE; 52 | } 53 | 54 | public static int toPacked(double angle) { 55 | return (int) (angle * ANGLE_SCALE); 56 | } 57 | 58 | /** 59 | * Draws itself to the specified graphics object 60 | * @param g where to draw 61 | */ 62 | public void draw(Graphics2D g, LevelPanel levelPanel) { 63 | g.setColor(Color.WHITE); 64 | int startDeg = (int) -Math.toDegrees(toAngle(minAngle)); 65 | int arcDeg = (int) -Math.toDegrees(toAngle(maxAngle) - toAngle(minAngle)); 66 | g.fillArc(p.x - length, p.y - length, length * 2, length * 2, startDeg, arcDeg); 67 | } 68 | 69 | /** 70 | * Draws the handles to the specified graphics object 71 | * @param g where to draw 72 | */ 73 | public void drawHandles(Graphics2D g, LevelPanel levelPanel) { 74 | handle.draw(g, levelPanel); 75 | } 76 | 77 | /** 78 | * The public properties to show in the editor ui. 79 | * @return the properties to show 80 | */ 81 | public Field[] getProperties() { 82 | return getFields("visible", "collidable", "score", "bounce" 83 | , "behaviorId", "p", "minAngle", "maxAngle"); 84 | } 85 | 86 | /** 87 | * A handle for the whole line location between the endpoints. 88 | * @author tombr 89 | * 90 | */ 91 | class FlipperHandle extends Handle { 92 | /** 93 | * Overrides Handle. Gets the endpoint. 94 | * @return the handles endpoint 95 | */ 96 | public Point getCenter() { 97 | return p; 98 | } 99 | 100 | /** 101 | * The handle is dragged to the specified position. Moves the line the 102 | * distance dragged. 103 | * @param p where the handle is dragged to 104 | */ 105 | public void dragged(int dx, int dy) { 106 | p.translate(dx, dy); 107 | } 108 | 109 | /** 110 | * Gets the level object the hangle controlls. Can be null. 111 | * @return the level object 112 | */ 113 | public LevelObject getLevelObject() { 114 | return outerInstance; 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/GroupList.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.Component; 4 | import java.util.ArrayList; 5 | 6 | import javax.swing.JLabel; 7 | import javax.swing.JList; 8 | import javax.swing.ListCellRenderer; 9 | import javax.swing.ListModel; 10 | import javax.swing.event.ListDataEvent; 11 | import javax.swing.event.ListDataListener; 12 | 13 | public class GroupList implements ListModel { 14 | private ArrayList> groups = new ArrayList>(); 15 | 16 | private ArrayList listeners = new ArrayList(); 17 | 18 | public void add(ArrayList obj) { 19 | groups.add(obj); 20 | 21 | for (ListDataListener l : listeners) { 22 | l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, 0, groups.size())); 23 | } 24 | } 25 | 26 | public void remove(LevelObject obj) { 27 | for (ArrayList group : groups) { 28 | group.remove(obj); 29 | } 30 | 31 | for (ListDataListener l : listeners) { 32 | l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, groups.size())); 33 | } 34 | } 35 | 36 | /** 37 | * Removes the specified group. 38 | * @param group the group to remove 39 | */ 40 | public void remove(ArrayList group) { 41 | groups.remove(group); 42 | 43 | for (ListDataListener l : listeners) { 44 | l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, 0, groups.size())); 45 | } 46 | } 47 | 48 | public void move(int idx, boolean up) { 49 | System.out.println(getClass() + " move(" + idx +", " + (up ? "up" : "down")); 50 | if (up) { 51 | if (idx < 1 || idx >= groups.size()) { 52 | return; 53 | } 54 | } else { 55 | if (idx < 0 || idx >= groups.size() - 1) { 56 | return; 57 | } 58 | } 59 | ArrayList obj = groups.remove(idx); 60 | groups.add((up ? idx - 1 : idx + 1), obj); 61 | 62 | for (ListDataListener l : listeners) { 63 | l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, groups.size())); 64 | } 65 | } 66 | 67 | /* 68 | * (non-Javadoc) 69 | * @see javax.swing.ListModel#getSize() 70 | */ 71 | public int getSize() { 72 | return groups.size(); 73 | } 74 | 75 | /* 76 | * (non-Javadoc) 77 | * @see javax.swing.ListModel#addListDataListener(javax.swing.event.ListDataListener) 78 | */ 79 | public void addListDataListener(ListDataListener l) { 80 | listeners.add(l); 81 | } 82 | 83 | /* 84 | * (non-Javadoc) 85 | * @see javax.swing.ListModel#getElementAt(int) 86 | */ 87 | public Object getElementAt(int index) { 88 | return groups.get(index); 89 | } 90 | 91 | /* 92 | * (non-Javadoc) 93 | * @see javax.swing.ListModel#removeListDataListener(javax.swing.event.ListDataListener) 94 | */ 95 | public void removeListDataListener(ListDataListener l) { 96 | listeners.remove(l); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/GroupUI.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.Component; 5 | import java.awt.event.ActionEvent; 6 | import java.awt.event.ActionListener; 7 | import java.util.ArrayList; 8 | 9 | import javax.swing.JButton; 10 | import javax.swing.JLabel; 11 | import javax.swing.JList; 12 | import javax.swing.JPanel; 13 | import javax.swing.JScrollPane; 14 | import javax.swing.ListCellRenderer; 15 | import javax.swing.event.ListSelectionEvent; 16 | import javax.swing.event.ListSelectionListener; 17 | 18 | /** 19 | * A panel where the user can edit the level object properties. 20 | * @author tombr 21 | */ 22 | public class GroupUI extends JPanel implements ActionListener, ListSelectionListener { 23 | 24 | private GroupList groups; 25 | private LevelPanel levelPanel; 26 | private JList myList; 27 | private JButton upBtn = new JButton("Up"); 28 | private JButton downBtn = new JButton("Down"); 29 | private JButton deleteBtn = new JButton("Delete"); 30 | 31 | 32 | public GroupUI(GroupList groups, LevelPanel levelPanel) { 33 | this.groups = groups; 34 | this.levelPanel = levelPanel; 35 | 36 | myList = new JList(groups); 37 | myList.setCellRenderer(new GroupsCellRenderer()); 38 | myList.addListSelectionListener(this); 39 | 40 | deleteBtn.addActionListener(this); 41 | upBtn.addActionListener(this); 42 | downBtn.addActionListener(this); 43 | 44 | JPanel buttonPnl = new JPanel(); 45 | buttonPnl.add(upBtn); 46 | buttonPnl.add(downBtn); 47 | buttonPnl.add(deleteBtn); 48 | 49 | setLayout(new BorderLayout()); 50 | add(new JLabel("Groups:"), BorderLayout.NORTH); 51 | add(new JScrollPane(myList), BorderLayout.CENTER); 52 | add(buttonPnl, BorderLayout.SOUTH); 53 | } 54 | 55 | public void levelChanged() { 56 | this.groups = levelPanel.level.groups; 57 | myList.setModel(groups); 58 | } 59 | 60 | public void actionPerformed(ActionEvent e) { 61 | if (e.getSource() == deleteBtn) { 62 | groups.remove((ArrayList) myList.getSelectedValue()); 63 | } else if (e.getSource() == upBtn) { 64 | int selectedIdx = myList.getSelectedIndex(); 65 | if (selectedIdx > 0) { 66 | groups.move(myList.getSelectedIndex(), true); 67 | myList.setSelectedIndex(selectedIdx - 1); 68 | } 69 | } else if (e.getSource() == downBtn) { 70 | int selectedIdx = myList.getSelectedIndex(); 71 | if (selectedIdx >= 0 && selectedIdx < groups.getSize() - 1) { 72 | groups.move(myList.getSelectedIndex(), false); 73 | myList.setSelectedIndex(selectedIdx + 1); 74 | } 75 | } 76 | } 77 | 78 | class GroupsCellRenderer extends JLabel implements ListCellRenderer { 79 | public Component getListCellRendererComponent( 80 | JList list, // the list 81 | Object value, // value to display 82 | int index, // cell index 83 | boolean isSelected, // is the cell selected 84 | boolean cellHasFocus) // does the cell have focus 85 | { 86 | String s = value.toString(); 87 | setText(s); 88 | 89 | if (isSelected) { 90 | setBackground(list.getSelectionBackground()); 91 | setForeground(list.getSelectionForeground()); 92 | } else { 93 | setBackground(list.getBackground()); 94 | setForeground(list.getForeground()); 95 | } 96 | setEnabled(list.isEnabled()); 97 | setFont(list.getFont()); 98 | setOpaque(true); 99 | return this; 100 | } 101 | } 102 | 103 | /** 104 | * Implements ListSelectionListener. 105 | */ 106 | public void valueChanged(ListSelectionEvent e) { 107 | if (myList.getSelectedValue() != null) { 108 | ArrayList group = (ArrayList) myList.getSelectedValue(); 109 | levelPanel.setSelection(group); 110 | } 111 | 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/Handle.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.awt.Point; 6 | import java.awt.Rectangle; 7 | 8 | public abstract class Handle { 9 | 10 | /** 11 | * Gets the center of the handle. 12 | * @return the center 13 | */ 14 | public abstract Point getCenter(); 15 | 16 | /** 17 | * Gets the size of the handle. 18 | * @return the size of the handle 19 | */ 20 | public int getSize() { 21 | return 12; 22 | } 23 | 24 | /** 25 | * Draws itself to the specified graphics object 26 | * @param g where to draw 27 | */ 28 | public void draw(Graphics2D g, LevelPanel levelPanel) { 29 | if (levelPanel.getState() == LevelPanel.State.SELECT) { 30 | Point handleCenter = getCenter(); 31 | int x = handleCenter.x; 32 | int y = handleCenter.y; 33 | int size = getSize(); 34 | x -= size / 2; 35 | y -= size / 2; 36 | Rectangle rect = new Rectangle(x, y, size, size); 37 | g.setColor(new Color(0xff0000ff)); 38 | Point mousePos = levelPanel.getMousePosition(); 39 | if ((mousePos != null && rect.contains(mousePos)) 40 | || levelPanel.isHandleSelected(this)) { 41 | g.fillRect(x, y, size, size); 42 | } else { 43 | g.drawRect(x, y, size, size); 44 | } 45 | } 46 | } 47 | 48 | /** 49 | * Checks if handle contains the specified point. 50 | * @param p the point to check 51 | * @return true if handle contains point 52 | */ 53 | /*public boolean contains(Point p) { 54 | return getBounds().contains(p); 55 | }*/ 56 | public boolean intersects(Rectangle rect) { 57 | return (getBounds().intersects(rect) || rect.contains(getCenter())); 58 | } 59 | 60 | /** 61 | * Gets the bounds of the handle 62 | * @return the bounds 63 | */ 64 | private Rectangle getBounds() { 65 | Point p = getCenter(); 66 | int s = getSize(); 67 | return new Rectangle(p.x - (s / 2), p.y - (s / 2), s, s); 68 | } 69 | 70 | public abstract void dragged(int dx, int dy); 71 | 72 | /** 73 | * Gets the level object the hangle controlls. Can be null. 74 | * @return the level object 75 | */ 76 | public LevelObject getLevelObject() { 77 | return null; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/Level.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.*; 4 | import java.awt.geom.Point2D; 5 | import java.io.*; 6 | import java.util.*; 7 | 8 | /** 9 | * Before packing flags, score and behavior id: 10 | * before: 4181, 636, 430 11 | * after packing: 4170, 484, 419 12 | * after packing and changing loading: 4185, 484, 419 13 | * 14 | * @author tombr 15 | * 16 | */ 17 | public class Level { 18 | 19 | public static final int VISIBLE_MASK = (1 << 0); 20 | public static final int COLLIDABLE_MASK = (1 << 1); 21 | public static final int ROLL_OVER_MASK = (1 << 2); 22 | public static final int DROP_DOWN_MASK = (1 << 3); 23 | public static final int GATE_MASK = (1 << 4); 24 | public static final int BUMPER_MASK = (1 << 5); 25 | public static final int WRITE_SCORE = (1 << 6); 26 | public static final int WRITE_ID = (1 << 7); 27 | 28 | private static final int DEFAULT_WIDTH = 256*4; 29 | private static final int DEFAULT_HEIGHT = 256*6; 30 | 31 | private int width = DEFAULT_WIDTH; 32 | private int height = DEFAULT_HEIGHT; 33 | 34 | private ArrayList levelObjects = new ArrayList(); 35 | public GroupList groups = new GroupList(); 36 | 37 | /** 38 | * Creates a new empty level with the default size. 39 | */ 40 | public Level() { 41 | } 42 | 43 | /** 44 | * Creates a level read from the specified input stream. 45 | * @param in 46 | * @throws IOException 47 | */ 48 | public Level(InputStream in) throws IOException { 49 | read(in); 50 | } 51 | 52 | /** 53 | * Gets the size of the level in pixels. 54 | * @return the size of the level 55 | */ 56 | public Dimension getSize() { 57 | return new Dimension(width, height); 58 | } 59 | 60 | /** 61 | * Adds the specified level object to the level. 62 | * @param obj the object to add 63 | */ 64 | public void add(LevelObject obj) { 65 | levelObjects.add(obj); 66 | } 67 | 68 | /** 69 | * Draws itself to the specified graphics object 70 | * @param g where to draw 71 | */ 72 | public void draw(Graphics2D g, LevelPanel levelPanel) { 73 | for (LevelObject obj : levelObjects) { 74 | obj.draw(g, levelPanel); 75 | } 76 | } 77 | 78 | /** 79 | * Draws the handles to the specified graphics object 80 | * @param g where to draw 81 | */ 82 | public void drawHandles(Graphics2D g, LevelPanel levelPanel) { 83 | for (LevelObject obj : levelObjects) { 84 | obj.drawHandles(g, levelPanel); 85 | } 86 | } 87 | 88 | /** 89 | * Selects the handles that lies withing the specified bounds. 90 | * @param rect the selection bounds 91 | * @return a list of selected handles 92 | */ 93 | public ArrayList select(Rectangle rect) { 94 | ArrayList selected = new ArrayList(); 95 | for (LevelObject obj : levelObjects) { 96 | ArrayList handles = obj.getHandles(); 97 | for (Handle handle : handles) { 98 | if (handle.intersects(rect)) { 99 | selected.add(handle); 100 | } 101 | } 102 | } 103 | 104 | return selected; 105 | } 106 | 107 | public ArrayList select(ArrayList objects) { 108 | ArrayList selected = new ArrayList(); 109 | for (LevelObject obj : levelObjects) { 110 | if (objects.contains(obj)) { 111 | selected.addAll(obj.getHandles()); 112 | } 113 | } 114 | 115 | return selected; 116 | } 117 | 118 | /** 119 | * Deletes the specified handles. 120 | * @param selection the handles to delete 121 | */ 122 | public void delete(ArrayList selection) { 123 | System.out.println("delete " + selection.size()); 124 | for (int i = selection.size() - 1; i >= 0; i--) { 125 | Handle handle = selection.get(i); 126 | LevelObject obj = handle.getLevelObject(); 127 | if (obj != null) { 128 | levelObjects.remove(obj); 129 | selection.remove(i); 130 | groups.remove(obj); 131 | } 132 | } 133 | } 134 | 135 | private ArrayList> createLineStrips(ArrayList lines) { 136 | ArrayList clone = (ArrayList) lines.clone(); 137 | ArrayList> strips = new ArrayList>(); 138 | 139 | while (clone.size() > 0) { 140 | ArrayList strip = createStrip(clone); 141 | strips.add(strip); 142 | } 143 | 144 | System.out.println("lines="+lines.size()+" strips="+strips.size()); 145 | return strips; 146 | } 147 | 148 | /** 149 | * 98 - 20 - 39 - 38 150 | * Creates a strip from lines and removes strip from lines. 151 | * @param lines line soup 152 | */ 153 | private ArrayList createStrip(ArrayList lines) { 154 | ArrayList strip = new ArrayList(); 155 | 156 | ArrayList searchList = (ArrayList) lines.clone(); 157 | Line start = searchList.get(0); 158 | 159 | while (start != null) { 160 | searchList.remove(start); 161 | Line newStart = findConnectedLine(searchList, start, false); 162 | if (newStart == null) { 163 | break; 164 | } 165 | start = newStart; 166 | } 167 | 168 | 169 | while (start != null) { 170 | lines.remove(start); 171 | strip.add(start); 172 | start = findConnectedLine(lines, start, true); 173 | } 174 | 175 | return strip; 176 | } 177 | 178 | private Line findConnectedLine(ArrayList lines, Line source, boolean forward) { 179 | for (int i=0; i group = (ArrayList) groups.getElementAt(i); 208 | dataOut.writeByte(group.size()); 209 | for (LevelObject obj : group) { 210 | dataOut.writeByte(objIdxMap.get(obj).intValue()); 211 | }*/ 212 | private void sortGroups(ArrayList objects) { 213 | ArrayList sortedList = new ArrayList(); 214 | for (int groupIdx = 0; groupIdx < groups.getSize(); groupIdx++) { 215 | ArrayList group = (ArrayList) groups.getElementAt(groupIdx); 216 | for (int groupObjIdx = group.size()-1; groupObjIdx>=0; groupObjIdx--) { 217 | LevelObject groupObj = group.get(groupObjIdx); 218 | for (int objIdx=0; objIdx flippers = new ArrayList(); 238 | ArrayList lines = new ArrayList(); 239 | ArrayList sircles = new ArrayList(); 240 | ArrayList arrows = new ArrayList(); 241 | ArrayList beziers = new ArrayList(); 242 | 243 | for (LevelObject obj : levelObjects) { 244 | if (obj instanceof Flipper) { 245 | flippers.add((Flipper) obj); 246 | } else if (obj instanceof Line) { 247 | lines.add((Line) obj); 248 | } else if (obj instanceof Sircle) { 249 | sircles.add((Sircle) obj); 250 | } else if (obj instanceof Arrow) { 251 | arrows.add((Arrow) obj); 252 | } else if (obj instanceof Bezier) { 253 | Bezier bezier = (Bezier) obj; 254 | if (writeBeziers) { 255 | beziers.add(bezier); 256 | } else { 257 | Point2D.Float p1 = bezier.interpolate(0); 258 | int subdivs = bezier.subdivs; 259 | for (int i=1; i<=subdivs; i++) { 260 | Point2D.Float p2 = bezier.interpolate(i/(float)subdivs); 261 | 262 | Point p1Int = new Point(Math.round(p1.x), Math.round(p1.y)); 263 | Point p2Int = new Point(Math.round(p2.x), Math.round(p2.y)); 264 | 265 | Line line = new Line(p1Int, p2Int); 266 | lines.add(line); 267 | 268 | p1 = p2; 269 | } 270 | } 271 | } else { 272 | System.out.println(getClass() + " level object not supported " + obj.getClass()); 273 | } 274 | } 275 | 276 | Collections.sort(lines, new Line(new Point(), new Point())); 277 | Collections.sort(sircles, new Line(new Point(), new Point())); 278 | Collections.sort(arrows, new Line(new Point(), new Point())); 279 | 280 | sortGroups(lines); 281 | sortGroups(sircles); 282 | 283 | // move first line of each strip into lines array. strip will reference this array later 284 | HashMap, Integer> stripLineMap = new HashMap, Integer>(); 285 | ArrayList> strips = createLineStrips(lines); 286 | lines.clear(); 287 | for (int stripIdx=0; stripIdx strip = strips.get(stripIdx); 289 | Line firstLine = strip.remove(0); 290 | if (strip.size() == 0) { 291 | strips.remove(strip); 292 | stripIdx--; 293 | } else { 294 | stripLineMap.put(strip, lines.size()); 295 | } 296 | lines.add(firstLine); 297 | } 298 | 299 | ArrayList objects = new ArrayList(); 300 | 301 | for (Sircle sircle : sircles) { 302 | objects.add(sircle); 303 | } 304 | 305 | for (Arrow arrow : arrows) { 306 | objects.add(arrow); 307 | } 308 | 309 | for (Flipper flipper : flippers) { 310 | objects.add(flipper); 311 | } 312 | 313 | for (Line line : lines) { 314 | objects.add(line); 315 | } 316 | 317 | // start writing 318 | DataOutputStream dataOut = new DataOutputStream(out); 319 | 320 | dataOut.writeByte('|'); 321 | dataOut.writeByte('|'); 322 | dataOut.writeByte(flippers.size()); 323 | dataOut.writeByte(sircles.size()); 324 | dataOut.writeByte(arrows.size()); 325 | dataOut.writeByte(lines.size()); 326 | dataOut.writeByte(lines.size()+arrows.size()+sircles.size()+flippers.size()); 327 | 328 | HashMap objIdxMap = new HashMap(); 329 | 330 | int idx = 0; 331 | for (LevelObject obj : objects) { 332 | int flags = getFlags(obj); 333 | flags |= obj.flagOr; 334 | dataOut.writeByte(flags); 335 | dataOut.writeByte(obj.score); 336 | dataOut.writeByte(obj.behaviorId); 337 | objIdxMap.put(obj, new Integer(idx)); 338 | idx++; 339 | } 340 | for (LevelObject obj : objects) { 341 | dataOut.writeByte((byte) (obj.p.x / 4)); 342 | dataOut.writeByte((byte) (obj.p.y / 6)); 343 | } 344 | 345 | // write sircles 346 | for (Sircle sircle : sircles) { 347 | // if (sircle.flagOr != 0) { 348 | dataOut.writeByte((byte) sircle.radius); 349 | // } 350 | } 351 | 352 | // write arrows 353 | for (Arrow arrow : arrows) { 354 | dataOut.writeByte((byte) arrow.angle); 355 | } 356 | 357 | // write flippers 358 | for (Flipper flipper : flippers) { 359 | if (flipper.minAngle < 0 || flipper.maxAngle < 0) { 360 | flipper.minAngle = Flipper.toPacked(Flipper.toAngle(flipper.minAngle) + 2*Math.PI); 361 | flipper.maxAngle = Flipper.toPacked(Flipper.toAngle(flipper.maxAngle) + 2*Math.PI); 362 | } 363 | 364 | dataOut.writeByte((byte) (flipper.minAngle)); 365 | dataOut.writeByte((byte) (flipper.maxAngle)); 366 | dataOut.writeByte(flipper.leftFlipper ? 0 : 2); 367 | } 368 | 369 | // write lines 370 | int lineStartIdx = flippers.size() + sircles.size() + arrows.size(); 371 | for (Line line : lines) { 372 | dataOut.writeByte((byte) (line.p2.x / 4)); 373 | dataOut.writeByte((byte) (line.p2.y / 6)); 374 | } 375 | 376 | // write line strips 377 | dataOut.writeByte(strips.size()); 378 | for (ArrayList strip : strips) { 379 | dataOut.writeByte(strip.size()); 380 | dataOut.writeByte(stripLineMap.get(strip)+lineStartIdx); 381 | for (Line line : strip) { 382 | dataOut.writeByte((byte) (line.p2.x / 4)); 383 | dataOut.writeByte((byte) (line.p2.y / 6)); 384 | objIdxMap.put(line, new Integer(idx)); 385 | idx++; 386 | } 387 | } 388 | 389 | dataOut.writeByte(groups.getSize()); 390 | for (int i = 0; i < groups.getSize() ; i++) { 391 | ArrayList group = (ArrayList) groups.getElementAt(i); 392 | dataOut.writeByte(group.size()); 393 | int firstIdx = objIdxMap.get(group.get(0)).intValue(); 394 | if (group.size() > 0) { 395 | dataOut.writeByte(firstIdx); 396 | } 397 | for (LevelObject obj : group) { 398 | System.out.print(objIdxMap.get(obj).intValue()+" "); 399 | } 400 | System.out.print(" | "); 401 | for (int j=0; j 0) { 408 | dataOut.writeByte(beziers.size()); 409 | // write beziers 410 | for (Bezier bezier : beziers) { 411 | dataOut.writeByte((byte) (bezier.p.x / 4)); 412 | dataOut.writeByte((byte) (bezier.p.y / 6)); 413 | dataOut.writeByte((byte) (bezier.p2.x / 4)); 414 | dataOut.writeByte((byte) (bezier.p2.y / 6)); 415 | dataOut.writeByte((byte) (bezier.p3.x / 4)); 416 | dataOut.writeByte((byte) (bezier.p3.y / 6)); 417 | dataOut.writeByte((byte) bezier.subdivs); 418 | } 419 | } 420 | 421 | System.out.println((objects.size() + beziers.size()) + " objects saved"); 422 | } 423 | 424 | 425 | private int getFlags(LevelObject obj) { 426 | int flags = 0; 427 | if (obj.visible) { 428 | flags |= VISIBLE_MASK; 429 | } 430 | if (obj.collidable) { 431 | flags |= COLLIDABLE_MASK; 432 | } 433 | if (obj.isDropDown) { 434 | flags |= DROP_DOWN_MASK; 435 | } 436 | if (obj.isRollOver) { 437 | flags |= ROLL_OVER_MASK; 438 | } 439 | if (obj.isGate) { 440 | flags |= GATE_MASK; 441 | } 442 | if (obj.bounce > 1) { 443 | flags |= BUMPER_MASK; 444 | } 445 | 446 | return flags; 447 | } 448 | 449 | private void read(InputStream in) throws IOException { 450 | DataInputStream dataIn = new DataInputStream(in); 451 | 452 | // skip header 453 | dataIn.readUnsignedByte(); 454 | dataIn.readUnsignedByte(); 455 | int flippers = dataIn.readByte(); 456 | int sircles = dataIn.readByte(); 457 | int arrows = dataIn.readByte(); 458 | int lineCnt = dataIn.readUnsignedByte(); 459 | // obj count 460 | dataIn.readUnsignedByte(); 461 | 462 | for (int i = 0; i < sircles; i++) { 463 | Sircle sircle = new Sircle(new Point(0, 0), new Point(1, 0)); 464 | levelObjects.add(sircle); 465 | } 466 | 467 | for (int i = 0; i < arrows; i++) { 468 | Arrow arrow = new Arrow(new Point(0, 0), new Point(1, 0)); 469 | levelObjects.add(arrow); 470 | } 471 | 472 | for (int i = 0; i < flippers; i++) { 473 | Flipper flipper = new Flipper(new Point(0, 0), new Point(1, 0)); 474 | levelObjects.add(flipper); 475 | } 476 | 477 | for (int i = 0; i < lineCnt; i++) { 478 | Line line = new Line(new Point(0, 0), new Point(0, 0)); 479 | levelObjects.add(line); 480 | } 481 | 482 | for (LevelObject obj : levelObjects) { 483 | int flags = dataIn.readByte(); 484 | obj.visible = (flags & VISIBLE_MASK) != 0; 485 | obj.collidable = (flags & COLLIDABLE_MASK) != 0; 486 | obj.isRollOver = (flags & ROLL_OVER_MASK) != 0; 487 | obj.isDropDown = (flags & DROP_DOWN_MASK) != 0; 488 | obj.isGate = (flags & GATE_MASK) != 0; 489 | obj.score = dataIn.readUnsignedByte(); 490 | obj.behaviorId = dataIn.readUnsignedByte(); 491 | //obj.bounce = dataIn.readUnsignedByte() / 64f; 492 | obj.bounce = (flags & BUMPER_MASK) != 0 ? 1.1f : 0.75f; 493 | } 494 | for (LevelObject obj : levelObjects) { 495 | obj.p.x = dataIn.readUnsignedByte() * 4; 496 | obj.p.y = dataIn.readUnsignedByte() * 6; 497 | } 498 | 499 | int levelObjIdx = 0; 500 | 501 | for (int i = 0; i < sircles; i++) { 502 | Sircle sircle = (Sircle) levelObjects.get(levelObjIdx++); 503 | sircle.radius = dataIn.readUnsignedByte(); 504 | } 505 | 506 | for (int i = 0; i < arrows; i++) { 507 | Arrow arrow = (Arrow) levelObjects.get(levelObjIdx++); 508 | arrow.angle = dataIn.readUnsignedByte(); 509 | } 510 | 511 | for (int i = 0; i < flippers; i++) { 512 | Flipper flipper = (Flipper) levelObjects.get(levelObjIdx++); 513 | flipper.length = 134; 514 | flipper.minAngle = dataIn.readUnsignedByte(); 515 | flipper.maxAngle = dataIn.readUnsignedByte(); 516 | flipper.leftFlipper = (dataIn.readUnsignedByte() == 0); 517 | } 518 | 519 | for (int i = 0; i < lineCnt; i++) { 520 | Line line = (Line) levelObjects.get(levelObjIdx++); 521 | line.p2.x = dataIn.readUnsignedByte() * 4; 522 | line.p2.y = dataIn.readUnsignedByte() * 6; 523 | } 524 | 525 | 526 | ArrayList> stripsArray = new ArrayList>(); 527 | 528 | int strips = dataIn.readByte(); 529 | int stripBytes = 1+(strips*2); 530 | for (int stripIdx=0; stripIdx linesArray = new ArrayList(); 534 | linesArray.add((Line) levelObjects.get(prevIdx)); 535 | for (int lineIdx=0; lineIdx group = new ArrayList(); 558 | for (int objIdx = 0; objIdx < objCnt; objIdx++) { 559 | int groupObjIdx = firstIdx + objIdx; 560 | LevelObject groupObj = levelObjects.get(groupObjIdx); 561 | group.add(groupObj); 562 | } 563 | groups.add(group); 564 | } 565 | 566 | if (dataIn.available() > 0) { 567 | int beziers = dataIn.readByte(); 568 | for (int i = 0; i < beziers; i++) { 569 | Bezier bezier = new Bezier(new Point(0, 0), new Point(0, 0), new Point(0, 0)); 570 | bezier.p.x = dataIn.readUnsignedByte() * 4; 571 | bezier.p.y = dataIn.readUnsignedByte() * 6; 572 | bezier.p2.x = dataIn.readUnsignedByte() * 4; 573 | bezier.p2.y = dataIn.readUnsignedByte() * 6; 574 | bezier.p3.x = dataIn.readUnsignedByte() * 4; 575 | bezier.p3.y = dataIn.readUnsignedByte() * 6; 576 | bezier.subdivs = dataIn.readUnsignedByte(); 577 | levelObjects.add(bezier); 578 | } 579 | } 580 | 581 | int flipperBytes = 1 + (flippers * 9); 582 | int sircleBytes = 1 + (sircles * 6); 583 | int arrowBytes = 1 + (arrows * 6); 584 | int lineBytes = 1 + (lineCnt * 7); 585 | int total = flipperBytes + sircleBytes + stripBytes + groupBytes + lineBytes; 586 | System.out.println("reading level"); 587 | System.out.println(flippers+" flippers (9) "+flipperBytes); 588 | System.out.println(sircles+" sircles (6) "+sircleBytes); 589 | System.out.println(arrows+" arrows (6) "+arrowBytes); 590 | System.out.println(lineCnt+" lines (7) "+lineBytes); 591 | System.out.println(strips+" strips "+stripBytes); 592 | System.out.println(groupCnt+" groupes "+groupBytes); 593 | System.out.println(total+" total"); 594 | 595 | 596 | /* 597 | // paint strips 598 | try { 599 | JFrame frame = new JFrame(); 600 | frame.setSize(1024, 768); 601 | frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 602 | 603 | BufferedImage img = new BufferedImage(552, 868, BufferedImage.TYPE_INT_ARGB); 604 | Graphics g = img.getGraphics(); 605 | g.setColor(Color.BLACK); 606 | g.fillRect(0, 0, 2000, 2000); 607 | for (ArrayList strip : stripsArray) { 608 | g.setColor(new Color(0x8080 | (int) (Math.random() * 0xffffff))); 609 | for (Line line : strip) { 610 | g.drawLine(line.p.x/2, line.p.y/2, line.p2.x/2, line.p2.y/2); 611 | } 612 | } 613 | g.dispose(); 614 | ImageIcon icon = new ImageIcon(img); 615 | JLabel lbl = new JLabel(icon); 616 | frame.getContentPane().add(lbl, BorderLayout.CENTER); 617 | frame.setVisible(true); 618 | } catch (Exception e) { 619 | e.printStackTrace(); 620 | }*/ 621 | } 622 | } 623 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/LevelObject.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.Graphics2D; 4 | import java.awt.Point; 5 | import java.io.DataInput; 6 | import java.io.IOException; 7 | import java.lang.reflect.Field; 8 | import java.util.ArrayList; 9 | import java.util.Comparator; 10 | 11 | public abstract class LevelObject implements Comparator { 12 | 13 | 14 | /** Is object visible or not */ 15 | public boolean visible = true; 16 | 17 | /** Is object collidable or not */ 18 | public boolean collidable = true; 19 | 20 | /** Is drop down object */ 21 | public boolean isDropDown = false; 22 | 23 | /** Is drop down object */ 24 | public boolean isRollOver = false; 25 | 26 | /** Is drop down object */ 27 | public boolean isGate = false; 28 | 29 | public boolean isStripStart = false; 30 | public int flagOr = 0; 31 | 32 | /** The score to add object is triggered */ 33 | public int score = 0; 34 | 35 | /** The bounce factor */ 36 | public float bounce = 0.75f; 37 | 38 | /** Object behaviour */ 39 | public int behaviorId = 0; 40 | 41 | /** location of object */ 42 | public Point p; 43 | 44 | /** The object properties */ 45 | //public ObjectProperties properties = new ObjectProperties(); 46 | 47 | 48 | public LevelObject() { 49 | } 50 | 51 | /** 52 | * The list of handles that can manipulate this object. Must be set by objects 53 | * that inherits from this class. 54 | */ 55 | protected ArrayList handles = new ArrayList(); 56 | 57 | /** 58 | * Draws itself to the specified graphics object 59 | * @param g where to draw 60 | */ 61 | public abstract void draw(Graphics2D g, LevelPanel levelPanel); 62 | 63 | /** 64 | * Draws the handles to the specified graphics object 65 | * @param g where to draw 66 | */ 67 | public abstract void drawHandles(Graphics2D g, LevelPanel levelPanel); 68 | 69 | /** 70 | * Gets the object handles. 71 | * @return the list of object handles 72 | */ 73 | public ArrayList getHandles() { 74 | return handles; 75 | } 76 | 77 | /** 78 | * The public properties to show in the editor ui. 79 | * @return the properties to show 80 | */ 81 | public Field[] getProperties() { 82 | return new Field[0]; 83 | } 84 | 85 | /** 86 | * Gets a list of fields by their names. 87 | * @param names names of the fields to get 88 | * @return the fields 89 | */ 90 | protected Field[] getFields(String... names) { 91 | Field[] fields = new Field[names.length]; 92 | try { 93 | Class cls = getClass(); 94 | for (int i=0; i clickedPoints = new ArrayList(); 55 | private Point pressedPoint = null; 56 | private Point draggedPoint = null; 57 | private Point movedPoint = null; 58 | 59 | JToolBar toolbar = new JToolBar(); 60 | JToggleButton selectBtn = new JToggleButton("Select"); 61 | JToggleButton lineBtn = new JToggleButton("Line"); 62 | JToggleButton sircleBtn = new JToggleButton("Sircle"); 63 | JToggleButton arrowBtn = new JToggleButton("Arrow"); 64 | JToggleButton triggerBtn = new JToggleButton("Trigger"); 65 | JToggleButton flipperBtn = new JToggleButton("Flipper"); 66 | JToggleButton bezierBtn = new JToggleButton("Bezier"); 67 | 68 | JButton groupBtn = new JButton("Group"); 69 | JButton deleteBtn = new JButton("Delete"); 70 | JButton newBtn = new JButton("New"); 71 | JButton openBtn = new JButton("Open..."); 72 | JButton saveBtn = new JButton("Save"); 73 | JButton saveAsBtn = new JButton("Save As..."); 74 | JButton backgroundBtn = new JButton("Background..."); 75 | JButton runBtn = new JButton("Run"); 76 | 77 | JCheckBox bezierChk = new JCheckBox("Export beziers"); 78 | 79 | // The directory that is opened in the file choosers. Is updated when a 80 | // file is opened or saved. 81 | File currentDirectory = null; 82 | File currentFile = null; 83 | 84 | Rectangle selectRect = new Rectangle(); 85 | ArrayList selection = new ArrayList(); 86 | boolean dragSelection = false; 87 | 88 | private BufferedImage backgroundImage = null; 89 | 90 | public LevelPanel(Editor editor) { 91 | super(); 92 | 93 | this.editor = editor; 94 | 95 | currentDirectory = new File(System.getProperty("user.dir")); 96 | //openLevel(new File(System.getProperty("user.dir") + "/levelShort.bin")); 97 | openLevel(new File(System.getProperty("user.dir") + "/a")); 98 | 99 | Dimension preferredSize = new Dimension(level.getSize()); 100 | preferredSize.height += 32; 101 | setPreferredSize(preferredSize); 102 | revalidate(); 103 | 104 | addMouseListener(this); 105 | addMouseMotionListener(this); 106 | addKeyListener(this); 107 | setFocusable(true); 108 | 109 | selectBtn.setMnemonic(KeyEvent.VK_S); 110 | lineBtn.setMnemonic(KeyEvent.VK_L); 111 | triggerBtn.setMnemonic(KeyEvent.VK_T); 112 | flipperBtn.setMnemonic(KeyEvent.VK_F); 113 | sircleBtn.setMnemonic(KeyEvent.VK_I); 114 | arrowBtn.setMnemonic(KeyEvent.VK_A); 115 | deleteBtn.setMnemonic(KeyEvent.VK_D); 116 | runBtn.setMnemonic(KeyEvent.VK_R); 117 | bezierBtn.setMnemonic(KeyEvent.VK_B); 118 | 119 | // setup toolbar 120 | selectBtn.addActionListener(this); 121 | lineBtn.addActionListener(this); 122 | sircleBtn.addActionListener(this); 123 | arrowBtn.addActionListener(this); 124 | triggerBtn.addActionListener(this); 125 | flipperBtn.addActionListener(this); 126 | bezierBtn.addActionListener(this); 127 | groupBtn.addActionListener(this); 128 | deleteBtn.addActionListener(this); 129 | newBtn.addActionListener(this); 130 | openBtn.addActionListener(this); 131 | saveBtn.addActionListener(this); 132 | saveAsBtn.addActionListener(this); 133 | backgroundBtn.addActionListener(this); 134 | runBtn.addActionListener(this); 135 | 136 | ButtonGroup buttonGroup = new ButtonGroup(); 137 | buttonGroup.add(selectBtn); 138 | buttonGroup.add(lineBtn); 139 | buttonGroup.add(sircleBtn); 140 | buttonGroup.add(arrowBtn); 141 | buttonGroup.add(triggerBtn); 142 | buttonGroup.add(flipperBtn); 143 | buttonGroup.add(bezierBtn); 144 | 145 | selectBtn.setSelected(true); 146 | 147 | toolbar.setFloatable(false); 148 | toolbar.add(newBtn); 149 | toolbar.add(openBtn); 150 | toolbar.add(saveBtn); 151 | toolbar.add(saveAsBtn); 152 | toolbar.addSeparator(); 153 | toolbar.add(runBtn); 154 | toolbar.addSeparator(); 155 | toolbar.add(backgroundBtn); 156 | toolbar.addSeparator(); 157 | toolbar.add(selectBtn); 158 | toolbar.add(lineBtn); 159 | toolbar.add(arrowBtn); 160 | toolbar.add(sircleBtn); 161 | toolbar.add(triggerBtn); 162 | toolbar.add(flipperBtn); 163 | toolbar.add(bezierBtn); 164 | toolbar.addSeparator(); 165 | toolbar.add(groupBtn); 166 | toolbar.add(deleteBtn); 167 | toolbar.addSeparator(); 168 | toolbar.add(bezierChk); 169 | 170 | instance = this; 171 | } 172 | 173 | /** 174 | * Overrides JComponent. Draws the level. 175 | */ 176 | protected void paintComponent(Graphics g) { 177 | try { 178 | g.setColor(Color.BLACK); 179 | g.fillRect(0, 0, getWidth(), getHeight()); 180 | Graphics2D g2d = (Graphics2D)g.create(); 181 | 182 | if (backgroundImage != null) { 183 | //int width = backgroundImage.getWidth() * 1400 / backgroundImage.getHeight(); 184 | //g.drawImage(backgroundImage, 0, 0, width, 1400, null); 185 | g.drawImage(backgroundImage, 0, 0, null); 186 | } 187 | 188 | g.setColor(new Color(32, 32, 32)); 189 | for (int y=0; y<100; y++) { 190 | g.drawLine(0, y*24, 10000, y*24); 191 | g.drawLine(y*16, 0, y*16, 10000); 192 | } 193 | g.setColor(new Color(64, 64, 64)); 194 | for (int y=0; y<20; y++) { 195 | g.drawLine(0, y*24*8, 10000, y*24*8); 196 | g.drawLine(y*16*8, 0, y*16*8, 10000); 197 | } 198 | g.setColor(Color.RED); 199 | g.drawRect(0, 0, level.getSize().width, level.getSize().height); 200 | 201 | level.draw(g2d, this); 202 | level.drawHandles(g2d, this); 203 | 204 | if (pressedPoint != null && draggedPoint != null) { 205 | switch (currentState) { 206 | case SIRCLE: 207 | Sircle sircle = new Sircle(pressedPoint, draggedPoint); 208 | sircle.draw(g2d, this); 209 | break; 210 | case FLIPPER: 211 | Flipper flipper = new Flipper(pressedPoint, draggedPoint); 212 | flipper.draw(g2d, this); 213 | break; 214 | } 215 | } 216 | 217 | switch (currentState) { 218 | case LINE: 219 | if (clickedPoints.size() > 0 && movedPoint != null) { 220 | Line line = new Line(clickedPoints.get(0), movedPoint); 221 | line.draw(g2d, this); 222 | } 223 | break; 224 | case ARROW: 225 | if (clickedPoints.size() > 0 && movedPoint != null) { 226 | Arrow arrow = new Arrow(clickedPoints.get(0), movedPoint); 227 | arrow.draw(g2d, this); 228 | } 229 | break; 230 | case BEZIER: 231 | if (clickedPoints.size() > 1 && movedPoint != null) { 232 | Bezier bezier = new Bezier(clickedPoints.get(0), clickedPoints.get(1), movedPoint); 233 | bezier.draw(g2d, this); 234 | } else if (clickedPoints.size() > 0 && movedPoint != null) { 235 | Bezier bezier = new Bezier(clickedPoints.get(0), movedPoint, movedPoint); 236 | bezier.draw(g2d, this); 237 | } 238 | break; 239 | } 240 | 241 | // draw cross 242 | if (movedPoint != null) { 243 | Point p = snapToGrid(movedPoint); 244 | g2d.setColor(new Color(0xffffff00)); 245 | int crossSize = 5; 246 | g2d.drawLine(p.x - crossSize, p.y, p.x + crossSize, p.y); 247 | g2d.drawLine(p.x, p.y - crossSize, p.x, p.y + crossSize); 248 | 249 | String text = "(" + p.x + ", " + p.y + ")"; 250 | Font font = new Font("SansSerif", Font.PLAIN, 12); 251 | g2d.setFont(font); 252 | Rectangle2D bounds = font.getStringBounds(text, g2d.getFontRenderContext()); 253 | g2d.drawString(text, p.x - (int) bounds.getWidth() / 2, p.y - 5); 254 | } 255 | 256 | if (dragSelection) { 257 | g2d.setColor(new Color(0xffffffff)); 258 | Rectangle r = toRect(pressedPoint, draggedPoint); 259 | g2d.drawRect(r.x, r.y, r.width, r.height); 260 | } 261 | 262 | g2d.dispose(); //clean up 263 | } catch (Throwable t) { 264 | t.printStackTrace(); 265 | } 266 | } 267 | 268 | /** 269 | * 270 | * @param p 271 | * @return 272 | */ 273 | public static Point snapToGrid(java.awt.Point p) { 274 | if (snapToGrid) { 275 | return new Point((p.x + 2) / 4 * 4, (int) (Math.round(p.y / 6f) * 6)); 276 | } 277 | 278 | return p; 279 | } 280 | 281 | public void actionPerformed(ActionEvent e) { 282 | if (e.getSource() == selectBtn) { 283 | setState(LevelPanel.State.SELECT); 284 | } else if (e.getSource() == lineBtn) { 285 | setState(LevelPanel.State.LINE); 286 | } else if (e.getSource() == sircleBtn) { 287 | setState(LevelPanel.State.SIRCLE); 288 | } else if (e.getSource() == arrowBtn) { 289 | setState(LevelPanel.State.ARROW); 290 | } else if (e.getSource() == triggerBtn) { 291 | setState(LevelPanel.State.TRIGGER); 292 | } else if (e.getSource() == flipperBtn) { 293 | setState(LevelPanel.State.FLIPPER); 294 | } else if (e.getSource() == bezierBtn) { 295 | setState(LevelPanel.State.BEZIER); 296 | } else if (e.getSource() == groupBtn) { 297 | ArrayList group = new ArrayList(); 298 | for (Handle handle : selection) { 299 | LevelObject obj = handle.getLevelObject(); 300 | if (obj != null && !group.contains(obj)) { 301 | group.add(obj); 302 | } 303 | } 304 | if (group.size() > 0) { 305 | level.groups.add(group); 306 | } 307 | } else if (e.getSource() == deleteBtn) { 308 | level.delete(selection); 309 | } else if (e.getSource() == newBtn) { 310 | level = new Level(); 311 | groupUI.levelChanged(); 312 | } else if (e.getSource() == backgroundBtn) { 313 | JFileChooser chooser = new JFileChooser(currentDirectory); 314 | int returnVal = chooser.showOpenDialog(editor); 315 | if (returnVal == JFileChooser.APPROVE_OPTION) { 316 | currentDirectory = chooser.getCurrentDirectory(); 317 | openBackground(chooser.getSelectedFile()); 318 | } 319 | } else if (e.getSource() == openBtn) { 320 | JFileChooser chooser = new JFileChooser(currentDirectory); 321 | int returnVal = chooser.showOpenDialog(editor); 322 | if (returnVal == JFileChooser.APPROVE_OPTION) { 323 | currentDirectory = chooser.getCurrentDirectory(); 324 | openLevel(chooser.getSelectedFile()); 325 | } 326 | } else if (e.getSource() == saveBtn) { 327 | saveLevel(); 328 | } else if (e.getSource() == saveAsBtn) { 329 | JFileChooser chooser = new JFileChooser(currentDirectory); 330 | int returnVal = chooser.showSaveDialog(editor); 331 | if (returnVal == JFileChooser.APPROVE_OPTION) { 332 | currentDirectory = chooser.getCurrentDirectory(); 333 | currentFile = chooser.getSelectedFile(); 334 | saveLevel(); 335 | saveBtn.setEnabled(true); 336 | } 337 | } else if (e.getSource() == runBtn) { 338 | try { 339 | System.out.println("run"); 340 | ProcessBuilder processBuilder = new ProcessBuilder("java", "-classpath", "bin;.", "a"); 341 | processBuilder.redirectErrorStream(true); 342 | Process p = processBuilder.start(); 343 | new ProcessStreamReader(p.getInputStream()); 344 | System.out.println(processBuilder.directory()); 345 | } catch (IOException ex) { 346 | ex.printStackTrace(); 347 | } 348 | } 349 | repaint(); 350 | } 351 | 352 | public void mouseClicked(MouseEvent e) { 353 | clickedPoints.add(snapToGrid(e.getPoint())); 354 | handleClick(clickedPoints); 355 | } 356 | 357 | public void mouseEntered(MouseEvent e) { 358 | } 359 | 360 | public void mouseExited(MouseEvent e) { 361 | } 362 | 363 | public void mousePressed(MouseEvent e) { 364 | dragSelection = false; 365 | if (e.getButton() == MouseEvent.BUTTON1) { 366 | 367 | pressedPoint = snapToGrid(e.getPoint()); 368 | draggedPoint = snapToGrid(e.getPoint()); 369 | 370 | if (currentState == State.SELECT) { 371 | selectRect = new Rectangle(e.getPoint(), new Dimension(1, 1)); 372 | ArrayList newSelection = level.select(selectRect); 373 | 374 | if (!e.isControlDown()) { 375 | selection.clear(); 376 | } 377 | 378 | for (Handle handle : newSelection) { 379 | if (selection.contains(handle) == false) { 380 | selection.add(handle); 381 | } else { 382 | selection.remove(handle); 383 | } 384 | } 385 | 386 | if (selection.size() == 0) { 387 | dragSelection = true; 388 | } else { 389 | editor.select(selection); 390 | } 391 | } 392 | 393 | repaint(); 394 | } 395 | 396 | requestFocusInWindow(); 397 | } 398 | 399 | public void mouseReleased(MouseEvent e) { 400 | try { 401 | selectRect = new Rectangle(); 402 | if (dragSelection) { 403 | editor.select(selection); 404 | dragSelection = false; 405 | } 406 | if (e.getButton() == MouseEvent.BUTTON1) { 407 | Point releasePoint = snapToGrid(e.getPoint()); 408 | handleDrag(pressedPoint, releasePoint); 409 | if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0) { 410 | pressedPoint = releasePoint; 411 | draggedPoint = releasePoint; 412 | } else { 413 | pressedPoint = null; 414 | draggedPoint = null; 415 | } 416 | repaint(); 417 | } 418 | } catch (Throwable t) { 419 | t.printStackTrace(); 420 | } 421 | } 422 | 423 | public void mouseDragged(MouseEvent e) { 424 | try { 425 | Point lastDraggedPoint = draggedPoint; 426 | movedPoint = snapToGrid(e.getPoint()); 427 | draggedPoint = (currentState == State.SIRCLE ? e.getPoint() : snapToGrid(e.getPoint())); 428 | 429 | if (currentState == State.SELECT) { 430 | if (dragSelection) { 431 | selectRect = toRect(pressedPoint, draggedPoint); 432 | selection.clear(); 433 | selection = level.select(selectRect); 434 | } else { 435 | for (Handle handle : selection) { 436 | handle.dragged(draggedPoint.x-lastDraggedPoint.x, draggedPoint.y-lastDraggedPoint.y); 437 | } 438 | } 439 | } 440 | 441 | repaint(); 442 | } catch (Throwable t) { 443 | t.printStackTrace(); 444 | } 445 | } 446 | 447 | public void mouseMoved(MouseEvent e) { 448 | movedPoint = snapToGrid(e.getPoint()); 449 | repaint(); 450 | } 451 | 452 | public void keyPressed(KeyEvent e) { 453 | try { 454 | boolean ctrlDown = ((e.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0); 455 | if (ctrlDown) { 456 | if (e.getKeyCode() == KeyEvent.VK_S) { 457 | saveBtn.doClick(); 458 | } 459 | } else { 460 | switch (e.getKeyCode()) { 461 | case KeyEvent.VK_DELETE: 462 | case KeyEvent.VK_SPACE: 463 | deleteBtn.doClick(); 464 | break; 465 | case KeyEvent.VK_F1: 466 | selectBtn.doClick(); 467 | break; 468 | case KeyEvent.VK_F2: 469 | sircleBtn.doClick(); 470 | break; 471 | case KeyEvent.VK_F3: 472 | arrowBtn.doClick(); 473 | break; 474 | case KeyEvent.VK_F4: 475 | lineBtn.doClick(); 476 | break; 477 | case KeyEvent.VK_F5: 478 | flipperBtn.doClick(); 479 | break; 480 | case KeyEvent.VK_F6: 481 | triggerBtn.doClick(); 482 | break; 483 | case KeyEvent.VK_W: 484 | if (currentState == State.SELECT) { 485 | for (Handle handle : selection) { 486 | handle.dragged(0, -6); 487 | } 488 | repaint(); 489 | } 490 | break; 491 | case KeyEvent.VK_S: 492 | if (currentState == State.SELECT) { 493 | for (Handle handle : selection) { 494 | handle.dragged(0, 6); 495 | } 496 | repaint(); 497 | } 498 | break; 499 | case KeyEvent.VK_A: 500 | if (currentState == State.SELECT) { 501 | for (Handle handle : selection) { 502 | handle.dragged(-4, 0); 503 | } 504 | repaint(); 505 | } 506 | break; 507 | case KeyEvent.VK_D: 508 | if (currentState == State.SELECT) { 509 | for (Handle handle : selection) { 510 | handle.dragged(4, 0); 511 | } 512 | repaint(); 513 | } 514 | break; 515 | } 516 | } 517 | } catch (Throwable t) { 518 | t.printStackTrace(); 519 | } 520 | } 521 | 522 | public void keyReleased(KeyEvent e) { 523 | } 524 | 525 | public void keyTyped(KeyEvent e) { 526 | } 527 | 528 | /** 529 | * Handles a mouse drag or click. 530 | * @param pressedPos the position of the mouse when it was pressed 531 | * @param releasedPos the position of the mouse when it was released 532 | */ 533 | private void handleDrag(Point pressedPos, Point releasedPos) { 534 | if (pressedPos != null && releasedPos != null) { 535 | if (releasedPos.equals(pressedPos) == false) { 536 | switch (currentState) { 537 | case SIRCLE: 538 | Sircle sircle = new Sircle(pressedPos, releasedPos); 539 | level.add(sircle); 540 | break; 541 | 542 | case FLIPPER: 543 | Flipper flipper = new Flipper(pressedPos, releasedPos); 544 | level.add(flipper); 545 | break; 546 | } 547 | } 548 | } 549 | } 550 | 551 | /** 552 | * Handles a mouse drag or click. 553 | * @param pressedPos the position of the mouse when it was pressed 554 | * @param releasedPos the position of the mouse when it was released 555 | */ 556 | private void handleClick(ArrayList list) { 557 | switch (currentState) { 558 | case LINE: 559 | if (list.size() >= 2 && !list.get(0).equals(list.get(1))) { 560 | Line line = new Line(list.get(0), list.get(1)); 561 | level.add(line); 562 | list.clear(); 563 | } 564 | break; 565 | case ARROW: 566 | if (list.size() >= 2 && !list.get(0).equals(list.get(1))) { 567 | Arrow arrow = new Arrow(list.get(0), list.get(1)); 568 | level.add(arrow); 569 | list.clear(); 570 | } 571 | break; 572 | case BEZIER: 573 | if (list.size() >= 3 && !list.get(0).equals(list.get(1))) { 574 | Bezier line = new Bezier(list.get(0), list.get(1), list.get(2)); 575 | level.add(line); 576 | list.clear(); 577 | } 578 | break; 579 | } 580 | } 581 | 582 | /** 583 | * Sets the new edit state. 584 | * @param newState the state to set 585 | */ 586 | public void setState(State newState) { 587 | currentState = newState; 588 | pressedPoint = null; 589 | draggedPoint = null; 590 | clickedPoints.clear(); 591 | repaint(); 592 | } 593 | 594 | /** 595 | * Gets the state. 596 | * @return the state 597 | */ 598 | public State getState() { 599 | return currentState; 600 | } 601 | 602 | /** 603 | * Gets the toolbar 604 | * @return the toolbar 605 | */ 606 | public JToolBar getToolBar() { 607 | return toolbar; 608 | } 609 | 610 | /** 611 | * Checks if the specified handle is currently selected 612 | * @param handle the handle to check 613 | * @return true if handle is selected false otherwise 614 | */ 615 | public boolean isHandleSelected(Handle handle) { 616 | for (Handle h : selection) { 617 | if (h == handle) { 618 | return true; 619 | } 620 | } 621 | 622 | return false; 623 | } 624 | 625 | public boolean isSelected(LevelObject obj) { 626 | for (Handle h : selection) { 627 | if (h.getLevelObject() == obj) { 628 | return true; 629 | } 630 | } 631 | 632 | return false; 633 | } 634 | 635 | /** 636 | * 637 | * @param p1 638 | * @param p2 639 | * @return 640 | */ 641 | public Rectangle toRect(Point p1, Point p2) { 642 | return new Rectangle(p1, new Dimension()).union(new Rectangle(p2, new Dimension())); 643 | } 644 | 645 | public void setSelection(ArrayList objects) { 646 | selection = level.select(objects); 647 | repaint(); 648 | } 649 | 650 | /** 651 | * Opens the specified level file. 652 | * @param file the level file 653 | */ 654 | public void openLevel(File file) { 655 | try { 656 | currentFile = file; 657 | FileInputStream fileIn = new FileInputStream(currentFile); 658 | level = new Level(fileIn); 659 | saveBtn.setEnabled(true); 660 | } catch (Exception e) { 661 | e.printStackTrace(); 662 | currentFile = null; 663 | saveBtn.setEnabled(false); 664 | level = new Level(); 665 | } 666 | if (groupUI != null) { 667 | groupUI.levelChanged(); 668 | } 669 | } 670 | 671 | /** 672 | * Saves the level the the currently opened file. 673 | */ 674 | public void saveLevel() { 675 | try { 676 | FileOutputStream file2Out = new FileOutputStream(currentFile); 677 | level.write(file2Out, bezierChk.isSelected()); 678 | file2Out.close(); 679 | } catch (IOException ioException) { 680 | ioException.printStackTrace(); 681 | } 682 | } 683 | 684 | /** 685 | * Opens the specified image as background. 686 | * @param file the image file 687 | */ 688 | public void openBackground(File file) { 689 | try { 690 | backgroundImage = ImageIO.read(file); 691 | } catch (IOException e) { 692 | e.printStackTrace(); 693 | backgroundImage = null; 694 | } 695 | } 696 | 697 | class ProcessStreamReader implements Runnable { 698 | 699 | BufferedInputStream in; 700 | 701 | public ProcessStreamReader(InputStream in) { 702 | this.in = new BufferedInputStream(in); 703 | Thread thread = new Thread(this); 704 | thread.setDaemon(true); 705 | thread.start(); 706 | } 707 | 708 | public void run() { 709 | try { 710 | int bytesRead = 0; 711 | byte[] data = new byte[1024]; 712 | while ((bytesRead = in.read(data)) != -1) { 713 | System.out.write(data, 0, bytesRead); 714 | } 715 | } catch (IOException e) { 716 | e.printStackTrace(); 717 | } 718 | } 719 | } 720 | } 721 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/Line.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.Color; 4 | import java.awt.Dimension; 5 | import java.awt.Graphics2D; 6 | import java.awt.Point; 7 | import java.awt.Rectangle; 8 | import java.awt.geom.Line2D; 9 | import java.lang.reflect.Field; 10 | import java.util.Comparator; 11 | 12 | public class Line extends LevelObject { 13 | 14 | private static int nextId = 1; 15 | 16 | private int id = 0; 17 | 18 | public Point p2; 19 | 20 | private LineHandle lineHandle = new LineHandle(); 21 | private EndpointHandle p1Handle = new EndpointHandle(true); 22 | private EndpointHandle p2Handle = new EndpointHandle(false); 23 | 24 | public Line(Line line) { 25 | this(line.p, line.p2); 26 | 27 | this.isDropDown = line.isDropDown; 28 | this.isRollOver = line.isRollOver; 29 | this.isGate = line.isGate; 30 | this.visible = line.visible; 31 | this.collidable = line.collidable; 32 | this.bounce = line.bounce; 33 | this.behaviorId = line.behaviorId; 34 | this.score = line.score; 35 | } 36 | 37 | public Line(Point p1, Point p2) { 38 | this.p = new Point(p1); 39 | this.p2 = new Point(p2); 40 | this.id = nextId++; 41 | 42 | handles.add(lineHandle); 43 | handles.add(p1Handle); 44 | handles.add(p2Handle); 45 | } 46 | 47 | /** 48 | * Draws itself to the specified graphics object 49 | * @param g where to draw 50 | */ 51 | public void draw(Graphics2D g, LevelPanel levelPanel) { 52 | g.setColor(Color.WHITE); 53 | if (levelPanel.getState() == LevelPanel.State.SELECT) { 54 | if (levelPanel.isSelected(this)) { 55 | g.setColor(Color.red); 56 | } 57 | 58 | Point mousePos = levelPanel.getMousePosition(); 59 | if (mousePos != null) { 60 | Rectangle mouseRect = new Rectangle(mousePos, new Dimension(1, 1)); 61 | if (lineHandle.intersects(mouseRect)) { 62 | g.setColor(new Color(0xff7f0000)); 63 | } 64 | } 65 | if (lineHandle.intersects(levelPanel.selectRect)) { 66 | g.setColor(new Color(0xff7f0000)); 67 | } 68 | } 69 | 70 | g.drawLine(p.x, p.y, p2.x, p2.y); 71 | } 72 | 73 | /** 74 | * Draws the handles to the specified graphics object 75 | * @param g where to draw 76 | */ 77 | public void drawHandles(Graphics2D g, LevelPanel levelPanel) { 78 | p1Handle.draw(g, levelPanel); 79 | p2Handle.draw(g, levelPanel); 80 | } 81 | 82 | /** 83 | * The public properties to show in the editor ui. 84 | * @return the properties to show 85 | */ 86 | public Field[] getProperties() { 87 | return getFields("visible", "collidable", "isDropDown", "isRollOver" 88 | , "isGate", "score", "bounce", "behaviorId", "p", "p2"); 89 | } 90 | 91 | /* 92 | * (non-Javadoc) 93 | * @see java.lang.Object#toString() 94 | */ 95 | public String toString() { 96 | return "Line "+id; 97 | } 98 | 99 | /** 100 | * A handle for one of the lines. 101 | * @author tombr 102 | * 103 | */ 104 | class LineHandle extends Handle { 105 | LineHandle() { 106 | } 107 | 108 | /** 109 | * Draws itself to the specified graphics object 110 | * @param g where to draw 111 | */ 112 | public void draw(Graphics2D g, LevelPanel levelPanel) { 113 | } 114 | 115 | public boolean intersects(Rectangle rect) { 116 | Line2D.Float line = new Line2D.Float(p, p2); 117 | if (rect.width <= 1 && rect.height <= 1) { 118 | return line.ptSegDist(new Point(rect.x, rect.y)) < 5; 119 | } 120 | 121 | return line.intersects(rect); 122 | /* 123 | if (rect.contains(p) || rect.contains(p2)) { 124 | return true; 125 | } 126 | */ 127 | 128 | } 129 | 130 | /** 131 | * Overrides Handle. Gets the endpoint. 132 | * @return the handles endpoint 133 | */ 134 | public Point getCenter() { 135 | return p; 136 | } 137 | 138 | /** 139 | * The handle is dragged to the specified position. Moves the endpoin 140 | * the distance dragged. 141 | * @param p where the handle is dragged to 142 | */ 143 | public void dragged(int dx, int dy) { 144 | if (!LevelPanel.instance.selection.contains(p1Handle) && !LevelPanel.instance.selection.contains(p2Handle)) { 145 | p.translate(dx, dy); 146 | p2.translate(dx, dy); 147 | } 148 | } 149 | 150 | /** 151 | * Gets the level object the hangle controlls. Can be null. 152 | * @return the level object 153 | */ 154 | public LevelObject getLevelObject() { 155 | return Line.this; 156 | } 157 | } 158 | 159 | /** 160 | * A handle for one of the lines. 161 | * @author tombr 162 | * 163 | */ 164 | class EndpointHandle extends Handle { 165 | boolean handleFirstEndpoint = true; 166 | EndpointHandle(boolean handleFirstEndpoint) { 167 | this.handleFirstEndpoint = handleFirstEndpoint; 168 | } 169 | 170 | /** 171 | * Overrides Handle. Gets the endpoint. 172 | * @return the handles endpoint 173 | */ 174 | public Point getCenter() { 175 | return handleFirstEndpoint ? p : p2; 176 | } 177 | 178 | /** 179 | * The handle is dragged to the specified position. Moves the endpoin 180 | * the distance dragged. 181 | * @param p where the handle is dragged to 182 | */ 183 | public void dragged(int dx, int dy) { 184 | getCenter().translate(dx, dy); 185 | } 186 | 187 | /** 188 | * Gets the level object the hangle controlls. Can be null. 189 | * @return the level object 190 | */ 191 | public LevelObject getLevelObject() { 192 | return Line.this; 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/ObjectProperties.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | public class ObjectProperties { 4 | 5 | /** Is object visible or not */ 6 | public boolean visible = true; 7 | 8 | /** Is object collidable or not */ 9 | public boolean collidable = true; 10 | 11 | /** The score to add object is triggered */ 12 | public int score = 0; 13 | 14 | /** The bounce factor */ 15 | public float bounce = 0.75f; 16 | 17 | /** Object behaviour */ 18 | public int behaviorId = 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/ObjectPropertiesUI.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.GridLayout; 5 | import java.awt.Point; 6 | import java.awt.event.ActionEvent; 7 | import java.awt.event.ActionListener; 8 | import java.lang.reflect.Field; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | 12 | import javax.swing.*; 13 | import javax.swing.table.AbstractTableModel; 14 | 15 | /** 16 | * A panel where the user can edit the level object properties. 17 | * @author tombr 18 | */ 19 | public class ObjectPropertiesUI extends JPanel { 20 | 21 | public ArrayList selection = new ArrayList(); 22 | private MyTableModel tableModel = new MyTableModel(); 23 | 24 | public ObjectPropertiesUI() { 25 | JTable table = new JTable(tableModel); 26 | JScrollPane scrollpane = new JScrollPane(table); 27 | 28 | setLayout(new BorderLayout()); 29 | add(new JLabel("Object properties:"), BorderLayout.NORTH); 30 | add(table, BorderLayout.CENTER); 31 | //add(storeBtn, BorderLayout.SOUTH); 32 | } 33 | 34 | public void setSelection(ArrayList selection) { 35 | this.selection = selection; 36 | tableModel.fireTableDataChanged(); 37 | } 38 | 39 | private Field[] getFields() { 40 | if (selection.size() == 0) { 41 | return new Field[0]; 42 | } 43 | 44 | return selection.get(0).getProperties(); 45 | } 46 | 47 | class MyTableModel extends AbstractTableModel { 48 | public int getRowCount() { 49 | return getFields().length; 50 | } 51 | 52 | public int getColumnCount() { 53 | return 2; 54 | } 55 | 56 | public Object getValueAt(int row, int column) { 57 | Field field = getFields()[row]; 58 | if (column == 0) { 59 | return field.getName() + " (" + field.getType().getSimpleName() + ")"; 60 | } 61 | try { 62 | Object value = field.get(selection.get(0)); 63 | if (value instanceof Point) { 64 | Point point = (Point) value; 65 | return "" + point.x + " " + point.y; 66 | } 67 | return value; 68 | } catch (Exception e) { 69 | } 70 | return "error"; 71 | } 72 | 73 | public boolean isCellEditable(int rowIndex, int columnIndex) { 74 | return (columnIndex == 1); 75 | } 76 | 77 | public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 78 | for (LevelObject obj : selection) { 79 | try { 80 | Field field = getFields()[rowIndex]; 81 | if (field.getType().equals(float.class)) { 82 | field.setFloat(obj, Float.parseFloat("" + aValue)); 83 | } else if (field.getType().equals(int.class)) { 84 | field.setInt(obj, Integer.parseInt("" + aValue)); 85 | } else if (field.getType().equals(boolean.class)) { 86 | field.setBoolean(obj, Boolean.parseBoolean("" + aValue)); 87 | } 88 | System.out.println("setValueAt " + rowIndex + " " + aValue); 89 | LevelPanel.instance.repaint(); 90 | } catch (Exception e) { 91 | e.printStackTrace(); 92 | } 93 | } 94 | } 95 | } 96 | 97 | /* 98 | public ArrayList selectionProps; 99 | 100 | private HashMap fieldTxtMap = new HashMap(); 101 | 102 | public ObjectPropertiesUI(Class propsClass) { 103 | Field[] fields = propsClass.getFields(); 104 | 105 | JPanel fieldPnl = new JPanel(); 106 | fieldPnl.setLayout(new GridLayout(fields.length, 2)); 107 | 108 | for (Field field : fields) { 109 | fieldPnl.add(new JLabel(field.getName())); 110 | 111 | JComponent fieldCmp = new JTextField(); 112 | if (new String("" + field.getType()).equals("boolean")) { 113 | String[] boolString = {"true", "false"}; 114 | fieldCmp = new JComboBox(boolString); 115 | } else if (field.getName().equals("behaviorId")) { 116 | System.out.println(field.getName()); 117 | String[] behaviourString = {"normal", "game over", "start", "drop down", "roll over", "bumper", "gate"}; 118 | fieldCmp = new JComboBox(behaviourString); 119 | } 120 | 121 | fieldTxtMap.put(field.getName(), fieldCmp); 122 | fieldPnl.add(fieldCmp); 123 | } 124 | 125 | JButton storeBtn = new JButton("Store"); 126 | storeBtn.addActionListener(new ActionListener() { 127 | public void actionPerformed(ActionEvent e) { 128 | store(selectionProps); 129 | } 130 | }); 131 | 132 | setLayout(new BorderLayout()); 133 | add(new JLabel("Object properties:"), BorderLayout.NORTH); 134 | add(fieldPnl, BorderLayout.CENTER); 135 | add(storeBtn, BorderLayout.SOUTH); 136 | }*/ 137 | 138 | /** 139 | * Loads the specified fields in the specified property object into the ui. 140 | * @param selectionProps the object to load 141 | */ 142 | /*public void load(ArrayList newProps) { 143 | store(selectionProps); 144 | if (newProps != null && newProps.size() > 0) { 145 | ObjectProperties objProps = newProps.get(0); 146 | Field[] fields = objProps.getClass().getFields(); 147 | for (Field field : fields) { 148 | try { 149 | if (new String("" + field.getType()).equals("boolean")) { 150 | JComboBox boolList = (JComboBox) fieldTxtMap.get(field.getName()); 151 | boolList.setSelectedIndex(field.getBoolean(objProps) ? 0 : 1); 152 | } else if (field.getName().equals("behaviorId")) { 153 | JComboBox boolList = (JComboBox) fieldTxtMap.get(field.getName()); 154 | boolList.setSelectedIndex(field.getInt(objProps)); 155 | } else { 156 | JTextField fieldTxt = (JTextField) fieldTxtMap.get(field.getName()); 157 | fieldTxt.setText("" + field.get(objProps)); 158 | } 159 | } catch (Exception e) { 160 | System.out.println("Failed to load " + field.getName() + " of type " + field.getType()); 161 | e.printStackTrace(); 162 | } 163 | } 164 | } 165 | 166 | selectionProps = newProps; 167 | }*/ 168 | 169 | /** 170 | * Stores the ui values in the properties fields 171 | * @param selectionProps where to store the data 172 | */ 173 | /*private void store(ArrayList storeProps) { 174 | if (storeProps != null && storeProps.size() > 0) { 175 | for (ObjectProperties props : storeProps) { 176 | Field[] fields = props.getClass().getFields(); 177 | for (Field field : fields) { 178 | try { 179 | if (field.getName().equals("behaviorId")) { 180 | JComboBox behaviorList = (JComboBox) fieldTxtMap.get(field.getName()); 181 | field.set(props, behaviorList.getSelectedIndex()); 182 | } else if (field.getType().toString().equals("boolean")) { 183 | JComboBox boolList = (JComboBox) fieldTxtMap.get(field.getName()); 184 | field.set(props, Boolean.valueOf(boolList.getSelectedItem().toString())); 185 | } else if (field.getType().toString().equals("int")) { 186 | JTextField fieldTxt = (JTextField) fieldTxtMap.get(field.getName()); 187 | field.set(props, Integer.valueOf(fieldTxt.getText())); 188 | } else if (field.getType().toString().equals("float")) { 189 | JTextField fieldTxt = (JTextField) fieldTxtMap.get(field.getName()); 190 | field.set(props, Float.valueOf(fieldTxt.getText())); 191 | } 192 | } catch (Exception e) { 193 | System.out.println(getClass() + " error storing field " + field); 194 | e.printStackTrace(); 195 | } 196 | } 197 | } 198 | } 199 | }*/ 200 | } 201 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/PaintUtil.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.Graphics2D; 4 | 5 | public class PaintUtil { 6 | 7 | public static void drawText(Graphics2D g, String text, float x, float y) { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/QuadBezier.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.*; 4 | import javax.swing.*; 5 | 6 | public class QuadBezier extends JPanel { 7 | 8 | public void paintComponent(Graphics g) { 9 | float[] xs = {100, 200, 200, 200, 300}; 10 | float[] ys = {100, 100, 200, 150, 200}; 11 | 12 | for (int curveIdx=0; curveIdx < (xs.length-1)/2; curveIdx++) { 13 | int idx = curveIdx * 2; 14 | float x0 = xs[idx]; 15 | float y0 = ys[idx]; 16 | float x1 = xs[idx+1]; 17 | float y1 = ys[idx+1]; 18 | float x2 = xs[idx+2]; 19 | float y2 = ys[idx+2]; 20 | 21 | float prevx = x0; 22 | float prevy = y0; 23 | for (float t=0; t<=1; t+=0.01f) { 24 | float t2 = t*t; 25 | float tinv = 1-t; 26 | float tinv2 = tinv*tinv; 27 | 28 | float x = tinv2 * x0 + 2*t*tinv*x1 + t2*x2; 29 | float y = tinv2 * y0 + 2*t*tinv*y1 + t2*y2; 30 | g.drawLine((int) prevx, (int) prevy, (int) x, (int) y); 31 | prevx = x; 32 | prevy = y; 33 | } 34 | } 35 | } 36 | 37 | 38 | public static void main(String[] args) { 39 | JFrame frame = new JFrame(); 40 | frame.setSize(640, 480); 41 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 42 | frame.getContentPane().add(new QuadBezier(), BorderLayout.CENTER); 43 | frame.setVisible(true); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/editor/Sircle.java: -------------------------------------------------------------------------------- 1 | package java4k.pinball4k.editor; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.awt.Point; 6 | import java.io.DataInput; 7 | import java.io.IOException; 8 | import java.lang.reflect.Field; 9 | import java.util.ArrayList; 10 | 11 | public class Sircle extends LevelObject { 12 | public int radius; 13 | private SircleHandle handle; 14 | private RadiusHandle radiusHandle; 15 | 16 | private Sircle outerInstance; 17 | 18 | public Sircle(Point p1, Point p2) { 19 | this.p = new Point(p1); 20 | radius = (int) p2.distance(p1); 21 | 22 | outerInstance = this; 23 | handle = new SircleHandle(); 24 | radiusHandle = new RadiusHandle(); 25 | handles.add(handle); 26 | handles.add(radiusHandle); 27 | } 28 | 29 | /** 30 | * Draws itself to the specified graphics object 31 | * @param g where to draw 32 | */ 33 | public void draw(Graphics2D g, LevelPanel levelPanel) { 34 | g.setColor(Color.WHITE); 35 | g.fillOval(p.x - radius, p.y - radius, radius * 2, radius * 2); 36 | } 37 | 38 | /** 39 | * Draws the handles to the specified graphics object 40 | * @param g where to draw 41 | */ 42 | public void drawHandles(Graphics2D g, LevelPanel levelPanel) { 43 | handle.draw(g, levelPanel); 44 | radiusHandle.draw(g, levelPanel); 45 | } 46 | 47 | /** 48 | * The public properties to show in the editor ui. 49 | * @return the properties to show 50 | */ 51 | public Field[] getProperties() { 52 | return getFields("visible", "collidable", "isRollOver", "score", "bounce", "behaviorId", "p", "radius"); 53 | } 54 | 55 | public int getSortValue() { 56 | int val = super.getSortValue(); 57 | return (radius << 26) | (val >>> 6); 58 | } 59 | 60 | 61 | class SircleHandle extends Handle { 62 | 63 | /** 64 | * Gets the center of the handle. 65 | * @return the center 66 | */ 67 | public Point getCenter() { 68 | return p; 69 | } 70 | 71 | /** 72 | * The handle is dragged to the specified location 73 | * @param pos where the handle was dragged to 74 | */ 75 | public void dragged(int dx, int dy) { 76 | p.translate(dx, dy); 77 | } 78 | 79 | /** 80 | * Gets the level object the hangle controlls. Can be null. 81 | * @return the level object 82 | */ 83 | public LevelObject getLevelObject() { 84 | return outerInstance; 85 | } 86 | } 87 | 88 | /* 89 | * (non-Javadoc) 90 | * @see java.lang.Object#toString() 91 | */ 92 | public String toString() { 93 | return "Sircle(" + p.x + ", " + p.y + ")"; 94 | } 95 | 96 | class RadiusHandle extends Handle { 97 | 98 | /** 99 | * Gets the center of the handle. 100 | * @return the center 101 | */ 102 | public Point getCenter() { 103 | return new Point(p.x + radius, p.y); 104 | } 105 | 106 | /** 107 | * The handle is dragged to the specified location 108 | * @param pos where the handle was dragged to 109 | */ 110 | public void dragged(int dx, int dy) { 111 | radius += dx; 112 | //radius = (int) p.distance(pos); 113 | } 114 | 115 | /** 116 | * Gets the level object the hangle controlls. Can be null. 117 | * @return the level object 118 | */ 119 | public LevelObject getLevelObject() { 120 | return null; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/java4k/pinball4k/readme.txt: -------------------------------------------------------------------------------- 1 | Pinball 4k 2 | ========== 3 | 4 | Description 5 | ----------- 6 | 7 | Pinball Game with lots of features and bonus plays 8 | 9 | Instructions 10 | ------------ 11 | 12 | Keys 13 | 14 | left arrow - left flipper 15 | right arrow - right flipper 16 | space - tilt 17 | enter - new game 18 | escape - exit game 19 | 20 | Scoring and Bonus Rules 21 | 22 | Bumpers and slingshots gives 1000 points. Dropdowns and rollovers 4000 points. 23 | 24 | 5000 bonus points for completing a dropdown or rollover group. 25 | 26 | Completing the A, B or C drop target will ligth a bullseye arrow. The bullseye bonus depends on the number of arrow lit: 27 | 0: 25 000 28 | 1: 50 000 29 | 2: 100 000 30 | 3: 200 000 31 | 32 | Completing the multiplier rollovers will increase the multiplier. All bonus scores are multiplied by the multiplier. 33 | 34 | The inlane rollovers will lite the left lane arrow for 30 seconds. The bumper rollovers will lite the right lane arrow for 30 seconds. The left and right lane awards 25000 bonus point when its arrow is lit. 35 | 36 | Hitting the bumper rollovers 3 times will enable the bumper bonus for 30 seconds. Hitting a bumper when the bonus is on awards 5000 bonus points. 37 | 38 | Hitting the left lane 3 time will enable the rollover bonus for 30 seconds. Hitting the right lane 3 time will enable the dropdown bonus for 30 seconds. Hitting a rollover or dropdown when the bonus is on awards 10000 bonus points. 39 | 40 | Completing the kicker dropdowns will light the coresponding kicker. Triggering a kicker will kick the ball back and award 15000 bonus points. 41 | 42 | Extraball is awarded when reaching the following scores: 43 | 1 000 000 44 | 2 000 000 45 | 4 000 000 46 | 8 000 000 47 | 16 000 000 48 | 32 000 000 49 | 64 000 000 50 | etc 51 | 52 | Extraballs do not stack. 53 | 54 | 55 | Strategy 56 | 57 | Hit anything that is blinking. Bonuses are shown by an object blinking. So if it is blinking, try to hit it. 58 | 59 | Go for the multiplier. Learn how to trap the ball on the left flipper. If you trap it on the right flipper you can tilt the board to move it to the left. Then hit the right lane to move the ball to the multiplier dropdown. Use tilt to complete the rollover on the right. 60 | 61 | Use the slingshots to hit the kickers and bumper rollovers. Use tilt to get extra kick from the slingshots. 62 | 63 | Use the tilt as much as possible to conroll the ball. But be careful, the board is locked if you tilt two times in under half a second. 64 | 65 | 66 | Features 67 | 68 | * Vector based posteriori collision detection 69 | * Realistic collision repsonse 70 | * Rollover targets 71 | * Drop targets 72 | * Bumbers 73 | * Slingshots 74 | * One way gates 75 | * Tilt 76 | * Multiplier 77 | * Outlane kickers 78 | * 3 flippers 79 | * Bullseye skill shot 80 | * 5 time bonuses 81 | * Extraball -------------------------------------------------------------------------------- /src/java4k/pitfall4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/pitfall4k/a.png -------------------------------------------------------------------------------- /src/java4k/pitfall4k/readme.txt: -------------------------------------------------------------------------------- 1 | Pitfall 4K 2 | ========== 3 | 4 | Description 5 | ----------- 6 | 7 | The optimal pathway through the maze can be viewed here: 8 | 9 | http://meatfighter.com/java4k2012/pitfall4k/map.html 10 | 11 | You can safely stand on the right tip of crocodile heads even when their mouths are open. 12 | 13 | The object of Pitfall 4K is to guide Harry through a maze of jungle scenes, jumping over or avoiding many deadly dangers, and helping Harry grab the most treasures in the shortest possible time. You start each adventure with 2000 points. Some misfortunes will cause a deduction of points. Should you fall down a hole by accident, you will lose 100 points. Rolling logs will also cause point loss depending on how long contact is made with them. 14 | 15 | Each treasure you find will add points to your score. There are eight of each type of treasure in the entire game, 32 in all, for a total of 112,000 points. A perfect score is 114,000 points, reached by collecting all treasures without losing any points by falling down holes or tripping on logs. 16 | 17 | You have 20 minutes to complete each adventure. Harry has 3 lives in each game. 18 | 19 | There are 255 jungle scenes through which Harry can travel. Each scene covered underground is equivalent to three on the surface. Pitfall 4K is a circular maze, which means that, if Harry safely goes through all 255 different scenes, he will come back to the starting point. In the course of that journey, Harry will also encounter all 32 treasures. 20 | 21 | Pitfall Harry's Jungle Adventure is fraught with danger. Some hazards will slow him down and rob you of points, while others will stop him cold in his tracks. The lesser hazards are the open holes in the ground and rolling logs. The catastrophic hazards are the scorpions, fires, cobra rattlers, crocodiles, swamps, quicksand and tar pits. These obstacles will not cost you points, but they will cost one of Harry's 3 lives. 22 | 23 | Instructions 24 | ------------ 25 | 26 | Use the arrow keys or the WASD keys to move. Press any other key to jump. 27 | 28 | Press 8 to enable a secret compass that will guide you through the optimal pathway. 29 | -------------------------------------------------------------------------------- /src/java4k/porta4k/P.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/porta4k/P.jpg -------------------------------------------------------------------------------- /src/java4k/porta4k/readme.txt: -------------------------------------------------------------------------------- 1 | Porta4K 2 | ======= 3 | 4 | Description 5 | ----------- 6 | 7 | You wake up and find yourself trapped in a maze of sinister tests. 8 | Fight your way out by jumping through portals to reach the green zone. 9 | 10 | Portals only sticks on the light gray walls. 11 | 12 | Instructions 13 | ------------ 14 | 15 | CONTROLS 16 | * a, d to steer left and right. 17 | * w or space to jump. 18 | * Left mouse button fire an orange portal. 19 | * Right mouse button fire a blue portal. 20 | 21 | NOT WORKING? 22 | It might be because of conflicting sound sources. 23 | 24 | ACKNOWLEDGEMENTS 25 | Thanks to Druttis and Jocke for their help with the synth and music respectively. -------------------------------------------------------------------------------- /src/java4k/rainbowroad/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/rainbowroad/a.png -------------------------------------------------------------------------------- /src/java4k/rainbowroad/readme.txt: -------------------------------------------------------------------------------- 1 | Rainbow Road 2 | ============ 3 | 4 | Description 5 | ----------- 6 | 7 | The longest and most treacherous course in Mario Kart, Rainbow Road is a wild ride unlike any other. Its hypnotic curves and stomach-turning drops are enough to shake even the steadiest racers. 8 | 9 | Driving through an Item Box will yield one of the following items: 10 | 11 | Green Shells fire directly forward of the player. 12 | 13 | Red Shells home in on the opponent whose rank is one higher than the player. 14 | 15 | Blue Shells navigate along the track until it homes in on the player who is currently in first, potentially hitting other players along the way. 16 | 17 | Banana Peels cause the kart to spin-out, slowing it down a little. 18 | 19 | Fake Item Boxes resemble regular Item Boxes, but they are upside-down. Instead of bestowing items, they cause crashes. 20 | 21 | Mushrooms grant a brief burst of speed. When using multiple mushrooms, it is more effective to space out the bursts rather than consuming them all at once. 22 | 23 | Stars make the player temporarily invulnerable to all damage. In addition, a player using a star travels faster and can run over other players. 24 | 25 | Thunderbolts temporarily shrink all the other racers making them slower and weaker. Shrunken players can be driven over. 26 | 27 | Instructions 28 | ------------ 29 | 30 | X = Accelerate 31 | C = Use items -------------------------------------------------------------------------------- /src/java4k/s23/A.java: -------------------------------------------------------------------------------- 1 | package java4k.s23; 2 | 3 | import java.applet.Applet; 4 | import java.awt.AWTEvent; 5 | import java.awt.Color; 6 | import java.awt.Graphics; 7 | import java.awt.event.KeyEvent; 8 | import java.awt.image.BufferedImage; 9 | import java.util.Random; 10 | 11 | public class A extends Applet implements Runnable { 12 | static boolean keys[] = new boolean[65536]; 13 | final static double PI = 3.1415; 14 | final static int enemynum = 80; 15 | final static int bulletnum = 8000; 16 | final static int itemnum = 8000; 17 | final static int grazenum = 2000; 18 | 19 | public void start() { 20 | enableEvents(AWTEvent.KEY_EVENT_MASK); 21 | new Thread(this).start(); 22 | } 23 | 24 | public void run() { 25 | boolean newGame = true; 26 | for (;;) { 27 | if (newGame) { 28 | l(); 29 | newGame = false; 30 | } 31 | 32 | if (keys[KeyEvent.VK_R]) 33 | newGame = true; 34 | 35 | if (!isActive()) 36 | return; 37 | } 38 | } 39 | 40 | public void l() { 41 | setSize(480, 480); //delete 42 | 43 | Random rndLvl = new Random(23), rndItemStar = new Random(1337); 44 | 45 | BufferedImage screen = new BufferedImage(480, 480, BufferedImage.TYPE_INT_RGB); 46 | Graphics g = screen.getGraphics(); 47 | Graphics appletGraphics = getGraphics(); 48 | 49 | //Variables 50 | //--------- 51 | 52 | int playerX = 225, playerY = 400, shotY = -30, playerSpeed = 1, lastShot = -1380, lives = 3, lastDeath = -120, score = 0, multiplier = 1, nextEnemy = 0, nextEnemyDiff = 180, i, j, stari; 53 | double t1, t2; 54 | 55 | //x - y - state - shootdelay 56 | int[][] enemy = new int[enemynum][4]; 57 | int[] enemyStack = new int[enemynum]; 58 | int enemyStacki = enemynum; 59 | 60 | double[][] enemyB = new double[enemynum][9]; 61 | 62 | //bullet: x - y - angle1 - speed1 - delay1 - homing/angle2 - speed2 - delay2 63 | double[][] bullet = new double[bulletnum][8]; 64 | //state - smooth - grazed 65 | int[][] ibullet = new int[bulletnum][3]; 66 | int[] bulletStack = new int[bulletnum]; 67 | int bulletStacki = bulletnum; 68 | 69 | //x - y - xspeed - yspeed - xacc - yacc 70 | double[][] item = new double[itemnum][6]; 71 | int itemStack[] = new int[itemnum]; 72 | int itemStacki = itemnum; 73 | 74 | int item2[] = { 0, 490, 600, 1 }; 75 | 76 | //x - y - xspeed - yspeed - state 77 | double[][] graze = new double[grazenum][5]; 78 | int[] grazeStack = new int[grazenum]; 79 | int grazeStacki = grazenum; 80 | 81 | double star[][] = new double[75][2]; 82 | 83 | for (i = 0; i < itemnum; ++i) { 84 | if (i < enemynum) { 85 | enemy[i][2] = 0; 86 | enemyStack[i] = i; 87 | } 88 | if (i < bulletnum) { 89 | ibullet[i][0] = 0; 90 | bulletStack[i] = i; 91 | } 92 | if (i < grazenum) { 93 | graze[i][4] = 0; 94 | grazeStack[i] = i; 95 | } 96 | item[i][1] = -10; 97 | itemStack[i] = i; 98 | } 99 | 100 | //Graphics 101 | //-------- 102 | 103 | Graphics g2; 104 | BufferedImage gplayer = new BufferedImage(30, 30, BufferedImage.TYPE_INT_ARGB); 105 | BufferedImage genemy = new BufferedImage(30, 30, BufferedImage.TYPE_INT_ARGB); 106 | BufferedImage gitem = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB); 107 | BufferedImage gbullet = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB); 108 | BufferedImage gbg = new BufferedImage(480, 480, BufferedImage.TYPE_INT_RGB); 109 | 110 | Color bgCol[] = { new Color(64, 20, 64), new Color(160, 60, 160), new Color(112, 112, 140) }; 111 | 112 | //Player and Enemy 113 | long playerG = 35466898305473L, enemyG = 562949815469064L; 114 | for (i = 6; i >= 0; --i) 115 | for (j = 6; j >= 0; --j) { 116 | g2 = gplayer.getGraphics(); 117 | g2.setColor(new Color(128, 0, 16)); 118 | if (playerG % 2 == 1) 119 | g2.fillRect(4 * j, 4 * i, 4, 4); 120 | playerG /= 2; 121 | 122 | g2.setColor(new Color(16, 128, 64)); 123 | g2.fillRect(12, 8, 4, 4); 124 | 125 | g2 = genemy.getGraphics(); 126 | g2.setColor(new Color(16, 128, 64)); 127 | if (enemyG % 2 == 1) 128 | g2.fillRect(4 * j, 4 * i, 4, 4); 129 | enemyG /= 2; 130 | } 131 | 132 | //Items 133 | g2 = gitem.getGraphics(); 134 | g2.setColor(Color.blue); 135 | g2.fillRect(0, 0, 10, 10); 136 | 137 | //Bullet 138 | g2 = gbullet.getGraphics(); 139 | for (i = 0; i < 10; i++) { 140 | g2.setColor(Color.getHSBColor(0f, 0.625f - i / 20f, 0.75f + i / 40f)); 141 | g2.fillOval(i, i, 20 - 2 * i, 20 - 2 * i); 142 | } 143 | 144 | //Stars 145 | for (i = 0; i < 75; ++i) { 146 | star[i][0] = rndItemStar.nextInt(480); 147 | star[i][1] = rndItemStar.nextInt(480); 148 | } 149 | 150 | g2 = gbg.getGraphics(); 151 | g2.setColor(Color.black); 152 | g2.fillRect(0, 0, 480, 480); 153 | 154 | for (stari = 700; stari > 0; --stari) { 155 | t2 = rndItemStar.nextDouble() * 320 - 60; 156 | t1 = t2 * t2 * 0.0034; 157 | 158 | i = (int) t2 + 60; 159 | t1 += (rndItemStar.nextInt(i) - i / 2) / 1.5; 160 | 161 | g2.setColor(Color.getHSBColor(0.9f, 0.4f, 0.5f + i / 640f)); 162 | g2.fillRect((int) t1 + 160, (int) t2 + 220, 1, 1); 163 | } 164 | 165 | for (stari = 1200; stari > 0; --stari) { 166 | i = rndItemStar.nextInt(300); 167 | int d = i - 150; 168 | if (d < 0) 169 | d *= -1; 170 | d = 180 - d; 171 | 172 | j = i + rndItemStar.nextInt(d) - d / 2; 173 | g2.setColor(bgCol[rndItemStar.nextInt(2)]); 174 | if (rndItemStar.nextInt(2) == 0) 175 | g2.setColor(Color.getHSBColor(0.8f, 0.2f, d / 200f)); //200 = 180 + something 176 | g2.fillRect(i + 50, j + 50, 1, 1); 177 | 178 | if (rndItemStar.nextInt(3) == 0) { 179 | d /= 3; 180 | j = i + rndItemStar.nextInt(d) - d / 2; 181 | g2.setColor(bgCol[2]); 182 | g2.fillRect(i + 50, j + 50, 1, 1); 183 | } 184 | } 185 | 186 | for (stari = 480; stari > 0; --stari) { 187 | i = rndItemStar.nextInt(100); 188 | j = rndItemStar.nextInt(100); 189 | int d = (i - 50) * (i - 50) + (j - 50) * (j - 50); 190 | g2.setColor(Color.getHSBColor(0.8f, 0.2f, 1 - d / 6000f)); //6000 = 5000 + something 191 | g2.fillRect(i + 140, j + 130, 1, 1); 192 | g2.fillRect(rndItemStar.nextInt(480), rndItemStar.nextInt(480), 1, 1); 193 | } 194 | 195 | //Main Loop 196 | //--------- 197 | 198 | int fps = 0, fpsout = 0, frame = 0; 199 | long lastfpst, lastfpsoutt = System.nanoTime(); 200 | while (lives >= 0) { 201 | lastfpst = System.nanoTime(); 202 | 203 | //Control 204 | 205 | playerSpeed = 2; 206 | if (keys[KeyEvent.VK_Y] || keys[KeyEvent.VK_Z]) 207 | playerSpeed = 4; 208 | if (keys[KeyEvent.VK_SHIFT]) 209 | playerSpeed = 1; 210 | 211 | if (keys[KeyEvent.VK_ESCAPE]) 212 | lives = -1; 213 | if (keys[KeyEvent.VK_UP] && playerY > 2) 214 | playerY -= playerSpeed; 215 | if (keys[KeyEvent.VK_DOWN] && playerY < 448) 216 | playerY += playerSpeed; 217 | if (keys[KeyEvent.VK_LEFT] && playerX > 2) 218 | playerX -= playerSpeed; 219 | if (keys[KeyEvent.VK_RIGHT] && playerX < 448) 220 | playerX += playerSpeed; 221 | 222 | //Shoot 223 | if ((keys[KeyEvent.VK_X] || keys[KeyEvent.VK_SPACE]) && frame - lastShot >= 1380) { 224 | lastShot = frame; 225 | shotY = playerY; 226 | multiplier = 1; 227 | } 228 | 229 | if (shotY > -30) 230 | shotY -= 4; 231 | 232 | //Items 233 | for (i = 0; i < itemnum; ++i) { 234 | if (item[i][1] > -1) { 235 | item[i][0] += item[i][2]; 236 | item[i][1] += item[i][3]; 237 | 238 | int dir = item[i][2] > 0.0625 ? -1 : 1; 239 | item[i][2] += dir * item[i][4]; 240 | if (item[i][3] < 5) 241 | item[i][3] += item[i][5]; 242 | 243 | if (item[i][1] > 480) { 244 | item[i][1] = -10; 245 | itemStack[itemStacki++] = i; 246 | } 247 | if (item[i][0] > playerX - 5 && item[i][0] < playerX + 25 && item[i][1] > playerY - 5 && item[i][1] < playerY + 25) { 248 | score += 20; 249 | item[i][1] = -10; 250 | itemStack[itemStacki++] = i; 251 | } 252 | } 253 | } 254 | 255 | //Item2 256 | if (item2[1] <= 480) { 257 | item2[1]++; 258 | if (item2[1] > 480) 259 | item2[3] = 1; 260 | } 261 | if (item2[2] == frame) { 262 | item2[0] = rndItemStar.nextInt(450); 263 | item2[1] = -30; 264 | item2[2] += 900; 265 | } 266 | if (playerX + 18 > item2[0] && playerX < item2[0] + 18 && playerY + 18 > item2[1] && playerY < item2[1] + 18) { 267 | score += item2[3] * 500; 268 | if (item2[3] < 32) 269 | item2[3] *= 2; 270 | item2[1] = 490; 271 | } 272 | 273 | //Level Generator 274 | if (frame >= nextEnemy) { 275 | if (enemyStacki > 0) 276 | enemyStacki--; 277 | int ei = enemyStack[enemyStacki]; 278 | enemy[ei][0] = rndLvl.nextInt(400) + 25; 279 | enemy[ei][1] = -30; 280 | enemy[ei][2] = 1; 281 | 282 | nextEnemy = frame + nextEnemyDiff + rndLvl.nextInt(60 + nextEnemyDiff); 283 | if (nextEnemyDiff >= 2) 284 | nextEnemyDiff -= 2; 285 | 286 | enemyB[ei][0] = rndLvl.nextInt(100) + 50; 287 | t1 = enemyB[ei][1] = rndLvl.nextInt(6); 288 | enemyB[ei][2] = 60 + rndLvl.nextInt(4) * 20; 289 | enemyB[ei][3] = 5; 290 | enemyB[ei][4] = 1.5; 291 | enemyB[ei][5] = 20; 292 | enemyB[ei][6] = rndLvl.nextInt(2); 293 | enemyB[ei][7] = 1.5; 294 | enemyB[ei][8] = 60 * (rndLvl.nextInt(2) + 1); 295 | 296 | if (t1 == 2) 297 | enemyB[ei][2] = 25 * rndLvl.nextInt(5) + 100; 298 | if (t1 == 1 || t1 == 2) { 299 | enemyB[ei][5] = 10; 300 | enemyB[ei][6] = 0; 301 | enemyB[ei][7] = 0; 302 | enemyB[ei][8] = -1; 303 | } 304 | } 305 | 306 | //Enemies 307 | for (i = 0; i < enemynum; ++i) { 308 | if (enemy[i][2] > 0) { 309 | if (enemy[i][1] > shotY && enemy[i][1] < shotY + 20 && shotY > -30) { 310 | enemy[i][2] = 0; 311 | enemyStack[enemyStacki++] = i; 312 | 313 | score += 100 * multiplier; 314 | if (frame - lastDeath > 300 && multiplier < 64) 315 | multiplier *= 2; 316 | 317 | for (j = 0; j < 100; ++j) { 318 | if (itemStacki > 0) 319 | itemStacki--; 320 | int ii = itemStack[itemStacki]; 321 | item[ii][0] = enemy[i][0]; 322 | item[ii][1] = enemy[i][1]; 323 | item[ii][2] = rndItemStar.nextInt(100) / 40.0 - 1.25; 324 | item[ii][3] = rndItemStar.nextInt(100) / 50.0 + 0.5; 325 | item[ii][4] = rndItemStar.nextInt(10) * 0.002; 326 | item[ii][5] = rndItemStar.nextInt(10) * 0.0005 + 0.01; 327 | } 328 | } 329 | 330 | //Movement 331 | if (enemy[i][2] == 1) { 332 | enemy[i][1]++; 333 | if (enemy[i][1] > enemyB[i][0]) { 334 | enemy[i][2]++; 335 | enemy[i][3] = 0; 336 | } 337 | } 338 | 339 | //Bullet firing 340 | if (enemy[i][2] == 2 && --enemy[i][3] <= 0) { 341 | enemy[i][3] = 500; 342 | for (j = 0; j < enemyB[i][2]; ++j) { 343 | if (bulletStacki > 0) 344 | bulletStacki--; 345 | int bi = bulletStack[bulletStacki]; 346 | ibullet[bi][0] = 1; 347 | ibullet[bi][2] = 0; 348 | bullet[bi][0] = enemy[i][0]; 349 | bullet[bi][1] = enemy[i][1]; 350 | 351 | bullet[bi][3] = enemyB[i][4]; 352 | bullet[bi][5] = enemyB[i][6]; 353 | bullet[bi][6] = enemyB[i][7]; 354 | bullet[bi][7] = enemyB[i][8]; 355 | 356 | stari = (int) (enemyB[i][2] / enemyB[i][3]); 357 | 358 | //PI*0.04 = 2*PI*0.02 359 | if (enemyB[i][1] == 0 || enemyB[i][1] == 4 || enemyB[i][1] == 5) { 360 | bullet[bi][2] = j * 2 * PI * (enemyB[i][3] / enemyB[i][2]); 361 | bullet[bi][4] = enemyB[i][5] * (j / stari); 362 | 363 | if (enemyB[i][1] == 4) 364 | bullet[bi][2] -= (j / stari) * PI * 0.04; 365 | if (enemyB[i][1] == 5) { 366 | bullet[bi][6] = enemyB[i][7] * (1 + 0.2 * j / stari); 367 | bullet[bi][7] = enemyB[i][5] * (enemyB[i][3] - 1) - bullet[bi][4]; 368 | } 369 | } 370 | if (enemyB[i][1] == 1) { 371 | bullet[bi][2] = (j / enemyB[i][3]) * PI * 0.04 + (j % enemyB[i][3]) * 2 * PI / enemyB[i][3]; 372 | bullet[bi][4] = enemyB[i][5] * (j / enemyB[i][3]); 373 | } 374 | if (enemyB[i][1] == 2) { 375 | int wavenum = 5 * (int) enemyB[i][3]; 376 | bullet[bi][2] = (j / wavenum) * PI * 0.04 + (j % enemyB[i][3]) * 2 * PI / enemyB[i][3]; 377 | bullet[bi][4] = enemyB[i][5] * (((j % wavenum) / enemyB[i][3]) + (j / wavenum) * (enemyB[i][3] + 2)); 378 | } 379 | if (enemyB[i][1] == 3) { 380 | bullet[bi][2] = (-PI / 8) - ((j / 2) % 5) * (PI / 20); 381 | if (j % 2 == 1) 382 | bullet[bi][2] = -PI - bullet[bi][2]; 383 | bullet[bi][4] = enemyB[i][5] * (j / 10); 384 | bullet[bi][5] = 1; 385 | } 386 | 387 | } 388 | } 389 | } 390 | } 391 | 392 | //Bullet movement 393 | for (i = 0; i < bulletnum; ++i) { 394 | if (ibullet[i][0] > 0) { 395 | if (bullet[i][1] > shotY && bullet[i][1] < shotY + 20) { 396 | ibullet[i][0] = 0; 397 | bulletStack[bulletStacki++] = i; 398 | } 399 | 400 | if (ibullet[i][0] == 1 && --bullet[i][4] <= 0) { 401 | ibullet[i][0]++; 402 | ibullet[i][1] = 30; 403 | while (bullet[i][2] > PI) 404 | bullet[i][2] -= 2 * PI; 405 | } 406 | 407 | if (ibullet[i][0] == 2 && --bullet[i][7] == -1) { 408 | ibullet[i][0]++; 409 | if (bullet[i][5] == 1) { 410 | t1 = playerX - bullet[i][0] + 5; 411 | t2 = playerY - bullet[i][1] + 5; 412 | bullet[i][5] = Math.acos(t1 / Math.sqrt(t1 * t1 + t2 * t2)); //dot = t1*1 + t2*0 413 | if (t2 > 0) 414 | bullet[i][5] *= -1; 415 | } else 416 | bullet[i][5] = bullet[i][2]; 417 | bullet[i][5] -= bullet[i][2]; 418 | } 419 | 420 | if (ibullet[i][0] == 2 || ibullet[i][0] == 3) { 421 | if (ibullet[i][0] == 3 && ibullet[i][1] > 0) 422 | ibullet[i][1]--; 423 | t1 = bullet[i][2] + bullet[i][5] * (30 - ibullet[i][1]) / 30.0; 424 | t2 = ibullet[i][1] / 30.0 * bullet[i][3] + (30 - ibullet[i][1]) / 30.0 * bullet[i][6]; 425 | bullet[i][0] += Math.cos(t1) * t2; 426 | bullet[i][1] -= Math.sin(t1) * t2; 427 | 428 | if (bullet[i][0] < -20 || bullet[i][0] > 480 || bullet[i][1] < -20 || bullet[i][1] > 480) { 429 | ibullet[i][0] = 0; 430 | bulletStack[bulletStacki++] = i; 431 | } 432 | 433 | t1 = (playerX + 4 - bullet[i][0]) * (playerX + 4 - bullet[i][0]) + (playerY - bullet[i][1]) * (playerY - bullet[i][1]); 434 | if (t1 < 100 && frame - lastDeath > 120) { 435 | playerX = 225; 436 | playerY = 400; 437 | lives--; 438 | lastDeath = frame; 439 | } 440 | if (t1 < 1600 && ibullet[i][2] == 0) { 441 | ibullet[i][2] = 1; 442 | score += 20; 443 | 444 | if (grazeStacki > 0) 445 | grazeStacki--; 446 | int gi = grazeStack[grazeStacki]; 447 | graze[gi][0] = playerX + 16; 448 | graze[gi][1] = playerY + 12; 449 | graze[gi][2] = 2 * rndItemStar.nextDouble() - 1; 450 | graze[gi][3] = 2 * rndItemStar.nextDouble() - 1; 451 | graze[gi][4] = 60; 452 | } 453 | } 454 | } 455 | } 456 | 457 | //Graze 458 | for (i = 0; i < grazenum; ++i) 459 | if (graze[i][4] > 0) { 460 | graze[i][0] += graze[i][2]; 461 | graze[i][1] += graze[i][3]; 462 | if (--graze[i][4] <= 0) 463 | grazeStack[grazeStacki++] = i; 464 | } 465 | 466 | //Blitting 467 | 468 | g.drawImage(gbg, 0, 0, null); 469 | 470 | //Stars 471 | for (i = 1, stari = 0; i <= 5; ++i) 472 | for (j = 0; j < i * 5; ++j, ++stari) { 473 | star[stari][1] += (26 - i * i) * 0.01; 474 | if (star[stari][1] > 480) { 475 | star[stari][0] = rndItemStar.nextInt(480); 476 | star[stari][1] = -rndItemStar.nextInt(30) - 10; 477 | } 478 | g.setColor(Color.white); 479 | g.fillRect((int) star[stari][0], (int) star[stari][1], (6 - i), (6 - i)); 480 | } 481 | 482 | if (item2[1] <= 480) { 483 | g.setColor(Color.blue); 484 | g.fillRect(item2[0], item2[1], 30, 30); 485 | } 486 | for (i = 0; i < enemynum; ++i) 487 | if (enemy[i][2] > 0) 488 | g.drawImage(genemy, enemy[i][0], enemy[i][1], null); 489 | if (frame - lastDeath > 120 || (frame / 10) % 3 > 0) 490 | g.drawImage(gplayer, playerX, playerY, null); 491 | for (i = 0; i < itemnum; ++i) 492 | if (item[i][1] > -1) 493 | g.drawImage(gitem, (int) item[i][0], (int) item[i][1], null); 494 | for (i = 0; i < bulletnum; ++i) 495 | if (ibullet[i][0] > 1) 496 | g.drawImage(gbullet, (int) bullet[i][0], (int) bullet[i][1], null); 497 | g.setColor(Color.pink); 498 | for (i = 0; i < grazenum; ++i) 499 | if (graze[i][4] > 0) 500 | g.fillRect((int) graze[i][0], (int) graze[i][1], 2, 2); 501 | if (shotY > -30) 502 | g.fillRect(0, shotY, 480, 20); 503 | 504 | int cd = (1439 - frame + lastShot) / 60; 505 | if (cd < 0) 506 | cd = 0; 507 | g.setColor(Color.white); 508 | g.drawString("Score: " + String.valueOf(score), 5, 15); 509 | g.drawString("Lives: " + String.valueOf(lives), 5, 30); 510 | g.drawString("Next Bomb: " + String.valueOf(cd), 5, 45); 511 | g.drawString("FPS: " + String.valueOf(fpsout), 430, 475); 512 | 513 | appletGraphics.drawImage(screen, 0, 0, null); 514 | 515 | do { 516 | Thread.yield(); 517 | } while (System.nanoTime() - lastfpst < 16600000L); 518 | 519 | fps++; 520 | frame++; 521 | if (System.nanoTime() - lastfpsoutt >= 1000000000L) { 522 | fpsout = fps; 523 | fps = 0; 524 | lastfpsoutt += 1000000000L; 525 | } 526 | 527 | if (!isActive()) 528 | return; 529 | } 530 | 531 | g.drawString("GAME OVER", 200, 220); 532 | g.drawString("Press 'R' to Restart", 190, 240); 533 | appletGraphics.drawImage(screen, 0, 0, null); 534 | } 535 | 536 | public void processKeyEvent(KeyEvent e) { 537 | keys[e.getKeyCode()] = (e.getID() == KeyEvent.KEY_PRESSED); 538 | } 539 | } -------------------------------------------------------------------------------- /src/java4k/s23/A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/s23/A.png -------------------------------------------------------------------------------- /src/java4k/s23/readme.txt: -------------------------------------------------------------------------------- 1 | 23 seconds 2 | ========== 3 | 4 | Description 5 | ----------- 6 | 7 | Lost in space with defective laser weapons, your only way to survive are the ship's bombs. 8 | But these need 23 seconds to reload. 23 seconds you need to survive. 9 | 10 | Instructions 11 | ------------ 12 | 13 | Arrows: Move 14 | X/Space: Bomb 15 | Z/Y: Speed up 16 | Left Shift: Slow down 17 | Escape: Abort game 18 | 19 | Scoring: 20 | Destroy as many enemies as possible at once. 21 | Graze bullets. 22 | Collect the small items enemies drop when being destroyed. 23 | Collect the large items that appear from time to time. Don't miss them to get more points. 24 | (By the way: Destroying enemies immediately after you've died, doesn't give you many points) -------------------------------------------------------------------------------- /src/java4k/scramble/G.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/scramble/G.png -------------------------------------------------------------------------------- /src/java4k/scramble/readme.txt: -------------------------------------------------------------------------------- 1 | Scramble 2 | ======== 3 | 4 | Description 5 | ----------- 6 | 7 | My attempt at the age old classic arcade game SCRAMBLE. 8 | 9 | Have fun! 10 | 11 | By Tim Foden 12 | 13 | Instructions 14 | ------------ 15 | 16 | Use the arrow keys or WASD to move. 17 | Use SHIFT or SPACE to fire bullets. 18 | Use CTRL or \ or / to fire bombs. 19 | Use '1' to start playing. -------------------------------------------------------------------------------- /src/java4k/spacedevastation/A.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/spacedevastation/A.java -------------------------------------------------------------------------------- /src/java4k/spacedevastation/A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/spacedevastation/A.png -------------------------------------------------------------------------------- /src/java4k/spacedevastation/readme.txt: -------------------------------------------------------------------------------- 1 | Space Devastation 2 | ================= 3 | 4 | Description 5 | ----------- 6 | 7 | Welcome to "Space Devastation!" 8 | You are the lucky owner of a heavily armed spaceship. During a tuning exhibition, someone use his keys to scratch the paint! When you realize the fact, the criminal is already gone. In an attempt to catch his flying wreck, you accidentally hit an asteroid! The world is against you, what do I say the universe! 9 | 10 | So you decide to take revenge of the universe by destroying it! 11 | 12 | Unfortunately, the legions of Captain Galaxy are not going to let you do! Will that be enough to stop you? Your ship has been damaged in the collision (but vengeance cannot wait!) Your repairs bots has begun to do their work. Your spaceship will not be fully operational from the beginning, but it would be soon! 13 | 14 | The Secret tips of General Forthx: 15 | 16 | Your shield and your ultralaser both use energy. This energy slowly recharges but if it drop below 25% ultralaser is disabled for your own security. 17 | Enemies do not use a shield. If they are damaged they lose attack power. 18 | The shootings of most dangerous enemies are brighter than others. 19 | Your secondary fire (ultralaser) is expensive but devastating! Do not forget it! 20 | Each level you gain energy bonus and each two levels you gain a special bonus due to the reparations. This bonus can change your way to play ! 21 | 22 | The game has 10 levels and 3 modes: 23 | 24 | The first mode is good for learning to play and for CASUAL gamers. For other it could be quickly boring. The game is slow and it is possible to complete it without the ultralaser. 25 | 26 | The second mode is for AVERAGE gamers who want some challenge. In this mode you must learn to use your ultralaser to reach level 10, even if the game starts smoothly. 27 | 28 | The third mode is for trained player who wants adrenalin and scoring. You have more speed, more enemies, more bullets and obviously more fun! 29 | 30 | Instructions 31 | ------------ 32 | 33 | Instructions: 34 | Read the story, annihilate your enemies, and destroy the galaxy! 35 | 36 | Update: 37 | You can use the two fire mode simultaneously. 38 | 3mode added, the easy mode could be complete in less than 10 min. 39 | 40 | Input: 41 | 42 | Mouse move = aim for destination. 43 | Left click = primary lasers, hold click for autofire. 44 | Right click = ultralaser, hold click for massive destruction. 45 | 46 | -------------------------------------------------------------------------------- /src/java4k/supermarioland4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/supermarioland4k/a.png -------------------------------------------------------------------------------- /src/java4k/supermarioland4k/readme.txt: -------------------------------------------------------------------------------- 1 | Super Mario Land 4K 2 | =================== 3 | 4 | Description 5 | ----------- 6 | 7 | To rescue Princess Daisy, beat all 5 levels. 8 | 9 | Instructions 10 | ------------ 11 | 12 | Use the arrow keys or the WASD keys to move. Press any other key to jump. -------------------------------------------------------------------------------- /src/java4k/thebattleforhoth4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/thebattleforhoth4k/a.png -------------------------------------------------------------------------------- /src/java4k/thebattleforhoth4k/readme.txt: -------------------------------------------------------------------------------- 1 | Star Wars: The Battle for Hoth 4K 2 | ================================= 3 | 4 | Description 5 | ----------- 6 | 7 | "No one ever complained about the cold on Hoth. We never felt it. Even though we were blinded by blizzards, 8 | we could see the final end of the Rebellion in our blaster sights. Was it only a mirage? Perhaps; 9 | but on that day, on that planet, our blood ran hot with dreams of victory, 10 | melting the ice that stood in our way." -- Unknown Stormtrooper 11 | 12 | Instructions 13 | ------------ 14 | 15 | Use the arrow keys or the WASD keys to move. The left and right keys control heading. 16 | The up and down keys control altitude. Hold down any other key for auto-fire. 17 | While firing, your ship slows to half speed to aid in targeting. 18 | 19 | Pay attention to your radar in the upper-right. It will guide you to the remaining enemies. 20 | 21 | If you inadvertently fly away from the battle zone, your ship's autopilot will momentarily take control 22 | to steer you back into the action. 23 | 24 | There are 5 stages to beat. Press any key to begin. -------------------------------------------------------------------------------- /src/java4k/wolfenstein4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/wolfenstein4k/a.png -------------------------------------------------------------------------------- /src/java4k/wolfenstein4k/readme.txt: -------------------------------------------------------------------------------- 1 | Wolfenstein 4K 2 | ============== 3 | 4 | Description 5 | ----------- 6 | 7 | Get Psyched! If you successfully battle through all 6 levels... CALL APOGEE SAY "AARDWOLF". 8 | But, please don't mention copyright and intellectual property infringement. 9 | 10 | Instructions 11 | ------------ 12 | 13 | Use the arrow keys or the WASD keys to move. Use spacebar to open doors. Use any other key to fire. -------------------------------------------------------------------------------- /src/java4k/yoshiscoins4k/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glegris/Java4K/78115366f4134a69d7a1ca9ddf03a4b76874741e/src/java4k/yoshiscoins4k/a.png -------------------------------------------------------------------------------- /src/java4k/yoshiscoins4k/readme.txt: -------------------------------------------------------------------------------- 1 | Yoshi's Coins 4k 2 | ================ 3 | 4 | Description 5 | ----------- 6 | 7 | Yoshi's Coins (also known as Connect Four, Four in a Row, Four in a Line, Four Up, Plot Four and Find Four) is 8 | a turn-based game in which the players drop coins from the top into a seven-column, six-row vertically-suspended grid. 9 | The coins fall straight down, occupying the next available space within the column. The object of the game is to connect 10 | four yellow coins next to each other vertically, horizontally or diagonally before Yoshi does it with red coins. 11 | 12 | You start off with 1 egg and each time you beat Yoshi, you gain another egg. 13 | For each egg you own, Yoshi becomes a more challenging opponent. 14 | If you own 7 eggs and you beat Yoshi, you win the tournament. Good luck! 15 | 16 | Instructions 17 | ------------ 18 | 19 | When it's your turn, click on a column to drop a yellow coin. When play ends, click to start a new game. --------------------------------------------------------------------------------