Klicka på startknappen i den lilla mediespelaren ovan för att lyssna på lektionen. (Man kan behöva vänta en stund på att ljudfilen laddas ner.) Om mediespelaren inte syns, eller om det inte fungerar av något annat skäl, kan man klicka här för att ladda ner mp3-filen (ca 29 minuter, ca 13 megabyte). Beroende på hur webbläsaren är konfigurerad kan det kräva ett separat mp3-spelarprogram av något slag. Bild 1: En studsboll I lektionen om hur man ritar saker såg vi hur man kan rita upp saker på en Canvas. Man anropar metoder som drawLine, drawRect och fillRect. Vi såg också hur man kunde få grafiken att ändras på kommando från användaren. Rörlig grafik innebär att grafiken ändras av sig själv, utan kommandon från användaren. Programmet ska självt göra ändringar, helst många gånger per sekund. Vi ska göra en studsboll som åker runt på skärmen och studsar på kanterna: "Bild" 2: Data om studsbollen Utseende: radie, färg Var är bollen nu: x och y Bollens riktning och hastighet: delta-x och delta-y "Bild" 3: Klassen Studsboll1 Klassen Studsboll1. Utdrag ur filen Studsboll1.java: 1 public class Studsboll1 extends MIDlet { 2 private Display displayen; 3 private Studscanvas canvasen; 4 5 public void startApp() { 6 displayen = Display.getDisplay(this); 7 if (canvasen == null) { 8 canvasen = new Studscanvas(); 9 displayen = Display.getDisplay(this); 10 displayen.setCurrent(canvasen); 11 } 12 } 13 14 public void pauseApp() { } 15 16 public void destroyApp(boolean unconditional) { } 17 } // class Studsboll1 "Bild" 4: Klassen Studscanvas - ett misslyckat försök Klassen Studscanvas, ur programmet Studsboll1. Filen Studscanvas.java: 1 // Studscanvas.java 2 3 import javax.microedition.lcdui.*; 4 5 public class Studscanvas extends Canvas { 6 int ball_radius; 7 double ball_x, ball_y, ball_dx, ball_dy; 8 9 public Studscanvas() { 10 int screen_width = getWidth(); 11 int screen_height = getHeight(); 12 13 ball_radius = 5; 14 ball_x = screen_width / 2; 15 ball_y = screen_height / 2; 16 ball_dx = 1; 17 ball_dy = -1; 18 19 // This doesn't work 20 while (true) { 21 update_game_state(); 22 repaint(); 23 } 24 } 25 26 private void update_game_state() { 27 int screen_width = getWidth(); 28 int screen_height = getHeight(); 29 ball_x += ball_dx; // This means: ball_x = ball_x + ball_dx; 30 ball_y += ball_dy; 31 if (ball_x + ball_radius >= screen_width) { 32 ball_dx *= -1; // Same as: ball_dx = -ball_dx; 33 } 34 else if (ball_x - ball_radius <= 0) { 35 ball_dx *= -1; 36 } 37 if (ball_y - ball_radius <= 0) { 38 ball_dy *= -1; 39 } 40 else if (ball_y + ball_radius >= screen_height) { 41 ball_dy *= -1; 42 } 43 44 System.out.println("ball_x = " + ball_x + ", ball_y = " + ball_y + 45 ", ball_dx = " + ball_dx + " + ball_dy = " + ball_dy); 46 } 47 48 public void paint(Graphics g) { 49 g.setColor(0xffffff); 50 g.fillRect(0, 0, getWidth(), getHeight()); 51 g.setColor(0x000000); 52 g.fillArc((int)(ball_x - ball_radius), (int)(ball_y - ball_radius), 53 ball_radius * 2, ball_radius * 2, 0, 360); 54 } 55 56 } // class Studscanvas "Bild" 5: En bättre Studscanvas Använd en egen tråd eller en timer i stället för en loop. En timer är enklast. Klassen Studscanvas, ur programmet Studsboll2. Filen Studscanvas.java: 1 // Studscanvas.java 2 3 import java.util.*; 4 import javax.microedition.lcdui.*; 5 6 public class Studscanvas extends Canvas { 7 int ball_radius; 8 double ball_x, ball_y, ball_dx, ball_dy; 9 Timer the_timer; 10 11 public Studscanvas() { 12 int screen_width = getWidth(); 13 int screen_height = getHeight(); 14 15 ball_radius = 5; 16 ball_x = screen_width / 2; 17 ball_y = screen_height / 2; 18 ball_dx = 1; 19 ball_dy = -1; 20 } 21 22 public void showNotify() { 23 the_timer = new Timer(); 24 TimerTask task = new TimerTask() { 25 public void run() { 26 update_game_state(); 27 repaint(); 28 } 29 }; 30 the_timer.schedule(task, 0, 20); 31 } 32 33 public void hideNotify() { 34 if (the_timer != null) { 35 the_timer.cancel(); 36 the_timer = null; 37 } 38 } 39 40 private void update_game_state() { 41 int screen_width = getWidth(); 42 int screen_height = getHeight(); 43 ball_x += ball_dx; 44 ball_y += ball_dy; 45 if (ball_x + ball_radius >= screen_width) { 46 ball_dx *= -1; 47 } 48 else if (ball_x - ball_radius <= 0) { 49 ball_dx *= -1; 50 } 51 if (ball_y - ball_radius <= 0) { 52 ball_dy *= -1; 53 } 54 else if (ball_y + ball_radius >= screen_height) { 55 ball_dy *= -1; 56 } 57 58 System.out.println("ball_x = " + ball_x + ", ball_y = " + ball_y + 59 ", ball_dx = " + ball_dx + " + ball_dy = " + ball_dy); 60 } 61 62 public void paint(Graphics g) { 63 g.setColor(0xffffff); 64 g.fillRect(0, 0, getWidth(), getHeight()); 65 g.setColor(0x000000); 66 g.fillArc((int)(ball_x - ball_radius), (int)(ball_y - ball_radius), 67 ball_radius * 2, ball_radius * 2, 0, 360); 68 } 69 70 } // class Studscanvas "Bild" 6: En ännu bättre Studscanvas Klassen Studscanvas, ur programmet Studsboll3. Filen Studscanvas.java: 1 // Studscanvas.java 2 3 import java.util.*; 4 import javax.microedition.lcdui.*; 5 import javax.microedition.lcdui.game.*; 6 7 public class Studscanvas extends GameCanvas { 8 int ball_radius; 9 double ball_x, ball_y, ball_dx, ball_dy; 10 Timer the_timer; 11 Graphics g; 12 13 public Studscanvas() { 14 super(false); 15 int screen_width = getWidth(); 16 int screen_height = getHeight(); 17 18 ball_radius = 5; 19 ball_x = screen_width / 2; 20 ball_y = screen_height / 2; 21 ball_dx = 1; 22 ball_dy = -1; 23 } 24 25 public void showNotify() { 26 the_timer = new Timer(); 27 g = getGraphics(); 28 TimerTask task = new TimerTask() { 29 public void run() { 30 update_game_state(); 31 render(); 32 flushGraphics(); 33 } 34 }; 35 the_timer.schedule(task, 0, 20); 36 } 37 38 public void hideNotify() { 39 if (the_timer != null) { 40 the_timer.cancel(); 41 the_timer = null; 42 } 43 } 44 45 private void update_game_state() { 46 int screen_width = getWidth(); 47 int screen_height = getHeight(); 48 ball_x += ball_dx; 49 ball_y += ball_dy; 50 if (ball_x + ball_radius >= screen_width) { 51 ball_dx *= -1; 52 } 53 else if (ball_x - ball_radius <= 0) { 54 ball_dx *= -1; 55 } 56 if (ball_y - ball_radius <= 0) { 57 ball_dy *= -1; 58 } 59 else if (ball_y + ball_radius >= screen_height) { 60 ball_dy *= -1; 61 } 62 63 System.out.println("ball_x = " + ball_x + ", ball_y = " + ball_y + 64 ", ball_dx = " + ball_dx + " + ball_dy = " + ball_dy); 65 } 66 67 public void render() { 68 g.setColor(0xffffff); 69 g.fillRect(0, 0, getWidth(), getHeight()); 70 g.setColor(0x000000); 71 g.fillArc((int)(ball_x - ball_radius), (int)(ball_y - ball_radius), 72 ball_radius * 2, ball_radius * 2, 0, 360); 73 } 74 75 } // class Studscanvas "Bild" 7: Knapptryckningar Man kan använda metoderna keyPressed, keyReleased och keyRepeated, eller hantera knapptryckningarna helt själv med getKeyStates. Ur klassen Studscanvas, från programmet Studsboll4. Filen Studscanvas.java: 1 private void process_keys() { 2 int keys = getKeyStates(); 3 // System.out.println("keys = " + keys); 4 if ((keys & LEFT_PRESSED) != 0) { 5 System.out.println("Pressed left!"); 6 ball_dx -= 1; 7 } 8 if ((keys & RIGHT_PRESSED) != 0) { 9 System.out.println("Pressed right!"); 10 ball_dx += 1; 11 } 12 if ((keys & UP_PRESSED) != 0) { 13 System.out.println("Pressed up!"); 14 ball_dy -= 1; 15 } 16 if ((keys & DOWN_PRESSED) != 0) { 17 System.out.println("Pressed down!"); 18 ball_dy += 1; 19 } 20 if ((keys & FIRE_PRESSED) != 0) { 21 System.out.println("Pressed FIRE!"); 22 ball_dx = 0; 23 ball_dy = 0; 24 } 25 } "Bild" 8: Lägg till process_keys i "spel-loopen" Ur klassen Studscanvas, från programmet Studsboll4. Filen Studscanvas.java: 1 public void showNotify() { 2 the_timer = new Timer(); 3 g = getGraphics(); 4 TimerTask task = new TimerTask() { 5 public void run() { 6 process_keys(); 7 update_game_state(); 8 render(); 9 flushGraphics(); 10 } 11 }; 12 the_timer.schedule(task, 0, 20); 13 } Bild 9: Ett problem med knapptryckningar "Kontakstudsar" på telefonen, och ännu värre i emulatorn. "Bild" 10: Tangent-repeat Man kan hålla reda på tangentrepeaten själv: Håller användaren knappen nere nu? Om hon håller knappen nere: var det mer än (säg) en kvarts sekund (dvs 250 millisekunder) sen knappen "räknades" senast? Om det var mer än en kvarts sekund: räkna knapptryckningen, och börja om att räkna tiden. Om användaren inte håller knappen nere, eller om det var mindre än en kvarts sekund sen den "räknades" senast: gör ingenting. Se även: http://devlinslab.blogspot.com/2007/10/input-handling-keypress-with-repeat.html "Bild" 11: Tangent-repeat som kod Klassen Studscanvas, från programmet Studsboll5. Ur filen Studscanvas.java: 1 // Studscanvas.java 2 3 import java.util.*; 4 import javax.microedition.lcdui.*; 5 import javax.microedition.lcdui.game.*; 6 7 public class Studscanvas extends GameCanvas { 8 int ball_radius; 9 double ball_x, ball_y, ball_dx, ball_dy; 10 Timer the_timer; 11 Graphics g; 12 13 // Key repeat rate in milliseconds 14 public static final int KEY_REPEAT_RATE = 250; 15 16 // Key constants 17 public static final int MY_UP_KEY = 0; 18 public static final int MY_LEFT_KEY = 1; 19 public static final int MY_DOWN_KEY = 2; 20 public static final int MY_RIGHT_KEY = 3; 21 public static final int MY_FIRE_KEY = 4; 22 23 // Key states for up, left, down, right, and fire key 24 private boolean[] key_is_down = { 25 false, false, false, false, false 26 }; 27 28 // The last time each key changed state 29 private long[] last_key_time = { 30 0, 0, 0, 0, 0 31 }; 32 33 // Lookup table for key constants 34 private int[] key_value = { 35 GameCanvas.UP_PRESSED, 36 GameCanvas.LEFT_PRESSED, 37 GameCanvas.DOWN_PRESSED, 38 GameCanvas.RIGHT_PRESSED, 39 GameCanvas.FIRE_PRESSED 40 }; ... 75 private void process_keys() { 76 int keys = getKeyStates(); 77 long current_time = System.currentTimeMillis(); 78 79 // Loop through the keys 80 for (int i = 0; i < 5; i++){ 81 82 // By default, the key is not pressed 83 key_is_down[i] = false; 84 85 // Is the user pressing this key? 86 if ((keys & key_value[i]) != 0) { 87 long elapsed_time = current_time - last_key_time[i]; 88 89 // Is it time to toggle the key state? 90 if (elapsed_time >= KEY_REPEAT_RATE) { 91 92 // Save the current time 93 last_key_time[i] = current_time; 94 95 // Toggle the state to "down" 96 key_is_down[i] = true; 97 } 98 } 99 } 100 101 if (key_is_down[MY_LEFT_KEY]) { 102 System.out.println("Pressed left!"); 103 ball_dx -= 1; 104 } 105 if (key_is_down[MY_RIGHT_KEY]) { 106 System.out.println("Pressed right!"); 107 ball_dx += 1; 108 } 109 if (key_is_down[MY_UP_KEY]) { 110 System.out.println("Pressed up!"); 111 ball_dy -= 1; 112 } 113 if (key_is_down[MY_DOWN_KEY]) { 114 System.out.println("Pressed down!"); 115 ball_dy += 1; 116 } 117 if (key_is_down[MY_FIRE_KEY]) { 118 System.out.println("Pressed FIRE!"); 119 ball_dx = 0; 120 ball_dy = 0; 121 } 122 123 } ... "Bild" 12: Ett mycket enklare sätt Som vi sagt ovan: Man kan använda metoderna keyPressed, keyReleased och keyRepeated, eller hantera knapptryckningarna helt själv med getKeyStates. Nu provar vi med keyPressed med flera. Klassen Studscanvas, från programmet Studsboll6. Ur filen Studscanvas.java: 1 protected void keyPressed(int keyCode) { 2 System.out.println("keyPressed, keyCode = " + keyCode); 3 int game_action = getGameAction(keyCode); 4 System.out.println("keyPressed, game_action = " + game_action); 5 6 switch (game_action) { 7 case UP: ball_dy -= 1; break; 8 case DOWN: ball_dy += 1; break; 9 case LEFT: ball_dx -= 1; break; 10 case RIGHT: ball_dx += 1; break; 11 case FIRE: ball_dx = 0; ball_dy = 0; break; 12 } 13 } 14 15 protected void keyRepeated(int keyCode) { 16 System.out.println("keyRepeated, keyCode = " + keyCode); 17 keyPressed(keyCode); 18 } 19 20 protected void keyReleased(int keyCode) { 21 System.out.println("keyReleased, keyCode = " + keyCode); 22 } Läsanvisningar Man kan läsa mer om klassen GameCanvas i kapitel 11, Using the Game API, i den nya kursboken Kicking Butt with MIDP and MSA. I den gamla kursboken Beginning J2ME kan man läsa kapitel 14, The Game API. Programmeringsövningar Det finns inget kommando för att avsluta studsbollsprogrammet. Lägg till ett Avsluta-kommando till canvasen. Lägg till en racket, som visas längst ner på canvasen. Den ritas som en fyrkant med fillRect. Håll reda på racketens bredd, x-koordinat och y-koordinat i tre variabler. Ändra studsbollsprogrammet så man inte längre styr bollens hastighet med knapparna, utan låt vänster- och högerknapparna på telefonen ändra racketens position i x-led. Ändra studsen mot den nedersta kanten av canvasen till att studsa mot racketen, men bara om bollen träffar racketen. Om bollen missar, ska spelet avslutas. Ladda ner exempel-midleten till kursbokens kapitel 11 från http://kickbutt.jonathanknudsen.com/. Får man problem med att en knapptryckning registreras som flera? I så fall, laga. Fungerar det olika i emulatorn, och (om du har en) på din riktiga telefon? Föregående lektion | Lektionslista | Nästa lektion Thomas Padron-McCarthy (Thomas.Padron-McCarthy@oru.se), 13 juni 2008
Klicka på startknappen i den lilla mediespelaren ovan för att lyssna på lektionen. (Man kan behöva vänta en stund på att ljudfilen laddas ner.) Om mediespelaren inte syns, eller om det inte fungerar av något annat skäl, kan man klicka här för att ladda ner mp3-filen (ca 29 minuter, ca 13 megabyte). Beroende på hur webbläsaren är konfigurerad kan det kräva ett separat mp3-spelarprogram av något slag.
Rörlig grafik innebär att grafiken ändras av sig själv, utan kommandon från användaren. Programmet ska självt göra ändringar, helst många gånger per sekund. Vi ska göra en studsboll som åker runt på skärmen och studsar på kanterna:
1 public class Studsboll1 extends MIDlet { 2 private Display displayen; 3 private Studscanvas canvasen; 4 5 public void startApp() { 6 displayen = Display.getDisplay(this); 7 if (canvasen == null) { 8 canvasen = new Studscanvas(); 9 displayen = Display.getDisplay(this); 10 displayen.setCurrent(canvasen); 11 } 12 } 13 14 public void pauseApp() { } 15 16 public void destroyApp(boolean unconditional) { } 17 } // class Studsboll1
1 // Studscanvas.java 2 3 import javax.microedition.lcdui.*; 4 5 public class Studscanvas extends Canvas { 6 int ball_radius; 7 double ball_x, ball_y, ball_dx, ball_dy; 8 9 public Studscanvas() { 10 int screen_width = getWidth(); 11 int screen_height = getHeight(); 12 13 ball_radius = 5; 14 ball_x = screen_width / 2; 15 ball_y = screen_height / 2; 16 ball_dx = 1; 17 ball_dy = -1; 18 19 // This doesn't work 20 while (true) { 21 update_game_state(); 22 repaint(); 23 } 24 } 25 26 private void update_game_state() { 27 int screen_width = getWidth(); 28 int screen_height = getHeight(); 29 ball_x += ball_dx; // This means: ball_x = ball_x + ball_dx; 30 ball_y += ball_dy; 31 if (ball_x + ball_radius >= screen_width) { 32 ball_dx *= -1; // Same as: ball_dx = -ball_dx; 33 } 34 else if (ball_x - ball_radius <= 0) { 35 ball_dx *= -1; 36 } 37 if (ball_y - ball_radius <= 0) { 38 ball_dy *= -1; 39 } 40 else if (ball_y + ball_radius >= screen_height) { 41 ball_dy *= -1; 42 } 43 44 System.out.println("ball_x = " + ball_x + ", ball_y = " + ball_y + 45 ", ball_dx = " + ball_dx + " + ball_dy = " + ball_dy); 46 } 47 48 public void paint(Graphics g) { 49 g.setColor(0xffffff); 50 g.fillRect(0, 0, getWidth(), getHeight()); 51 g.setColor(0x000000); 52 g.fillArc((int)(ball_x - ball_radius), (int)(ball_y - ball_radius), 53 ball_radius * 2, ball_radius * 2, 0, 360); 54 } 55 56 } // class Studscanvas
Klassen Studscanvas, ur programmet Studsboll2. Filen Studscanvas.java:
1 // Studscanvas.java 2 3 import java.util.*; 4 import javax.microedition.lcdui.*; 5 6 public class Studscanvas extends Canvas { 7 int ball_radius; 8 double ball_x, ball_y, ball_dx, ball_dy; 9 Timer the_timer; 10 11 public Studscanvas() { 12 int screen_width = getWidth(); 13 int screen_height = getHeight(); 14 15 ball_radius = 5; 16 ball_x = screen_width / 2; 17 ball_y = screen_height / 2; 18 ball_dx = 1; 19 ball_dy = -1; 20 } 21 22 public void showNotify() { 23 the_timer = new Timer(); 24 TimerTask task = new TimerTask() { 25 public void run() { 26 update_game_state(); 27 repaint(); 28 } 29 }; 30 the_timer.schedule(task, 0, 20); 31 } 32 33 public void hideNotify() { 34 if (the_timer != null) { 35 the_timer.cancel(); 36 the_timer = null; 37 } 38 } 39 40 private void update_game_state() { 41 int screen_width = getWidth(); 42 int screen_height = getHeight(); 43 ball_x += ball_dx; 44 ball_y += ball_dy; 45 if (ball_x + ball_radius >= screen_width) { 46 ball_dx *= -1; 47 } 48 else if (ball_x - ball_radius <= 0) { 49 ball_dx *= -1; 50 } 51 if (ball_y - ball_radius <= 0) { 52 ball_dy *= -1; 53 } 54 else if (ball_y + ball_radius >= screen_height) { 55 ball_dy *= -1; 56 } 57 58 System.out.println("ball_x = " + ball_x + ", ball_y = " + ball_y + 59 ", ball_dx = " + ball_dx + " + ball_dy = " + ball_dy); 60 } 61 62 public void paint(Graphics g) { 63 g.setColor(0xffffff); 64 g.fillRect(0, 0, getWidth(), getHeight()); 65 g.setColor(0x000000); 66 g.fillArc((int)(ball_x - ball_radius), (int)(ball_y - ball_radius), 67 ball_radius * 2, ball_radius * 2, 0, 360); 68 } 69 70 } // class Studscanvas
1 // Studscanvas.java 2 3 import java.util.*; 4 import javax.microedition.lcdui.*; 5 import javax.microedition.lcdui.game.*; 6 7 public class Studscanvas extends GameCanvas { 8 int ball_radius; 9 double ball_x, ball_y, ball_dx, ball_dy; 10 Timer the_timer; 11 Graphics g; 12 13 public Studscanvas() { 14 super(false); 15 int screen_width = getWidth(); 16 int screen_height = getHeight(); 17 18 ball_radius = 5; 19 ball_x = screen_width / 2; 20 ball_y = screen_height / 2; 21 ball_dx = 1; 22 ball_dy = -1; 23 } 24 25 public void showNotify() { 26 the_timer = new Timer(); 27 g = getGraphics(); 28 TimerTask task = new TimerTask() { 29 public void run() { 30 update_game_state(); 31 render(); 32 flushGraphics(); 33 } 34 }; 35 the_timer.schedule(task, 0, 20); 36 } 37 38 public void hideNotify() { 39 if (the_timer != null) { 40 the_timer.cancel(); 41 the_timer = null; 42 } 43 } 44 45 private void update_game_state() { 46 int screen_width = getWidth(); 47 int screen_height = getHeight(); 48 ball_x += ball_dx; 49 ball_y += ball_dy; 50 if (ball_x + ball_radius >= screen_width) { 51 ball_dx *= -1; 52 } 53 else if (ball_x - ball_radius <= 0) { 54 ball_dx *= -1; 55 } 56 if (ball_y - ball_radius <= 0) { 57 ball_dy *= -1; 58 } 59 else if (ball_y + ball_radius >= screen_height) { 60 ball_dy *= -1; 61 } 62 63 System.out.println("ball_x = " + ball_x + ", ball_y = " + ball_y + 64 ", ball_dx = " + ball_dx + " + ball_dy = " + ball_dy); 65 } 66 67 public void render() { 68 g.setColor(0xffffff); 69 g.fillRect(0, 0, getWidth(), getHeight()); 70 g.setColor(0x000000); 71 g.fillArc((int)(ball_x - ball_radius), (int)(ball_y - ball_radius), 72 ball_radius * 2, ball_radius * 2, 0, 360); 73 } 74 75 } // class Studscanvas
Ur klassen Studscanvas, från programmet Studsboll4. Filen Studscanvas.java:
1 private void process_keys() { 2 int keys = getKeyStates(); 3 // System.out.println("keys = " + keys); 4 if ((keys & LEFT_PRESSED) != 0) { 5 System.out.println("Pressed left!"); 6 ball_dx -= 1; 7 } 8 if ((keys & RIGHT_PRESSED) != 0) { 9 System.out.println("Pressed right!"); 10 ball_dx += 1; 11 } 12 if ((keys & UP_PRESSED) != 0) { 13 System.out.println("Pressed up!"); 14 ball_dy -= 1; 15 } 16 if ((keys & DOWN_PRESSED) != 0) { 17 System.out.println("Pressed down!"); 18 ball_dy += 1; 19 } 20 if ((keys & FIRE_PRESSED) != 0) { 21 System.out.println("Pressed FIRE!"); 22 ball_dx = 0; 23 ball_dy = 0; 24 } 25 }
1 public void showNotify() { 2 the_timer = new Timer(); 3 g = getGraphics(); 4 TimerTask task = new TimerTask() { 5 public void run() { 6 process_keys(); 7 update_game_state(); 8 render(); 9 flushGraphics(); 10 } 11 }; 12 the_timer.schedule(task, 0, 20); 13 }
Se även: http://devlinslab.blogspot.com/2007/10/input-handling-keypress-with-repeat.html
1 // Studscanvas.java 2 3 import java.util.*; 4 import javax.microedition.lcdui.*; 5 import javax.microedition.lcdui.game.*; 6 7 public class Studscanvas extends GameCanvas { 8 int ball_radius; 9 double ball_x, ball_y, ball_dx, ball_dy; 10 Timer the_timer; 11 Graphics g; 12 13 // Key repeat rate in milliseconds 14 public static final int KEY_REPEAT_RATE = 250; 15 16 // Key constants 17 public static final int MY_UP_KEY = 0; 18 public static final int MY_LEFT_KEY = 1; 19 public static final int MY_DOWN_KEY = 2; 20 public static final int MY_RIGHT_KEY = 3; 21 public static final int MY_FIRE_KEY = 4; 22 23 // Key states for up, left, down, right, and fire key 24 private boolean[] key_is_down = { 25 false, false, false, false, false 26 }; 27 28 // The last time each key changed state 29 private long[] last_key_time = { 30 0, 0, 0, 0, 0 31 }; 32 33 // Lookup table for key constants 34 private int[] key_value = { 35 GameCanvas.UP_PRESSED, 36 GameCanvas.LEFT_PRESSED, 37 GameCanvas.DOWN_PRESSED, 38 GameCanvas.RIGHT_PRESSED, 39 GameCanvas.FIRE_PRESSED 40 }; ... 75 private void process_keys() { 76 int keys = getKeyStates(); 77 long current_time = System.currentTimeMillis(); 78 79 // Loop through the keys 80 for (int i = 0; i < 5; i++){ 81 82 // By default, the key is not pressed 83 key_is_down[i] = false; 84 85 // Is the user pressing this key? 86 if ((keys & key_value[i]) != 0) { 87 long elapsed_time = current_time - last_key_time[i]; 88 89 // Is it time to toggle the key state? 90 if (elapsed_time >= KEY_REPEAT_RATE) { 91 92 // Save the current time 93 last_key_time[i] = current_time; 94 95 // Toggle the state to "down" 96 key_is_down[i] = true; 97 } 98 } 99 } 100 101 if (key_is_down[MY_LEFT_KEY]) { 102 System.out.println("Pressed left!"); 103 ball_dx -= 1; 104 } 105 if (key_is_down[MY_RIGHT_KEY]) { 106 System.out.println("Pressed right!"); 107 ball_dx += 1; 108 } 109 if (key_is_down[MY_UP_KEY]) { 110 System.out.println("Pressed up!"); 111 ball_dy -= 1; 112 } 113 if (key_is_down[MY_DOWN_KEY]) { 114 System.out.println("Pressed down!"); 115 ball_dy += 1; 116 } 117 if (key_is_down[MY_FIRE_KEY]) { 118 System.out.println("Pressed FIRE!"); 119 ball_dx = 0; 120 ball_dy = 0; 121 } 122 123 } ...
Nu provar vi med keyPressed med flera.
Klassen Studscanvas, från programmet Studsboll6. Ur filen Studscanvas.java:
1 protected void keyPressed(int keyCode) { 2 System.out.println("keyPressed, keyCode = " + keyCode); 3 int game_action = getGameAction(keyCode); 4 System.out.println("keyPressed, game_action = " + game_action); 5 6 switch (game_action) { 7 case UP: ball_dy -= 1; break; 8 case DOWN: ball_dy += 1; break; 9 case LEFT: ball_dx -= 1; break; 10 case RIGHT: ball_dx += 1; break; 11 case FIRE: ball_dx = 0; ball_dy = 0; break; 12 } 13 } 14 15 protected void keyRepeated(int keyCode) { 16 System.out.println("keyRepeated, keyCode = " + keyCode); 17 keyPressed(keyCode); 18 } 19 20 protected void keyReleased(int keyCode) { 21 System.out.println("keyReleased, keyCode = " + keyCode); 22 }
I den gamla kursboken Beginning J2ME kan man läsa kapitel 14, The Game API.
Föregående lektion | Lektionslista | Nästa lektion