TDDE0 m.fl. Objektorienterad programmering i Java Föreläsning 9 Erik Nilsson, Institutionen för Datavetenskap, LiU På denna föreläsning: Projekt Omfattning, Upplägg Kravspecifikation Tips & Trix Spel-loop Buffra bilder Kollisionsdetektering
Projekt Upplägg Fö Fö KS godkänd Redovisning v7 Börja skriv KS Deadline KS v8 v9 v0 Börja koda Handeldning vid behov! Deadline Reflektion 2
Projekt (2) Omfattning Ett arkadspel skall göras! Spelare mot spelet Grafiskt gränssnitt som styrs med tangentbord och mus. Flera banor, fiender, powerups o.s.v. Meny, med bl.a. highscore. (d.v.s. poäng) 3
Projekt (3) Resurser Grupper om 2 (samma som laborationerna) Handledare finns att tillgå Knappt 3 veckor kalendertid. Två föreläsningar, (Krav, Tips, Versionshantering) En lektion (OOA-workshop) Projektpass i datorsalarna (ej handledare). GitLab Projektet är i stort sett helt självständigt arbete. 4
Projekt(4) Exempel 5 Robotron, Missle Command, m.fl.
Projekt (5) Övriga krav (icke-funktionella) Skall vara skrivet i Java. Får använda annat grafiskt lib än Swing, men då kan man inte förvänta sig hjälp med det. Skall versionshanteras med git/gitlab Handledaren skall bjudas in till projektet. Åtminstone 2 moduler (paket). Lämpligt att dela på grafik och logik. Javadoc skall finnas på klasser (endast kort beskrivning av vad klassen representerar krävs). 6
Projekt (6) Redovisning Godkänd kravspec. Godkänd muntlig demo vid redovisningstillfället. Kraven uppfyllda. Koden OK. Godkänt reflektionsdokument ( per grupp). 2-3 A4 om ert lärande under projektet. Översiktligt klassdiagram. 7
Kravspecifikation Vad som skall ingå: Er vision, d.v.s. en löpande text om hur spelet skall vara. Ca A4 text. En eller flera bilder (skisser) över hur spelet ser ut när man spelar, med förklarande texter. Helt OK att rita detta för hand. En tabell över konkreta, funktionella krav. Ca 5-25 st är rimligt. Skickas som PDF till handledaren senast kl 7.00 måndagen den 20:e februari Handledaren ger er svar senast nästa dag. När kravspecen är godkänd så kan ni börja koda! 8
Kravspecifikation (2) Hur är en kravspec för mjukvara? Fokus för detta projekt. Beskriver funktionaliteten. Vad programmet skall göra. Beskriver gränssnitt(en). Hur programmet interagerar med omvärlden (människor såväl som andra system). Beskriver andra attribut, t.ex. Portabilitet, hållbarhet, säkerhet, o.s.v. Andra begränsningar för systemet, t.ex. Implementationsspråk, resursbegränsning, o.s.v. Går inte in på design eller implementationsdetaljer! 9 IEEE Std 830-998: Recommended Practice for System Requirements Specifications
Kravspecifikation (3) Vilka krav behövs? Kraven arbetas fram tillsammans med kund och andra intressenter. Ofta används use-cases och scenarion även här, för att kunna identifiera systemets viktiga delar. I detta fall agerar ni både kund och utvecklare. Ni får alltså själva komma fram till vilka krav som behövs! Tips: Använd er vision och era skisser. Se även mini-kraven på kurshemsidan. Vi (handledare, examinator) finns med som yttre intressenter. 0 IEEE Std 830-998: Recommended Practice for System Requirements Specifications
Kravspecifikation (4) Hur skriver man ett krav? Det finns vissa karaktäristika som är viktiga för krav. Ett krav skall vara: Korrekt Om kravet inte skall gälla för programmet så är det inte korrekt. Icke tvetydigt Ett krav får inte ha flera tolkningar. Termer kan behöva definieras i en ordlista. Verifierbart Det måste gå att avgöra om kravet är uppfyllt. Spårbart Konsistent Ett krav får inte motsäga ett annat krav, eller andra delar av kravspecen (t.ex visionen, skissen). Rankat Vissa krav är viktigare än andra. Alla krav bör ha något mått så att man vet vad som bör prioriteras. IEEE Std 830-998: Recommended Practice for System Requirements Specifications Vi måste kunna referera till ett krav. Själva texten i ett krav kan ju ändras. Görs lättast med nummer. Icke redundant Om ett krav överlappar med ett annat kan detta leda till fel senare...
Kravspecifikation (5) Ev. redundant Det skall finnas åtta olika former i spelet. Spelaren skall kunna rotera en form genom att trycka på en tangent. Spelet skall visa upp spelarens nuvarande poäng. Spelet skall visa vilken av de sju formerna som kommer härnäst. Formerna skall dyka upp i spelets underkant och röra sig nedåt. När en rad är komplett så skall den försvinna och spelaren får poäng för den. Former kan roteras med mellanslag så länge de inte har landat. Spelets grafiska design skall vara snygg och användarvänlig. Ej konsistent Tvetydigt Vad är komplett? Vad är en rad? Ej spårbara Ej verifierbart Vad är snyggt? Vad är användarvänligt? Ej korrekt Ej rankade 2 IEEE Std 830-998: Recommended Practice for System Requirements Specifications
Kravspecifikation (6) ID 2 3 Ev. redundant 4 5 6 7 8 Beskrivning. Det skall finnas åtta sju olika former i spelet. Spelaren skall kunna rotera en form genom att trycka på en tangent. Spelet skall visa upp spelarens nuvarande poäng. Spelet skall visa vilken av de sju formerna som kommer härnäst. Formerna skall dyka upp i spelets underkant överkant och röra sig nedåt. När en rad är komplett så skall den försvinna och Se definitionerna för rad och spelaren får poäng för den. komplett i ordlistan. Former kan roteras med mellanslag så länge de inte har landat. Spelets grafiska design skall vara snygg och användarvänlig. Varje form skall ha en egen färg. Minst innebär viktigast Prio 2 2 Ej konsistent Tvetydigt Vad är komplett? Vad är en rad? Ej spårbara Ej verifierbart Vad är snyggt? Vad är användarvänligt? Ej korrekt Ej rankade 3 IEEE Std 830-998: Recommended Practice for System Requirements Specifications
Kravspecifikation (6) ID 2 3 4 5 6 7 8 Beskrivning. Det skall finnas åtta sju olika former i spelet. Spelaren skall kunna rotera en form genom att trycka på en tangent. Spelet skall visa upp spelarens nuvarande poäng. Spelet skall visa vilken av de sju formerna som kommer härnäst. Formerna skall dyka upp i spelets underkant överkant och röra sig nedåt. När en rad är komplett så skall den försvinna och Se definitionerna för rad och spelaren får poäng för den. komplett i ordlistan. Former kan roteras med mellanslag så länge de inte har landat. Spelets grafiska design skall vara snygg och användarvänlig. Varje form skall ha en egen färg. Minst innebär viktigast Prio 2 2 4 IEEE Std 830-998: Recommended Practice for System Requirements Specifications
Kravspecifikation (7) Övriga tips Låt åtminstone 3 av era krav vara lägre prioriterade så att ni har några extra saker att göra om ni blir klara tidigt. Om ni inte hinner med dessa så är det inte hela världen. Ni behöver inte fler än 3 prio-nivåer. Välj något välkänt spel och gör er egen variant av det. Ni hinner troligtvis inte att både designa ett nytt spel och implementera det. 5
Tips! Ritprogrammet (lab 3) är ju nästan ett spel... Ni kan säkert återanvända en del kod, eller åtminstone idéer från lab 3. Även här: jobba objektorienterat! Ni kommer säkert behöva ändra mycket i koden medans ni jobbar. Använd det ni har lärt er! D.v.s. klasshirarkier, polymorfi, abstrakta klasser, inkapsling. 6
Spel-Loop De allra flesta spel har någon form av spel-loop. Generell form: while (speletejslut) { hanteraindata(); // t.ex. mus, tangentbord uppdateramodell(); // Alla objekt uppdateras ritautallt(); // Uppdateringarna visas för // spelaren väntaenkortstund(20ms); } 7
Spel-Loop (2) De allra flesta spel har någon form av spel-loop. Generell form: while (speletejslut) { hanteraindata(); uppdateramodell(); ritautallt(); } T.ex. Thread.sleep(20); väntaenkortstund(20ms); Med swing behövs ev. inte denna, då indata kan hanteras av lyssnare och händelser. Modellen går igenom alla sina objekt och talar om för dem att uppdatera sig själva. Ex: for (ModelObject mo : modelobjects) { mo.updateyourself(this); } T.ex. repaint() eller paintimmediately() på GUIt Tips: Anropa Toolkit.getDefaultToolkit().sync(); direkt efter utritning om spelet verkar hacka. (Kan dock bero på annat också). 8
Spel-Loop (3) Thread.sleep() kan variera ett par ms. Uppdatering av model, kan också ta variabel tid. Egentligen bör man mäta hur lång tid varje del i spelloopen tar. Kan göras med System.currentTimeMillis() Därefter räknar man ut hur lång tid man skall vänta. Uppdatering av modellen bör då bero av tiden som gått sedan föregående uppdatering. 9
Spel-Loop (4) En annan approach är att låta uppdateringen också vara en händelse. I Swing finns en timer-klass just för detta ändamål! Timer t = new Timer(20, new ActionListener() { public void actionperformed(actionevent e) { uppdateramodell(); ritautallt(); Toolkit.getDefaultToolkit().sync(); } }); t.start(); 20
Buffra bilder Ni kommer säkert att vilja ha bilder, s.k. sprites i ert spel. Enklast är det nog att låta objekten själva rita ut dessa bilder: public void paintyourself(graphics g) { BufferedImage im = ImageIO.read( new File( sprites/bad.png )); g.drawimage(x, y, im, null); } Men vad händer när vi har många objekt? Alla dessa skall läsa filen varje gång spelet skall ritas ut. Även en liten bild kan då ta tid. 2
Buffra bilder (2) Lösning : Spara bilden som en klassvariabel. private static BufferedImage image = null; private static BufferedImage getimage() { if (image == null) { ImageIO.read(new File( sprites/bad.png )); } return image; } public void paintyourself(graphics g) { g.drawimage(x, y, getimage(), null); } 22
Buffra bilder (3) Lösning 2: Spara alla bilder i en separat managerklass. Den klassen ansvararför att bilder läses in enn gång. public void paintyourself(graphics g) { g.drawimage(x, y, SpriteManager.getImage( bad.png ), null); } 23
Buffra bilder (4) Andra tips om sprites Graphics-objektet kan rita ut bara en del av en bild. Kan vara praktiskt att använda sprite maps. Animationer kan vara en sprite map, där man tickar fram mellan bilderna. Graphics kan hantera transparens i bilder. 24
Kollisioner Ni kommer troligtvis behöva en del klasser för att sköta geometri i ert program. T.ex., hur vet vi om skeppet kolliderat med asteroiden? Finns många bra klasser i java.awt och java.awt.geom T.ex. Point2D.Double, för att hantera punkter i planet. Dimension, för att hantera storlek (bredd, höjd) Rectangle, för att representera en rektangel. 25 Line2D, för att representera en linje.
Kollisioner (2) Lösning : Se objekten som rektanglar och kolla om dessa överlappar. rect rect2 Rectangle rect = new Rectangle(ship.getX(), ship.gety(), ship.getwidth(), ship.getheight()); Rectangle rect2 = new Rectangle(rock.getX(), rock.gety(), rock.getwidth(), rock.getheight()); if (rect.intersects(rect2)) { // objekten har kolliderat! } 26
Kollisioner (3) Finns även funktion för att se om en sträcka beskär en rektangel. rect2 (Xb, Yb) (Xa, Ya) Rectangle rect2 = new Rectangle(rock.getX(), rock.gety(), rock.getwidth(), rock.getheight()); Line2D line = new Line2D(Xa, Ya, Xb, Yb); if (rect.intersects(line)) { // linjen beskär rektangeln. } 27
Concurrent Modification Antag att vi i modellen (GameModel) har följande någonstans i en metod: for (GameObject obj : allobjects) { obj.doyourstuff(this); } Och att vi även har denna metod i GameModel: public List<GameObject> getallobjects() { return allobjects; } Vad händer om vi i doyourstuff gör detta: 28 gamemodel.getallobjects().remove(...)
Concurrent Modification (2) Vi ändrar ju på en lista medans vi itererar igenom den Vägar runt detta: Markera objekt för borttagning. Samla objekt som skall tas bort I en skräplista, och ta bort dem efter. I båda dessa fall, ta bort elementen efter for-eachloopen. 29